Files
create/src/Gui/WorkbenchSelector.cpp
Zheng Lei b00a4384bf Gui: support toolbar drag and drop to status bar and menu bar (#13571)
* Gui: support toolbar drag and drop to status bar and menu bar

Closes FreeCAD/FreeCAD#12979

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Gui: improve toolbar handling in status and menu bar

* Gui: fix workbench tab bar orientation in status or menu bar

* Gui: remove workbench toolbar position settings

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2024-05-06 17:59:16 +02:00

266 lines
9.3 KiB
C++

/***************************************************************************
* Copyright (c) 2024 Pierre-Louis Boyer <development[at]Ondsel.com> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <QAbstractItemView>
# include <QActionGroup>
# include <QApplication>
# include <QMenuBar>
# include <QScreen>
# include <QStatusBar>
# include <QToolBar>
#endif
#include "Action.h"
#include "BitmapFactory.h"
#include "Command.h"
#include "PreferencePages/DlgSettingsWorkbenchesImp.h"
#include "DlgPreferencesImp.h"
#include "MainWindow.h"
#include "WorkbenchManager.h"
#include "WorkbenchSelector.h"
using namespace Gui;
WorkbenchComboBox::WorkbenchComboBox(WorkbenchGroup* aGroup, QWidget* parent) : QComboBox(parent)
{
setIconSize(QSize(16, 16));
setToolTip(aGroup->toolTip());
setStatusTip(aGroup->action()->statusTip());
setWhatsThis(aGroup->action()->whatsThis());
refreshList(aGroup->getEnabledWbActions());
connect(aGroup, &WorkbenchGroup::workbenchListRefreshed, this, &WorkbenchComboBox::refreshList);
connect(aGroup->groupAction(), &QActionGroup::triggered, this, [this, aGroup](QAction* action) {
setCurrentIndex(aGroup->actions().indexOf(action));
});
connect(this, qOverload<int>(&WorkbenchComboBox::activated), aGroup, [aGroup](int index) {
aGroup->actions()[index]->trigger();
});
}
void WorkbenchComboBox::showPopup()
{
int rows = count();
if (rows > 0) {
int height = view()->sizeHintForRow(0);
int maxHeight = QApplication::primaryScreen()->size().height();
view()->setMinimumHeight(qMin(height * rows, maxHeight/2));
}
QComboBox::showPopup();
}
void WorkbenchComboBox::refreshList(QList<QAction*> actionList)
{
clear();
ParameterGrp::handle hGrp;
hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Workbenches");
int itemStyleIndex = hGrp->GetInt("WorkbenchSelectorItem", 0);
for (QAction* action : actionList) {
QIcon icon = action->icon();
if (icon.isNull() || itemStyleIndex == 2) {
addItem(action->text());
}
else if (itemStyleIndex == 1) {
addItem(icon, QString::fromLatin1(""));
}
else {
addItem(icon, action->text());
}
if (action->isChecked()) {
this->setCurrentIndex(this->count() - 1);
}
}
}
WorkbenchTabWidget::WorkbenchTabWidget(WorkbenchGroup* aGroup, QWidget* parent)
: QTabBar(parent)
, wbActionGroup(aGroup)
{
setToolTip(aGroup->toolTip());
setStatusTip(aGroup->action()->statusTip());
setWhatsThis(aGroup->action()->whatsThis());
QAction* moreAction = new QAction(this);
menu = new QMenu(this);
moreAction->setMenu(menu);
connect(moreAction, &QAction::triggered, [this]() {
menu->popup(QCursor::pos());
});
connect(menu, &QMenu::aboutToHide, this, [this]() {
// if the more tab did not triggered a disabled workbench, make sure we reselect the correct tab.
std::string activeWbName = WorkbenchManager::instance()->activeName();
for (int i = 0; i < count(); ++i) {
if (wbActionGroup->actions()[i]->objectName().toStdString() == activeWbName) {
setCurrentIndex(i + 1);
break;
}
}
});
if (parent->inherits("QToolBar")) {
// set the initial orientation. We cannot do updateLayoutAndTabOrientation(false);
// because on init the toolbar area is always TopToolBarArea.
ParameterGrp::handle hGrp;
hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Workbenches");
std::string orientation = hGrp->GetASCII("TabBarOrientation", "North");
this->setShape(orientation == "North" ? QTabBar::RoundedNorth :
orientation == "South" ? QTabBar::RoundedSouth :
orientation == "East" ? QTabBar::RoundedEast :
QTabBar::RoundedWest);
}
setDocumentMode(true);
setUsesScrollButtons(true);
setDrawBase(true);
setObjectName(QString::fromLatin1("WbTabBar"));
setIconSize(QSize(16, 16));
refreshList(aGroup->getEnabledWbActions());
connect(aGroup, &WorkbenchGroup::workbenchListRefreshed, this, &WorkbenchTabWidget::refreshList);
connect(aGroup->groupAction(), &QActionGroup::triggered, this, [this, aGroup](QAction* action) {
int index = aGroup->actions().indexOf(action) + 1;
if (index > this->count() - 1) {
index = 0;
}
setCurrentIndex(index);
});
connect(this, qOverload<int>(&QTabBar::tabBarClicked), aGroup, [aGroup, moreAction](int index) {
if(index == 0) {
moreAction->trigger();
}
else if (index <= aGroup->getEnabledWbActions().size()) {
aGroup->actions()[index - 1]->trigger();
}
});
if (parent->inherits("QToolBar")) {
// Connect toolbar orientation changed
QToolBar* tb = qobject_cast<QToolBar*>(parent);
connect(tb, &QToolBar::topLevelChanged, this, &WorkbenchTabWidget::updateLayoutAndTabOrientation);
}
}
void WorkbenchTabWidget::refreshList(QList<QAction*> actionList)
{
// tabs->clear() (QTabBar has no clear)
for (int i = count() - 1; i >= 0; --i) {
removeTab(i);
}
ParameterGrp::handle hGrp;
hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Workbenches");
int itemStyleIndex = hGrp->GetInt("WorkbenchSelectorItem", 0);
QIcon icon = Gui::BitmapFactory().iconFromTheme("list-add");
if (itemStyleIndex == 2) {
addTab(QString::fromLatin1("+"));
}
else {
addTab(icon, QString::fromLatin1(""));
}
for (QAction* action : actionList) {
QIcon icon = action->icon();
if (icon.isNull() || itemStyleIndex == 2) {
addTab(action->text());
}
else if (itemStyleIndex == 1) {
addTab(icon, QString::fromLatin1(""));
}
else {
addTab(icon, action->text());
}
if (action->isChecked()) {
setCurrentIndex(count() - 1);
}
}
buildPrefMenu();
}
void WorkbenchTabWidget::updateLayoutAndTabOrientation(bool floating)
{
auto parent = parentWidget();
if (!parent || !parent->inherits("QToolBar")) {
return;
}
ParameterGrp::handle hGrp = App::GetApplication()
.GetParameterGroupByPath("User parameter:BaseApp/Preferences/Workbenches");
Qt::ToolBarArea area;
parent = parent->parentWidget();
if (floating) {
area = Qt::TopToolBarArea;
}
else if (parent && parent->parentWidget() == getMainWindow()->statusBar()) {
area = Qt::BottomToolBarArea;
}
else if (parent && parent->parentWidget() == getMainWindow()->menuBar()) {
area = Qt::TopToolBarArea;
}
else {
QToolBar* tb = qobject_cast<QToolBar*>(parentWidget());
area = getMainWindow()->toolBarArea(tb);
}
if (area == Qt::LeftToolBarArea || area == Qt::RightToolBarArea) {
setShape(area == Qt::LeftToolBarArea ? QTabBar::RoundedWest : QTabBar::RoundedEast);
hGrp->SetASCII("TabBarOrientation", area == Qt::LeftToolBarArea ? "West" : "East");
}
else {
setShape(area == Qt::TopToolBarArea ? QTabBar::RoundedNorth : QTabBar::RoundedSouth);
hGrp->SetASCII("TabBarOrientation", area == Qt::TopToolBarArea ? "North" : "South");
}
}
void WorkbenchTabWidget::buildPrefMenu()
{
menu->clear();
// Add disabled workbenches, sorted alphabetically.
menu->addActions(wbActionGroup->getDisabledWbActions());
menu->addSeparator();
QAction* preferencesAction = menu->addAction(tr("Preferences"));
connect(preferencesAction, &QAction::triggered, this, []() {
Gui::Dialog::DlgPreferencesImp cDlg(getMainWindow());
cDlg.activateGroupPage(QString::fromUtf8("Workbenches"), 0);
cDlg.exec();
});
}
#include "moc_WorkbenchSelector.cpp"