From 3405939f102af87c3b690801d407bcb9fc2ceae2 Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Mon, 29 Apr 2024 23:17:04 +0200 Subject: [PATCH] Gui: Move more button to the end WB TabBar This changes back placement of the "more" button of the WB TabBar to be at the end, where it should be naturally placed. In order to ensure that it is always visible the control was reworked to show this button always after the tab bar widget which now is dynamically sized. This is behavior that is well known from browsers. This commit also ensures that active workbench is always visible in the TabBar by adding additional temporary tab when necessary. This tab will automatically dissapear when not needed. Fixes: #13720 Fixes: #13630 --- src/Gui/WorkbenchSelector.cpp | 150 ++++++++++++++++++++-------------- src/Gui/WorkbenchSelector.h | 13 ++- 2 files changed, 101 insertions(+), 62 deletions(-) diff --git a/src/Gui/WorkbenchSelector.cpp b/src/Gui/WorkbenchSelector.cpp index 6ef25ce62e..252cd19e5a 100644 --- a/src/Gui/WorkbenchSelector.cpp +++ b/src/Gui/WorkbenchSelector.cpp @@ -31,6 +31,7 @@ # include # include # include +# include #endif #include "Action.h" @@ -101,29 +102,30 @@ void WorkbenchComboBox::refreshList(QList actionList) WorkbenchTabWidget::WorkbenchTabWidget(WorkbenchGroup* aGroup, QWidget* parent) - : QTabBar(parent) + : QWidget(parent) , wbActionGroup(aGroup) { setToolTip(aGroup->toolTip()); setStatusTip(aGroup->action()->statusTip()); setWhatsThis(aGroup->action()->whatsThis()); + setObjectName(QString::fromLatin1("WbTabBar")); - 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; - } - } - }); + tabBar = new QTabBar(this); + moreButton = new QToolButton(this); + + auto layout = new QHBoxLayout(this); + + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(tabBar); + layout->addWidget(moreButton); + + setLayout(layout); + + moreButton->setIcon(Gui::BitmapFactory().iconFromTheme("list-add")); + moreButton->setToolButtonStyle(Qt::ToolButtonIconOnly); + moreButton->setPopupMode(QToolButton::InstantPopup); + moreButton->setMenu(new QMenu(moreButton)); + moreButton->setObjectName(QString::fromLatin1("WbTabBarMore")); if (parent->inherits("QToolBar")) { // set the initial orientation. We cannot do updateLayoutAndTabOrientation(false); @@ -132,33 +134,47 @@ WorkbenchTabWidget::WorkbenchTabWidget(WorkbenchGroup* aGroup, QWidget* parent) hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Workbenches"); std::string orientation = hGrp->GetASCII("TabBarOrientation", "North"); - this->setShape(orientation == "North" ? QTabBar::RoundedNorth : + tabBar->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)); + tabBar->setDocumentMode(true); + tabBar->setUsesScrollButtons(true); + tabBar->setDrawBase(true); + tabBar->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; + connect(aGroup->groupAction(), &QActionGroup::triggered, this, [this](QAction* action) { + if (wbActionGroup->getDisabledWbActions().contains(action)) { + if (additionalWorkbenchAction == action) { + return; + } + + if (additionalWorkbenchAction) { + tabBar->removeTab(tabBar->count() - 1); + } + + additionalWorkbenchAction = action; + + addWorkbenchTab(action); + tabBar->setCurrentIndex(tabBar->count() - 1); + + return; } - setCurrentIndex(index); + + tabBar->setCurrentIndex(actionToTabIndex[action]); }); - connect(this, qOverload(&QTabBar::tabBarClicked), aGroup, [aGroup, moreAction](int index) { - if(index == 0) { - moreAction->trigger(); - } - else if (index <= aGroup->getEnabledWbActions().size()) { - aGroup->actions()[index - 1]->trigger(); + + connect(tabBar, qOverload(&QTabBar::currentChanged), aGroup, [this](int index) { + tabIndexToAction[index]->trigger(); + + if (index != tabBar->count() - 1 && additionalWorkbenchAction) { + tabBar->removeTab(tabBar->count() - 1); + additionalWorkbenchAction = nullptr; } }); @@ -171,41 +187,47 @@ WorkbenchTabWidget::WorkbenchTabWidget(WorkbenchGroup* aGroup, QWidget* parent) void WorkbenchTabWidget::refreshList(QList actionList) { + actionToTabIndex.clear(); + // tabs->clear() (QTabBar has no clear) - for (int i = count() - 1; i >= 0; --i) { - removeTab(i); + for (int i = tabBar->count() - 1; i >= 0; --i) { + tabBar->removeTab(i); } + for (QAction* action : actionList) { + addWorkbenchTab(action); + } + + if (additionalWorkbenchAction != nullptr) { + addWorkbenchTab(additionalWorkbenchAction); + } + + buildPrefMenu(); +} + +void WorkbenchTabWidget::addWorkbenchTab(QAction* action) +{ 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("+")); + actionToTabIndex[action] = tabBar->count(); + tabIndexToAction[tabBar->count()] = action; + + QIcon icon = action->icon(); + if (icon.isNull() || itemStyleIndex == 2) { + tabBar->addTab(action->text()); + } + else if (itemStyleIndex == 1) { + tabBar->addTab(icon, QString::fromLatin1("")); } else { - addTab(icon, QString::fromLatin1("")); + tabBar->addTab(icon, action->text()); } - 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); - } + if (action->isChecked()) { + tabBar->setCurrentIndex(tabBar->count() - 1); } - - buildPrefMenu(); } void WorkbenchTabWidget::updateLayoutAndTabOrientation(bool floating) @@ -236,21 +258,29 @@ void WorkbenchTabWidget::updateLayoutAndTabOrientation(bool floating) } if (area == Qt::LeftToolBarArea || area == Qt::RightToolBarArea) { - setShape(area == Qt::LeftToolBarArea ? QTabBar::RoundedWest : QTabBar::RoundedEast); + tabBar->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); + tabBar->setShape(area == Qt::TopToolBarArea ? QTabBar::RoundedNorth : QTabBar::RoundedSouth); hGrp->SetASCII("TabBarOrientation", area == Qt::TopToolBarArea ? "North" : "South"); } } void WorkbenchTabWidget::buildPrefMenu() { + auto menu = moreButton->menu(); + menu->clear(); // Add disabled workbenches, sorted alphabetically. - menu->addActions(wbActionGroup->getDisabledWbActions()); + for (auto action : wbActionGroup->getDisabledWbActions()) { + if (action->text() == QString::fromLatin1("")) { + continue; + } + + menu->addAction(action); + } menu->addSeparator(); diff --git a/src/Gui/WorkbenchSelector.h b/src/Gui/WorkbenchSelector.h index f5bd696955..f29637d624 100644 --- a/src/Gui/WorkbenchSelector.h +++ b/src/Gui/WorkbenchSelector.h @@ -27,7 +27,9 @@ #include #include #include +#include #include +#include namespace Gui { @@ -49,7 +51,7 @@ private: }; -class GuiExport WorkbenchTabWidget : public QTabBar +class GuiExport WorkbenchTabWidget : public QWidget { Q_OBJECT @@ -61,10 +63,17 @@ public: public Q_SLOTS: void refreshList(QList); + void addWorkbenchTab(QAction* workbenchActivateAction); private: WorkbenchGroup* wbActionGroup; - QMenu* menu; + QToolButton* moreButton; + QTabBar* tabBar; + // this action is used for workbenches that are typically disabled + QAction* additionalWorkbenchAction = nullptr; + + std::map actionToTabIndex; + std::map tabIndexToAction; };