From 489f72aa0c21e4bc8240c387d855aaa544f38241 Mon Sep 17 00:00:00 2001 From: Syarif Fakhri Date: Mon, 12 Sep 2022 15:55:45 +0800 Subject: [PATCH] Add side tab widget icons - Add config to prioritize icon only if it has one --- src/DockAreaTitleBar.cpp | 9 ++ src/DockManager.cpp | 27 ++++ src/DockManager.h | 50 ++++++-- src/DockWidget.cpp | 1 + src/DockWidgetSideTab.cpp | 170 ++++++++++++++++++++++++- src/DockWidgetSideTab.h | 39 ++++++ src/DockWidgetTab.cpp | 4 - src/OverlayDockContainer.cpp | 2 + src/stylesheets/focus_highlighting.css | 1 + 9 files changed, 282 insertions(+), 21 deletions(-) diff --git a/src/DockAreaTitleBar.cpp b/src/DockAreaTitleBar.cpp index 16c690d..df2c66a 100644 --- a/src/DockAreaTitleBar.cpp +++ b/src/DockAreaTitleBar.cpp @@ -120,6 +120,15 @@ struct DockAreaTitleBarPrivate return CDockManager::testConfigFlag(Flag); } + /** + * Returns true if the given config flag is set + * Convenience function to ease config flag testing + */ + static bool testConfigFlag(CDockManager::eOverlayFlag Flag) + { + return CDockManager::testConfigFlag(Flag); + } + /** * Test function for current drag state */ diff --git a/src/DockManager.cpp b/src/DockManager.cpp index 66f6130..1b0c5da 100644 --- a/src/DockManager.cpp +++ b/src/DockManager.cpp @@ -92,6 +92,7 @@ enum eStateFileVersion }; static CDockManager::ConfigFlags StaticConfigFlags = CDockManager::DefaultNonOpaqueConfig; +static CDockManager::OverlayFlags StaticOverlayConfigFlags = CDockManager::DefaultAutoHideConfig; /** * Private data class of CDockManager class (pimpl) @@ -1135,6 +1136,11 @@ CDockManager::ConfigFlags CDockManager::configFlags() return StaticConfigFlags; } +CDockManager::OverlayFlags CDockManager::overlayConfigFlags() +{ + return StaticOverlayConfigFlags; +} + //=========================================================================== void CDockManager::setConfigFlags(const ConfigFlags Flags) @@ -1143,12 +1149,26 @@ void CDockManager::setConfigFlags(const ConfigFlags Flags) } +//=========================================================================== +void CDockManager::setConfigFlags(const OverlayFlags Flags) +{ + StaticOverlayConfigFlags = Flags; +} + + //=========================================================================== void CDockManager::setConfigFlag(eConfigFlag Flag, bool On) { internal::setFlag(StaticConfigFlags, Flag, On); } + +//=========================================================================== +void CDockManager::setConfigFlag(eOverlayFlag Flag, bool On) +{ + internal::setFlag(StaticOverlayConfigFlags, Flag, On); +} + //=========================================================================== bool CDockManager::testConfigFlag(eConfigFlag Flag) { @@ -1156,6 +1176,13 @@ bool CDockManager::testConfigFlag(eConfigFlag Flag) } +//=========================================================================== +bool CDockManager::testConfigFlag(eOverlayFlag Flag) +{ + return overlayConfigFlags().testFlag(Flag); +} + + //=========================================================================== CIconProvider& CDockManager::iconProvider() { diff --git a/src/DockManager.h b/src/DockManager.h index 04c8283..9cbd5ac 100644 --- a/src/DockManager.h +++ b/src/DockManager.h @@ -203,20 +203,10 @@ public: //! Users can overwrite this by setting the environment variable ADS_UseNativeTitle to "1" or "0". MiddleMouseButtonClosesTab = 0x2000000, //! If the flag is set, the user can use the mouse middle button to close the tab under the mouse - DockAreaHasAutoHideButton = 0x4000000, //!< If the flag is set each dock area has a auto hide menu button - DockContainerHasLeftSideBar = 0x8000000, //!< If the flag is set each container will have a left side bar - DockContainerHasRightSideBar = 0x10000000, //!< If the flag is set each container will have a right side bar - DockAreaOverlayHasTitle = 0x20000000, //!< If the flag is set overlay dock area title bar will show the window title - DefaultDockAreaButtons = DockAreaHasCloseButton | DockAreaHasUndockButton | DockAreaHasTabsMenuButton, ///< default configuration of dock area title bar buttons - DefaultAutoHideConfig = DockContainerHasLeftSideBar - | DockContainerHasRightSideBar - | DockAreaHasAutoHideButton - | DockAreaOverlayHasTitle, ///< the default configuration for left and right side bars - DefaultBaseConfig = DefaultDockAreaButtons | ActiveTabHasCloseButton | XmlCompressionEnabled @@ -234,6 +224,23 @@ public: }; Q_DECLARE_FLAGS(ConfigFlags, eConfigFlag) + enum eOverlayFlag + { + DockContainerHasLeftSideBar = 0x01, //!< If the flag is set left side bar will prioritize showing icons only over text + DockContainerHasRightSideBar = 0x02, //!< If the flag is set right side bar will prioritize showing icons only over text + DockAreaHasAutoHideButton = 0x04, //!< If the flag is set each dock area has a auto hide menu button + LeftSideBarPrioritizeIconOnly = 0x08, //!< If the flag is set each container will have a left side bar + RightSideBarPrioritizeIconOnly = 0x10, //!< If the flag is set each container will have a right side bar + DockAreaOverlayHasTitle = 0x20, //!< If the flag is set overlay dock area title bar will show the window title + + DefaultAutoHideConfig = DockContainerHasLeftSideBar + | DockContainerHasRightSideBar + | DockAreaHasAutoHideButton + | DockAreaOverlayHasTitle, ///< the default configuration for left and right side bars + }; + Q_DECLARE_FLAGS(OverlayFlags, eOverlayFlag) + + /** * Default Constructor. * If the given parent is a QMainWindow, the dock manager sets itself as the @@ -253,6 +260,11 @@ public: */ static ConfigFlags configFlags(); + /** + * This function returns the overlay configuration flags + */ + static OverlayFlags overlayConfigFlags(); + /** * Sets the global configuration flags for the whole docking system. * Call this function before you create the dock manager and before @@ -260,17 +272,35 @@ public: */ static void setConfigFlags(const ConfigFlags Flags); + /** + * Sets the global configuration flags for the whole docking system. + * Call this function before you create the dock manager and before + * your create the first dock widget. + */ + static void setConfigFlags(const OverlayFlags Flags); + /** * Set a certain config flag. * \see setConfigFlags() */ static void setConfigFlag(eConfigFlag Flag, bool On = true); + /** + * Set a certain overlay config flag. + * \see setConfigFlags() + */ + static void setConfigFlag(eOverlayFlag Flag, bool On = true); + /** * Returns true if the given config flag is set */ static bool testConfigFlag(eConfigFlag Flag); + /** + * Returns true if the given overlay config flag is set + */ + static bool testConfigFlag(eOverlayFlag Flag); + /** * Returns the global icon provider. * The icon provider enables the use of custom icons in case using diff --git a/src/DockWidget.cpp b/src/DockWidget.cpp index 9f7f9bf..a87ac04 100644 --- a/src/DockWidget.cpp +++ b/src/DockWidget.cpp @@ -782,6 +782,7 @@ void CDockWidget::setTabToolTip(const QString &text) void CDockWidget::setIcon(const QIcon& Icon) { d->TabWidget->setIcon(Icon); + d->SideTabWidget->setIcon(Icon); if (!d->ToggleViewAction->isCheckable()) { d->ToggleViewAction->setIcon(Icon); diff --git a/src/DockWidgetSideTab.cpp b/src/DockWidgetSideTab.cpp index 1913d8d..a3376be 100644 --- a/src/DockWidgetSideTab.cpp +++ b/src/DockWidgetSideTab.cpp @@ -33,6 +33,7 @@ #include #include "DockAreaWidget.h" +#include "DockManager.h" #include "ElidingLabel.h" #include "DockWidget.h" @@ -52,7 +53,11 @@ struct DockWidgetSideTabPrivate CDockWidget* DockWidget; tTabLabel* TitleLabel; QBoxLayout* Layout; + QBoxLayout* TitleLayout; // To have independent spacing from the icon CSideTabBar* SideTabBar; + QSize IconSize; + SideTabIconLabel* IconLabel = nullptr; + QIcon Icon; /** * Private data constructor @@ -63,8 +68,28 @@ struct DockWidgetSideTabPrivate * Creates the complete layout */ void createLayout(); -}; -// struct DockWidgetTabPrivate + + /** + * Update the icon in case the icon size changed + */ + void updateIcon() + { + if (!IconLabel || Icon.isNull()) + { + return; + } + + if (IconSize.isValid()) + { + IconLabel->setPixmap(Icon.pixmap(IconSize)); + } + else + { + IconLabel->setPixmap(Icon.pixmap(_this->style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, _this))); + } + IconLabel->setVisible(true); + } +}; // struct DockWidgetTabPrivate //============================================================================ @@ -81,19 +106,24 @@ void DockWidgetSideTabPrivate::createLayout() TitleLabel->setElideMode(Qt::ElideRight); TitleLabel->setText(DockWidget->windowTitle()); TitleLabel->setObjectName("dockWidgetTabLabel"); - TitleLabel->setAlignment(Qt::AlignCenter); + //TitleLabel->setAlignment(Qt::AlignLeft); _this->connect(TitleLabel, SIGNAL(elidedChanged(bool)), SIGNAL(elidedChanged(bool))); QFontMetrics fm(TitleLabel->font()); int Spacing = qRound(fm.height() / 2.0); // Fill the layout - Layout = new QBoxLayout(QBoxLayout::LeftToRight); - Layout->setContentsMargins(Spacing,Spacing,0,Spacing); + // Purely for spacing on the text without messing up spacing on the icon + TitleLayout = new QBoxLayout(QBoxLayout::TopToBottom); + TitleLayout->setContentsMargins(Spacing,Spacing,0,Spacing); + TitleLayout->addWidget(TitleLabel); + TitleLayout->setSpacing(0); + + Layout = new QBoxLayout(QBoxLayout::TopToBottom); + Layout->setContentsMargins(0,0,0,0); Layout->setSpacing(0); _this->setLayout(Layout); - Layout->addWidget(TitleLabel, 1); - Layout->setAlignment(Qt::AlignCenter); + Layout->addLayout(TitleLayout, 1); TitleLabel->setVisible(true); } @@ -139,18 +169,22 @@ CDockWidgetSideTab::CDockWidgetSideTab(CDockWidget* DockWidget, QWidget* parent) setFocusPolicy(Qt::NoFocus); } + //============================================================================ CDockWidgetSideTab::~CDockWidgetSideTab() { delete d; } + //============================================================================ void CDockWidgetSideTab::updateStyle() { internal::repolishStyle(this, internal::RepolishDirectChildren); } + +//============================================================================ CDockWidgetSideTab::SideTabBarArea CDockWidgetSideTab::sideTabBarArea() const { auto dockAreaWidget = d->DockWidget->dockAreaWidget(); @@ -161,4 +195,126 @@ CDockWidgetSideTab::SideTabBarArea CDockWidgetSideTab::sideTabBarArea() const return Left; } + + +//============================================================================ +void CDockWidgetSideTab::setIcon(const QIcon& Icon) +{ + QBoxLayout* Layout = qobject_cast(layout()); + if (!d->IconLabel && Icon.isNull()) + { + return; + } + + if (!d->IconLabel) + { + d->IconLabel = new SideTabIconLabel(); + internal::setToolTip(d->IconLabel, d->TitleLabel->toolTip()); + Layout->insertWidget(0, d->IconLabel, Qt::AlignHCenter); + } + else if (Icon.isNull()) + { + // Remove icon label + Layout->removeWidget(d->IconLabel); + delete d->IconLabel; + d->IconLabel = nullptr; + } + + d->Icon = Icon; + d->updateIcon(); +} + + +//============================================================================ +QSize CDockWidgetSideTab::iconSize() const +{ + return d->IconSize; +} + + +//============================================================================ +void CDockWidgetSideTab::setIconSize(const QSize& Size) +{ + d->IconSize = Size; + d->updateIcon(); +} + + +//============================================================================ +void CDockWidgetSideTab::updateTitleAndIconVisibility(SideTabBarArea area) +{ + if (d->Icon.isNull()) + { + return; + } + + QFontMetrics fm(d->TitleLabel->font()); + int Spacing = qRound(fm.height() / 2.0); + + if (CDockManager::testConfigFlag(CDockManager::LeftSideBarPrioritizeIconOnly) && area == Left + || CDockManager::testConfigFlag(CDockManager::RightSideBarPrioritizeIconOnly) && area == Right) + { + d->TitleLabel->hide(); + d->TitleLayout->setContentsMargins(0, 0, 0, 0); + d->IconLabel->setContentsMargins(Spacing / 2, Spacing / 2, Spacing / 2, Spacing / 2); + return; + } + + d->TitleLayout->setContentsMargins(Spacing, Spacing, 0, Spacing); + d->IconLabel->setContentsMargins(Spacing / 2, Spacing / 2, Spacing / 2, 0); + + d->TitleLabel->show(); +} + +/** + * Private data class of SideTabIcon class (pimpl) + */ +struct SideTabIconLabelPrivate +{ + SideTabIconLabel* _this; + QLabel* IconLabel; + QBoxLayout* Layout; + + SideTabIconLabelPrivate(SideTabIconLabel* _public); +}; // struct SideTabIconLabelPrivate + + +//============================================================================ +SideTabIconLabelPrivate::SideTabIconLabelPrivate(SideTabIconLabel* _public) : + _this(_public) +{ +} + + +//============================================================================ +SideTabIconLabel::SideTabIconLabel(QWidget* parent) : QWidget(parent), + d(new SideTabIconLabelPrivate(this)) +{ + d->Layout = new QBoxLayout(QBoxLayout::TopToBottom); + d->Layout->addWidget(d->IconLabel = new QLabel()); + d->IconLabel->setAlignment(Qt::AlignHCenter); + d->IconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); + setLayout(d->Layout); +} + + +//============================================================================ +SideTabIconLabel::~SideTabIconLabel() +{ + delete d; +} + + +//============================================================================ +void SideTabIconLabel::setPixmap(const QPixmap& pixmap) +{ + d->IconLabel->setPixmap(pixmap); +} + + +//============================================================================ +void SideTabIconLabel::setContentsMargins(int left, int top, int right, int bottom) +{ + d->Layout->setContentsMargins(left, top, right, bottom); +} } diff --git a/src/DockWidgetSideTab.h b/src/DockWidgetSideTab.h index 5107828..0112308 100644 --- a/src/DockWidgetSideTab.h +++ b/src/DockWidgetSideTab.h @@ -39,6 +39,7 @@ struct DockWidgetSideTabPrivate; class CDockWidget; class CSideTabBar; class CDockWidgetTab; +struct SideTabIconLabelPrivate; /** * A dock widget Side tab that shows a title or an icon. @@ -50,6 +51,7 @@ class ADS_EXPORT CDockWidgetSideTab : public QFrame Q_OBJECT Q_PROPERTY(SideTabBarArea sideTabBarArea READ sideTabBarArea) + Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize) private: DockWidgetSideTabPrivate* d; ///< private data (pimpl) @@ -104,10 +106,47 @@ public: */ SideTabBarArea sideTabBarArea() const; + /** + * Sets the icon to show in title bar + */ + void setIcon(const QIcon& Icon); + + /** + * Returns the icon size. + * If no explicit icon size has been set, the function returns an invalid + * QSize + */ + QSize iconSize() const; + + /** + * Set an explicit icon size. + * If no icon size has been set explicitely, than the tab sets the icon size + * depending on the style + */ + void setIconSize(const QSize& Size); + + /** + * Update the title and icon visibility based on the area and the config + */ + void updateTitleAndIconVisibility(SideTabBarArea area); + Q_SIGNALS: void elidedChanged(bool elided); void clicked(); }; // class DockWidgetSideTab + +class SideTabIconLabel : public QWidget +{ +private: + SideTabIconLabelPrivate *d; ///< private data (pimpl) + +public: + SideTabIconLabel(QWidget* parent = nullptr); + virtual ~SideTabIconLabel(); + + void setPixmap(const QPixmap &pixmap); + void setContentsMargins(int left, int top, int right, int bottom); +}; // class SideTabIconLabel } // namespace ads //----------------------------------------------------------------------------- diff --git a/src/DockWidgetTab.cpp b/src/DockWidgetTab.cpp index f8b4e72..eed6fff 100644 --- a/src/DockWidgetTab.cpp +++ b/src/DockWidgetTab.cpp @@ -759,10 +759,6 @@ void CDockWidgetTab::setIconSize(const QSize& Size) d->IconSize = Size; d->updateIcon(); } - - - - } // namespace ads //--------------------------------------------------------------------------- // EOF DockWidgetTab.cpp diff --git a/src/OverlayDockContainer.cpp b/src/OverlayDockContainer.cpp index 0d14d51..49bfb78 100644 --- a/src/OverlayDockContainer.cpp +++ b/src/OverlayDockContainer.cpp @@ -204,6 +204,8 @@ void COverlayDockContainer::addDockWidget(CDockWidget* DockWidget) d->Splitter->setSizes({ rect.width() - dockWidth, dockWidth }); } + d->DockWidget->sideTabWidget()->updateTitleAndIconVisibility(d->Area); + updateSize(); updateMask(); } diff --git a/src/stylesheets/focus_highlighting.css b/src/stylesheets/focus_highlighting.css index 3d70856..f115a9c 100644 --- a/src/stylesheets/focus_highlighting.css +++ b/src/stylesheets/focus_highlighting.css @@ -24,6 +24,7 @@ ads--CDockWidgetTab { ads--CDockWidgetSideTab { background: palette(window); + qproperty-iconSize: 16px 16px;/* this is optional in case you would like to change icon size*/ } ads--CDockWidgetSideTab[sideTabBarArea="Left"] {