From 3684dc65604b5ee36e9cfcacf39caf8b343af6cf Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Sun, 9 Jun 2024 20:18:15 +0200 Subject: [PATCH] Gui: Display workbench icon in the middle for icon-only It ensures that for icon-only style it is displayed in the middle and empty text is not accounted while calculating tab size hint. Custom styles may need to target `QTabBar[style="icon-only"]` to apply specific fixes like disabling padding. Fixes: #14282 --- src/Gui/WorkbenchSelector.cpp | 16 +++++--- src/Gui/WorkbenchSelector.h | 71 ++++++++++++++++++++++++++++++++--- 2 files changed, 75 insertions(+), 12 deletions(-) diff --git a/src/Gui/WorkbenchSelector.cpp b/src/Gui/WorkbenchSelector.cpp index 173c5cbbc3..4d8ca65dd3 100644 --- a/src/Gui/WorkbenchSelector.cpp +++ b/src/Gui/WorkbenchSelector.cpp @@ -102,7 +102,6 @@ void WorkbenchComboBox::refreshList(QList actionList) } } - WorkbenchTabWidget::WorkbenchTabWidget(WorkbenchGroup* aGroup, QWidget* parent) : QWidget(parent) , wbActionGroup(aGroup) @@ -112,7 +111,7 @@ WorkbenchTabWidget::WorkbenchTabWidget(WorkbenchGroup* aGroup, QWidget* parent) setWhatsThis(aGroup->action()->whatsThis()); setObjectName(QString::fromLatin1("WbTabBar")); - tabBar = new QTabBar(this); + tabBar = new WbTabBar(this); moreButton = new QToolButton(this); layout = new QBoxLayout(QBoxLayout::LeftToRight, this); @@ -205,6 +204,12 @@ int WorkbenchTabWidget::tabIndexForWorkbenchActivateAction(QAction* workbenchAct return actionToTabIndex.at(workbenchActivateAction); } +WorkbenchItemStyle Gui::WorkbenchTabWidget::itemStyle() const +{ + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Workbenches"); + return static_cast(hGrp->GetInt("WorkbenchSelectorItem", 0)); +} + void WorkbenchTabWidget::updateLayout() { if (!parentWidget()) { @@ -293,6 +298,8 @@ void WorkbenchTabWidget::updateWorkbenchList() return; } + tabBar->setItemStyle(itemStyle()); + // As clearing and adding tabs can cause changing current tab in QTabBar. // This in turn will cause workbench to change, so we need to prevent // processing of such events until the QTabBar is fully prepared. @@ -320,8 +327,7 @@ void WorkbenchTabWidget::updateWorkbenchList() int WorkbenchTabWidget::addWorkbenchTab(QAction* action, int tabIndex) { - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Workbenches"); - auto itemStyle = static_cast(hGrp->GetInt("WorkbenchSelectorItem", 0)); + auto itemStyle = this->itemStyle(); // if tabIndex is negative we assume that tab must be placed at the end of tabBar (default behavior) if (tabIndex < 0) { @@ -422,5 +428,3 @@ void WorkbenchTabWidget::adjustSize() parentWidget()->adjustSize(); } - -#include "moc_WorkbenchSelector.cpp" diff --git a/src/Gui/WorkbenchSelector.h b/src/Gui/WorkbenchSelector.h index b60724fd9b..272a8b8a2a 100644 --- a/src/Gui/WorkbenchSelector.h +++ b/src/Gui/WorkbenchSelector.h @@ -64,13 +64,61 @@ class GuiExport WorkbenchTabWidget : public QWidget Q_OBJECT Q_PROPERTY(Qt::LayoutDirection direction READ direction WRITE setDirection NOTIFY directionChanged) - int addWorkbenchTab(QAction* workbenchActivateAction, int index = -1); + class WbTabBar : public QTabBar { + public: + explicit WbTabBar(QWidget* parent) : QTabBar(parent) {} - void setTemporaryWorkbenchTab(QAction* workbenchActivateAction); - int temporaryWorkbenchTabIndex() const; + QSize tabSizeHint(int index) const override { + auto sizeFromParent = QTabBar::tabSizeHint(index); - QAction* workbenchActivateActionByTabIndex(int tabIndex) const; - int tabIndexForWorkbenchActivateAction(QAction* workbenchActivateAction) const; + if (itemStyle() != IconOnly) { + return sizeFromParent; + } + + QStyleOptionTab opt; + + initStyleOption(&opt, index); + + int padding = style()->pixelMetric(QStyle::PM_TabBarTabHSpace, &opt, this); + + auto csz = iconSize(); + auto isHorizontal = opt.shape == RoundedNorth || opt.shape == RoundedSouth; + + if (isHorizontal) { + csz.setWidth(csz.width() + padding); + } else { + csz.setHeight(csz.height() + padding); + } + + auto size = style()->sizeFromContents(QStyle::CT_TabBarTab, &opt, csz, this); + + if (isHorizontal) { + size.setHeight(sizeFromParent.height()); + } else { + size.setWidth(sizeFromParent.width()); + } + + return size; + } + + WorkbenchItemStyle itemStyle() const { return _itemStyle; } + void setItemStyle(WorkbenchItemStyle itemStyle) { + _itemStyle = itemStyle; + setProperty("style", QString::fromUtf8(workbenchItemStyleToString(itemStyle))); + } + + private: + WorkbenchItemStyle _itemStyle; + + static const char* workbenchItemStyleToString(WorkbenchItemStyle style) + { + switch (style) { + case IconAndText: return "icon-and-text"; + case IconOnly: return "icon-only"; + case TextOnly: return "text-only"; + } + } + }; public: explicit WorkbenchTabWidget(WorkbenchGroup* aGroup, QWidget* parent = nullptr); @@ -93,12 +141,23 @@ public Q_SLOTS: Q_SIGNALS: void directionChanged(const Qt::LayoutDirection&); +protected: + int addWorkbenchTab(QAction* workbenchActivateAction, int index = -1); + + void setTemporaryWorkbenchTab(QAction* workbenchActivateAction); + int temporaryWorkbenchTabIndex() const; + + QAction* workbenchActivateActionByTabIndex(int tabIndex) const; + int tabIndexForWorkbenchActivateAction(QAction* workbenchActivateAction) const; + + WorkbenchItemStyle itemStyle() const; + private: bool isInitializing = false; WorkbenchGroup* wbActionGroup; QToolButton* moreButton; - QTabBar* tabBar; + WbTabBar* tabBar; QBoxLayout* layout; Qt::LayoutDirection _direction = Qt::LeftToRight;