From 3b97fdc2ceff71d814847e9f72df6183ec87cc0b Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Thu, 3 Nov 2022 11:34:04 +0100 Subject: [PATCH 1/6] Improved AutoHideSidebar to provide better resize behavior if parent widget is resized --- demo/MainWindow.cpp | 3 +- src/AutoHideSideBar.cpp | 184 ++++++++++++++++++------- src/AutoHideSideBar.h | 36 ++++- src/AutoHideTab.cpp | 8 ++ src/stylesheets/default.css | 25 ++-- src/stylesheets/focus_highlighting.css | 30 ++-- 6 files changed, 204 insertions(+), 82 deletions(-) diff --git a/demo/MainWindow.cpp b/demo/MainWindow.cpp index e0394c4..e46bd7c 100644 --- a/demo/MainWindow.cpp +++ b/demo/MainWindow.cpp @@ -746,13 +746,14 @@ void CMainWindow::savePerspective() //============================================================================ void CMainWindow::onViewToggled(bool Open) { + Q_UNUSED(Open); auto DockWidget = qobject_cast(sender()); if (!DockWidget) { return; } - //qDebug() << DockWidget->objectName() << " viewToggled(" << Open << ")"; + qDebug() << DockWidget->objectName() << " viewToggled(" << Open << ")"; } diff --git a/src/AutoHideSideBar.cpp b/src/AutoHideSideBar.cpp index 17d25c8..23babba 100644 --- a/src/AutoHideSideBar.cpp +++ b/src/AutoHideSideBar.cpp @@ -45,6 +45,8 @@ namespace ads { +class CTabsWidget; + /** * Private data class of CSideTabBar class (pimpl) */ @@ -57,6 +59,7 @@ struct AutoHideSideBarPrivate CAutoHideSideBar* _this; CDockContainerWidget* ContainerWidget; + CTabsWidget* TabsContainerWidget; QBoxLayout* TabsLayout; Qt::Orientation Orientation; SideBarLocation SideTabArea = SideBarLocation::Left; @@ -68,8 +71,43 @@ struct AutoHideSideBarPrivate { return Qt::Horizontal == Orientation; } + + /** + * Called from viewport to forward event handling to this + */ + void handleViewportEvent(QEvent* e); }; // struct AutoHideSideBarPrivate + +/** + * This widget stores the tab buttons + */ +class CTabsWidget : public QWidget +{ +public: + using QWidget::QWidget; + using Super = QWidget; + AutoHideSideBarPrivate* EventHandler; + + /** + * Returns the size hint as minimum size hint + */ + virtual QSize minimumSizeHint() const override + { + return Super::sizeHint(); + } + + /** + * Forward event handling to EventHandler + */ + /*virtual bool event(QEvent* e) override + { + EventHandler->handleViewportEvent(e); + return Super::event(e); + }*/ +}; + + //============================================================================ AutoHideSideBarPrivate::AutoHideSideBarPrivate(CAutoHideSideBar* _public) : _this(_public) @@ -77,6 +115,45 @@ AutoHideSideBarPrivate::AutoHideSideBarPrivate(CAutoHideSideBar* _public) : } +//============================================================================ +void AutoHideSideBarPrivate::handleViewportEvent(QEvent* e) +{ + switch (e->type()) + { + case QEvent::ChildRemoved: + if (TabsLayout->isEmpty()) + { + _this->hide(); + } + break; + + case QEvent::Resize: + if (_this->tabCount()) + { + auto ev = static_cast(e); + auto Tab = _this->tabAt(0); + int Size = isHorizontal() ? ev->size().height() : ev->size().width(); + int TabSize = isHorizontal() ? Tab->size().height() : Tab->size().width(); + // If the size of the side bar is less than the size of the first tab + // then there are no visible tabs in this side bar. This check will + // fail if someone will force a very big border via CSS!! + if (Size < TabSize) + { + _this->hide(); + } + } + else + { + _this->hide(); + } + break; + + default: + break; + } +} + + //============================================================================ CAutoHideSideBar::CAutoHideSideBar(CDockContainerWidget* parent, SideBarLocation area) : Super(parent), @@ -87,16 +164,24 @@ CAutoHideSideBar::CAutoHideSideBar(CDockContainerWidget* parent, SideBarLocation d->Orientation = (area == SideBarLocation::Bottom || area == SideBarLocation::Top) ? Qt::Horizontal : Qt::Vertical; - auto mainLayout = new QBoxLayout(d->Orientation == Qt::Vertical ? QBoxLayout::TopToBottom : QBoxLayout::LeftToRight); + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + setFrameStyle(QFrame::NoFrame); + setWidgetResizable(true); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + d->TabsContainerWidget = new CTabsWidget(); + d->TabsContainerWidget->EventHandler = d; + d->TabsContainerWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + d->TabsContainerWidget->setObjectName("sideTabsContainerWidget"); + d->TabsLayout = new QBoxLayout(d->Orientation == Qt::Vertical ? QBoxLayout::TopToBottom : QBoxLayout::LeftToRight); d->TabsLayout->setContentsMargins(0, 0, 0, 0); - d->TabsLayout->setSpacing(0); - mainLayout->addLayout(d->TabsLayout); - mainLayout->setContentsMargins(0, 0, 0, 0); - mainLayout->setSpacing(0); - mainLayout->addStretch(1); - setLayout(mainLayout); + d->TabsLayout->setSpacing(12); + d->TabsLayout->addStretch(1); + d->TabsContainerWidget->setLayout(d->TabsLayout); + setWidget(d->TabsContainerWidget); setFocusPolicy(Qt::NoFocus); if (d->isHorizontal()) @@ -108,6 +193,8 @@ CAutoHideSideBar::CAutoHideSideBar(CDockContainerWidget* parent, SideBarLocation setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); } + qDebug() << "d->TabsLayout->count " << d->TabsLayout->count(); + hide(); } @@ -130,9 +217,16 @@ CAutoHideSideBar::~CAutoHideSideBar() //============================================================================ void CAutoHideSideBar::insertTab(int Index, CAutoHideTab* SideTab) { - SideTab->installEventFilter(this); SideTab->setSideBar(this); - d->TabsLayout->insertWidget(Index, SideTab); + SideTab->installEventFilter(this); + if (Index < 0) + { + d->TabsLayout->insertWidget(d->TabsLayout->count() - 1, SideTab); + } + else + { + d->TabsLayout->insertWidget(Index, SideTab); + } show(); } @@ -161,46 +255,6 @@ void CAutoHideSideBar::removeTab(CAutoHideTab* SideTab) } -//============================================================================ -bool CAutoHideSideBar::event(QEvent* e) -{ - switch (e->type()) - { - case QEvent::ChildRemoved: - if (d->TabsLayout->isEmpty()) - { - hide(); - } - break; - - case QEvent::Resize: - if (d->TabsLayout->count()) - { - auto ev = static_cast(e); - auto Tab = tabAt(0); - int Size = d->isHorizontal() ? ev->size().height() : ev->size().width(); - int TabSize = d->isHorizontal() ? Tab->size().height() : Tab->size().width(); - // If the size of the side bar is less than the size of the first tab - // then there are no visible tabs in this side bar. This check will - // fail if someone will force a very big border via CSS!! - if (Size < TabSize) - { - hide(); - } - } - else - { - hide(); - } - break; - - default: - break; - } - return Super::event(e); -} - - //============================================================================ bool CAutoHideSideBar::eventFilter(QObject *watched, QEvent *event) { @@ -209,7 +263,7 @@ bool CAutoHideSideBar::eventFilter(QObject *watched, QEvent *event) return false; } - // As soon as on tab is shhown, we need to show the side tab bar + // As soon as on tab is shown, we need to show the side tab bar auto Tab = qobject_cast(watched); if (Tab) { @@ -235,7 +289,7 @@ CAutoHideTab* CAutoHideSideBar::tabAt(int index) const //============================================================================ int CAutoHideSideBar::tabCount() const { - return d->TabsLayout->count(); + return d->TabsLayout->count() - 1; } @@ -272,5 +326,33 @@ void CAutoHideSideBar::saveState(QXmlStreamWriter& s) const s.writeEndElement(); } +//=========================================================================== +QSize CAutoHideSideBar::minimumSizeHint() const +{ + QSize Size = sizeHint(); + Size.setWidth(10); + return Size; +} + + +//=========================================================================== +QSize CAutoHideSideBar::sizeHint() const +{ + return d->TabsContainerWidget->sizeHint(); +} + + +//=========================================================================== +int CAutoHideSideBar::spacing() const +{ + return d->TabsLayout->spacing(); +} + +//=========================================================================== +void CAutoHideSideBar::setSpacing(int Spacing) +{ + d->TabsLayout->setSpacing(Spacing); +} } // namespace ads + diff --git a/src/AutoHideSideBar.h b/src/AutoHideSideBar.h index 11f7345..3e57e2b 100644 --- a/src/AutoHideSideBar.h +++ b/src/AutoHideSideBar.h @@ -29,7 +29,7 @@ //============================================================================ // INCLUDES //============================================================================ -#include +#include #include "ads_globals.h" #include "AutoHideTab.h" @@ -50,12 +50,16 @@ class CDockingStateReader; * it contains visible tabs. If it is empty or all tabs are hidden, then the * side bar is also hidden. As soon as one single tab becomes visible, this * tab bar will be shown. + * The CAutoHideSideBar uses a QScrollArea here, to enable proper resizing. + * If the side bar contains many tabs, then the tabs are simply clipped - this + * is the same like in visual studio */ -class ADS_EXPORT CAutoHideSideBar : public QFrame +class ADS_EXPORT CAutoHideSideBar : public QScrollArea { Q_OBJECT Q_PROPERTY(int sideBarLocation READ sideBarLocation) Q_PROPERTY(Qt::Orientation orientation READ orientation) + Q_PROPERTY(int spacing READ spacing WRITE setSpacing) private: AutoHideSideBarPrivate* d; ///< private data (pimpl) @@ -64,7 +68,6 @@ private: friend DockContainerWidgetPrivate; protected: - virtual bool event(QEvent* e) override; virtual bool eventFilter(QObject *watched, QEvent *event) override; /** @@ -79,7 +82,7 @@ protected: void insertTab(int Index, CAutoHideTab* SideTab); public: - using Super = QFrame; + using Super = QScrollArea; /** * Default Constructor @@ -123,6 +126,31 @@ public: */ SideBarLocation sideBarLocation() const; + /** + * Overrides the minimumSizeHint() function of QScrollArea + * The minimumSizeHint() is bigger than the sizeHint () for the scroll + * area because even if the scrollbars are invisible, the required speace + * is reserved in the minimumSizeHint(). This override simply returns + * sizeHint(); + */ + virtual QSize minimumSizeHint() const override; + + /** + * The function provides a sizeHint that matches the height of the + * internal viewport. + */ + virtual QSize sizeHint() const override; + + /** + * Getter for spacing property - returns the spacing of the tabs + */ + int spacing() const; + + /** + * Setter for spacing property - sets the spacing + */ + void setSpacing(int Spacing); + Q_SIGNALS: void sideTabAutoHideToggleRequested(); }; diff --git a/src/AutoHideTab.cpp b/src/AutoHideTab.cpp index 461085d..9377980 100644 --- a/src/AutoHideTab.cpp +++ b/src/AutoHideTab.cpp @@ -173,6 +173,14 @@ SideBarLocation CAutoHideTab::sideBarLocation() const void CAutoHideTab::setOrientation(Qt::Orientation Orientation) { d->Orientation = Orientation; + if (orientation() == Qt::Horizontal) + { + setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); + } + else + { + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum); + } CPushButton::setButtonOrientation((Qt::Horizontal == Orientation) ? CPushButton::Horizontal : CPushButton::VerticalTopToBottom); updateStyle(); diff --git a/src/stylesheets/default.css b/src/stylesheets/default.css index 155de9e..718b482 100644 --- a/src/stylesheets/default.css +++ b/src/stylesheets/default.css @@ -131,53 +131,52 @@ QScrollArea#dockWidgetScrollArea { * CAutoHideTab *****************************************************************************/ ads--CAutoHideTab { - qproperty-iconSize: 16px 16px;/* this is optional in case you would like to change icon size*/ + qproperty-iconSize: 16px 16px;/* this is optional in case you would like to change icon size*/ background: none; border: none; padding-left: 2px; padding-right: 0px; text-align: center; - margin-right: 6px; - min-height: 20; + min-height: 20px; + padding-bottom: 2px; } ads--CAutoHideTab[sideBarLocation="0"], ads--CAutoHideTab[sideBarLocation="2"] { - border-top: 5px solid rgba(0, 0, 0, 48); - + border-top: 6px solid rgba(0, 0, 0, 48); } ads--CAutoHideTab[sideBarLocation="1"], ads--CAutoHideTab[sideBarLocation="3"] { - border-bottom: 5px solid rgba(0, 0, 0, 48); + border-bottom: 6px solid rgba(0, 0, 0, 48); } ads--CAutoHideTab:hover[sideBarLocation="0"], ads--CAutoHideTab:hover[sideBarLocation="2"] { - border-top: 5px solid palette(highlight); + border-top: 6px solid palette(highlight); color: palette(highlight); } ads--CAutoHideTab:hover[sideBarLocation="1"], ads--CAutoHideTab:hover[sideBarLocation="3"] { - border-bottom: 5px solid palette(highlight); + border-bottom: 6px solid palette(highlight); color: palette(highlight); } ads--CAutoHideTab[sideBarLocation="0"][activeTab="true"], ads--CAutoHideTab[sideBarLocation="2"][activeTab="true"] { - border-top: 5px solid palette(highlight); + border-top: 6px solid palette(highlight); } ads--CAutoHideTab[sideBarLocation="1"][activeTab="true"], ads--CAutoHideTab[sideBarLocation="3"][activeTab="true"] { - border-bottom: 5px solid palette(highlight); + border-bottom: 6px solid palette(highlight); } @@ -186,6 +185,12 @@ ads--CAutoHideTab[sideBarLocation="3"][activeTab="true"] { *****************************************************************************/ ads--CAutoHideSideBar{ background: palette(window); + border: none; + qproperty-spacing: 12; +} + +#sideTabsContainerWidget { + background: transparent; } diff --git a/src/stylesheets/focus_highlighting.css b/src/stylesheets/focus_highlighting.css index 1e09c43..1057769 100644 --- a/src/stylesheets/focus_highlighting.css +++ b/src/stylesheets/focus_highlighting.css @@ -168,59 +168,52 @@ QScrollArea#dockWidgetScrollArea { * CAutoHideTab *****************************************************************************/ ads--CAutoHideTab { - /*background: palette(window);*/ qproperty-iconSize: 16px 16px;/* this is optional in case you would like to change icon size*/ -} - - -ads--CAutoHideTab { background: none; border: none; padding-left: 2px; padding-right: 0px; text-align: center; + min-height: 20px; + padding-bottom: 2px; } ads--CAutoHideTab[sideBarLocation="0"], ads--CAutoHideTab[sideBarLocation="2"] { - border-top: 5px solid rgba(0, 0, 0, 48); - margin-right: 6px; - min-height: 20; + border-top: 6px solid rgba(0, 0, 0, 48); } ads--CAutoHideTab[sideBarLocation="1"], ads--CAutoHideTab[sideBarLocation="3"] { - border-bottom: 5px solid rgba(0, 0, 0, 48); - margin-right: 6px; - min-height: 20; + border-bottom: 6px solid rgba(0, 0, 0, 48); } ads--CAutoHideTab:hover[sideBarLocation="0"], ads--CAutoHideTab:hover[sideBarLocation="2"] { - border-top: 5px solid palette(highlight); + border-top: 6px solid palette(highlight); color: palette(highlight); } ads--CAutoHideTab:hover[sideBarLocation="1"], ads--CAutoHideTab:hover[sideBarLocation="3"] { - border-bottom: 5px solid palette(highlight); + border-bottom: 6px solid palette(highlight); color: palette(highlight); } ads--CAutoHideTab[sideBarLocation="0"][activeTab="true"], ads--CAutoHideTab[sideBarLocation="2"][activeTab="true"] { - border-top: 5px solid palette(highlight); + border-top: 6px solid palette(highlight); } ads--CAutoHideTab[sideBarLocation="1"][activeTab="true"], ads--CAutoHideTab[sideBarLocation="3"][activeTab="true"] { - border-bottom: 5px solid palette(highlight); + border-bottom: 6px solid palette(highlight); } @@ -229,6 +222,12 @@ ads--CAutoHideTab[sideBarLocation="3"][activeTab="true"] { *****************************************************************************/ ads--CAutoHideSideBar{ background: palette(window); + border: none; + qproperty-spacing: 12; +} + +#sideTabsContainerWidget { + background: transparent; } @@ -336,4 +335,3 @@ ads--CAutoHideDockContainer[sideBarLocation="2"] ads--CResizeHandle { ads--CAutoHideDockContainer[sideBarLocation="3"] ads--CResizeHandle { border-top: 1px solid palette(dark); } - From 1922395b4b2f175c92546a22f045d7b497fae1bd Mon Sep 17 00:00:00 2001 From: Uwe Date: Thu, 3 Nov 2022 12:00:52 +0100 Subject: [PATCH 2/6] Improved linux auto hide specific css code --- src/stylesheets/default_linux.css | 57 +++++++++++-------- src/stylesheets/focus_highlighting_linux.css | 58 ++++++++++++-------- 2 files changed, 69 insertions(+), 46 deletions(-) diff --git a/src/stylesheets/default_linux.css b/src/stylesheets/default_linux.css index 28d2b5a..fbfc305 100644 --- a/src/stylesheets/default_linux.css +++ b/src/stylesheets/default_linux.css @@ -167,49 +167,52 @@ ads--CFloatingWidgetTitleBar { * CAutoHideTab *****************************************************************************/ ads--CAutoHideTab { - qproperty-iconSize: 16px 16px;/* this is optional in case you would like to change icon size*/ - padding-left: 2px; - padding-right: 0px; - text-align: center; - margin-right: 6px; - min-height: 20; - border: none; -} - -ads--CAutoHideTab[sideBarLocation="1"], -ads--CAutoHideTab[sideBarLocation="3"] { - border-bottom: 5px solid rgba(0, 0, 0, 48); + qproperty-iconSize: 16px 16px;/* this is optional in case you would like to change icon size*/ + background: none; + border: none; + padding-left: 2px; + padding-right: 0px; + text-align: center; + min-height: 20px; + padding-bottom: 2px; } ads--CAutoHideTab[sideBarLocation="0"], ads--CAutoHideTab[sideBarLocation="2"] { - border-top: 5px solid rgba(0, 0, 0, 48); + border-top: 6px solid rgba(0, 0, 0, 48); } +ads--CAutoHideTab[sideBarLocation="1"], +ads--CAutoHideTab[sideBarLocation="3"] { + border-bottom: 6px solid rgba(0, 0, 0, 48); +} + + + ads--CAutoHideTab:hover[sideBarLocation="0"], ads--CAutoHideTab:hover[sideBarLocation="2"] { - border-top: 5px solid palette(highlight); - color: palette(highlight); + border-top: 6px solid palette(highlight); + color: palette(highlight); } ads--CAutoHideTab:hover[sideBarLocation="1"], ads--CAutoHideTab:hover[sideBarLocation="3"] { - border-bottom: 5px solid palette(highlight); - color: palette(highlight); + border-bottom: 6px solid palette(highlight); + color: palette(highlight); } ads--CAutoHideTab[sideBarLocation="0"][activeTab="true"], ads--CAutoHideTab[sideBarLocation="2"][activeTab="true"] { - border-top: 5px solid palette(highlight); + border-top: 6px solid palette(highlight); } ads--CAutoHideTab[sideBarLocation="1"][activeTab="true"], ads--CAutoHideTab[sideBarLocation="3"][activeTab="true"] { - border-bottom: 5px solid palette(highlight); + border-bottom: 6px solid palette(highlight); } @@ -218,23 +221,29 @@ ads--CAutoHideTab[sideBarLocation="3"][activeTab="true"] { *****************************************************************************/ ads--CAutoHideSideBar{ background: palette(window); + border: none; + qproperty-spacing: 12; +} + +#sideTabsContainerWidget { + background: transparent; } ads--CAutoHideSideBar[sideBarLocation="0"] { - border-bottom: 1px solid palette(dark); + border-bottom: 1px solid palette(dark); } ads--CAutoHideSideBar[sideBarLocation="1"] { - border-right: 1px solid palette(dark); + border-right: 1px solid palette(dark); } ads--CAutoHideSideBar[sideBarLocation="2"] { - border-left: 1px solid palette(dark); + border-left: 1px solid palette(dark); } ads--CAutoHideSideBar[sideBarLocation="3"] { - border-top: 1px solid palette(dark); + border-top: 1px solid palette(dark); } @@ -291,10 +300,12 @@ ads--CAutoHideDockContainer #dockAreaCloseButton{ ads--CAutoHideDockContainer ads--CTitleBarButton:hover { background: rgba(255, 255, 255, 48); + border: none; } ads--CAutoHideDockContainer ads--CTitleBarButton:pressed { background: rgba(255, 255, 255, 96); + border: none; } /***************************************************************************** diff --git a/src/stylesheets/focus_highlighting_linux.css b/src/stylesheets/focus_highlighting_linux.css index 3a78cef..45a8784 100644 --- a/src/stylesheets/focus_highlighting_linux.css +++ b/src/stylesheets/focus_highlighting_linux.css @@ -243,74 +243,84 @@ ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleMaximizeButton: * CAutoHideTab *****************************************************************************/ ads--CAutoHideTab { - qproperty-iconSize: 16px 16px;/* this is optional in case you would like to change icon size*/ - padding-left: 2px; - padding-right: 0px; - text-align: center; - margin-right: 6px; - min-height: 20; - border: none; -} - -ads--CAutoHideTab[sideBarLocation="1"], -ads--CAutoHideTab[sideBarLocation="3"] { - border-bottom: 5px solid rgba(0, 0, 0, 48); + qproperty-iconSize: 16px 16px;/* this is optional in case you would like to change icon size*/ + background: none; + border: none; + padding-left: 2px; + padding-right: 0px; + text-align: center; + min-height: 20px; + padding-bottom: 2px; } ads--CAutoHideTab[sideBarLocation="0"], ads--CAutoHideTab[sideBarLocation="2"] { - border-top: 5px solid rgba(0, 0, 0, 48); + border-top: 6px solid rgba(0, 0, 0, 48); } +ads--CAutoHideTab[sideBarLocation="1"], +ads--CAutoHideTab[sideBarLocation="3"] { + border-bottom: 6px solid rgba(0, 0, 0, 48); +} + + + ads--CAutoHideTab:hover[sideBarLocation="0"], ads--CAutoHideTab:hover[sideBarLocation="2"] { - border-top: 5px solid palette(highlight); - color: palette(highlight); + border-top: 6px solid palette(highlight); + color: palette(highlight); } ads--CAutoHideTab:hover[sideBarLocation="1"], ads--CAutoHideTab:hover[sideBarLocation="3"] { - border-bottom: 5px solid palette(highlight); - color: palette(highlight); + border-bottom: 6px solid palette(highlight); + color: palette(highlight); } ads--CAutoHideTab[sideBarLocation="0"][activeTab="true"], ads--CAutoHideTab[sideBarLocation="2"][activeTab="true"] { - border-top: 5px solid palette(highlight); + border-top: 6px solid palette(highlight); } ads--CAutoHideTab[sideBarLocation="1"][activeTab="true"], ads--CAutoHideTab[sideBarLocation="3"][activeTab="true"] { - border-bottom: 5px solid palette(highlight); + border-bottom: 6px solid palette(highlight); } + /***************************************************************************** * CAutoHideSideBar *****************************************************************************/ ads--CAutoHideSideBar{ background: palette(window); + border: none; + qproperty-spacing: 12; +} + +#sideTabsContainerWidget { + background: transparent; } ads--CAutoHideSideBar[sideBarLocation="0"] { - border-bottom: 1px solid palette(dark); + border-bottom: 1px solid palette(dark); } ads--CAutoHideSideBar[sideBarLocation="1"] { - border-right: 1px solid palette(dark); + border-right: 1px solid palette(dark); } ads--CAutoHideSideBar[sideBarLocation="2"] { - border-left: 1px solid palette(dark); + border-left: 1px solid palette(dark); } ads--CAutoHideSideBar[sideBarLocation="3"] { - border-top: 1px solid palette(dark); + border-top: 1px solid palette(dark); } @@ -367,10 +377,12 @@ ads--CAutoHideDockContainer #dockAreaCloseButton{ ads--CAutoHideDockContainer ads--CTitleBarButton:hover { background: rgba(255, 255, 255, 48); + border: none; } ads--CAutoHideDockContainer ads--CTitleBarButton:pressed { background: rgba(255, 255, 255, 96); + border: none; } /***************************************************************************** From 04ea1c68a71d706e3719e3bfb78f2eed9f43a573 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Thu, 3 Nov 2022 15:28:01 +0100 Subject: [PATCH 3/6] Added option to auto hide a DockWidget or a DockArea to a specific sidebar location --- examples/autohide/mainwindow.cpp | 4 +-- src/AutoHideDockContainer.cpp | 56 +++++++++++++++++++------------- src/AutoHideSideBar.cpp | 4 +-- src/AutoHideTab.cpp | 17 ++++++---- src/DockAreaTitleBar.cpp | 37 ++++++++++++++++++++- src/DockAreaTitleBar.h | 1 + src/DockAreaWidget.cpp | 56 ++++++++++++++++---------------- src/DockAreaWidget.h | 4 +-- src/DockContainerWidget.cpp | 8 ++--- src/DockWidget.cpp | 8 ++--- src/DockWidget.h | 4 +-- src/DockWidgetTab.cpp | 32 ++++++++++++++++-- src/DockWidgetTab.h | 1 + src/ads_globals.h | 9 ++--- 14 files changed, 161 insertions(+), 80 deletions(-) diff --git a/examples/autohide/mainwindow.cpp b/examples/autohide/mainwindow.cpp index 56b6eaa..d70b51c 100644 --- a/examples/autohide/mainwindow.cpp +++ b/examples/autohide/mainwindow.cpp @@ -46,7 +46,7 @@ CMainWindow::CMainWindow(QWidget *parent) TableDockWidget->setWidget(table); TableDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget); TableDockWidget->setMinimumSize(200,150); - const auto autoHideContainer = DockManager->addAutoHideDockWidget(SideBarLocation::Left, TableDockWidget); + const auto autoHideContainer = DockManager->addAutoHideDockWidget(SideBarLocation::SideBarLeft, TableDockWidget); autoHideContainer->setSize(480); ui->menuView->addAction(TableDockWidget->toggleViewAction()); @@ -58,7 +58,7 @@ CMainWindow::CMainWindow(QWidget *parent) TableDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget); TableDockWidget->resize(250, 150); TableDockWidget->setMinimumSize(200,150); - DockManager->addAutoHideDockWidget(SideBarLocation::Left, TableDockWidget); + DockManager->addAutoHideDockWidget(SideBarLocation::SideBarLeft, TableDockWidget); ui->menuView->addAction(TableDockWidget->toggleViewAction()); QTableWidget* propertiesTable = new QTableWidget(); diff --git a/src/AutoHideDockContainer.cpp b/src/AutoHideDockContainer.cpp index 1f0f1aa..6033596 100644 --- a/src/AutoHideDockContainer.cpp +++ b/src/AutoHideDockContainer.cpp @@ -57,10 +57,12 @@ bool static isHorizontalArea(SideBarLocation Area) { switch (Area) { - case SideBarLocation::Top: - case SideBarLocation::Bottom: return true; - case SideBarLocation::Left: - case SideBarLocation::Right: return false; + case SideBarLocation::SideBarTop: + case SideBarLocation::SideBarBottom: return true; + case SideBarLocation::SideBarLeft: + case SideBarLocation::SideBarRight: return false; + default: + return true; } return true; @@ -72,10 +74,12 @@ Qt::Edge static edgeFromSideTabBarArea(SideBarLocation Area) { switch (Area) { - case SideBarLocation::Top: return Qt::BottomEdge; - case SideBarLocation::Bottom: return Qt::TopEdge; - case SideBarLocation::Left: return Qt::RightEdge; - case SideBarLocation::Right: return Qt::LeftEdge; + case SideBarLocation::SideBarTop: return Qt::BottomEdge; + case SideBarLocation::SideBarBottom: return Qt::TopEdge; + case SideBarLocation::SideBarLeft: return Qt::RightEdge; + case SideBarLocation::SideBarRight: return Qt::LeftEdge; + default: + return Qt::LeftEdge; } return Qt::LeftEdge; @@ -87,11 +91,14 @@ int resizeHandleLayoutPosition(SideBarLocation Area) { switch (Area) { - case SideBarLocation::Bottom: - case SideBarLocation::Right: return 0; + case SideBarLocation::SideBarBottom: + case SideBarLocation::SideBarRight: return 0; - case SideBarLocation::Top: - case SideBarLocation::Left: return 1; + case SideBarLocation::SideBarTop: + case SideBarLocation::SideBarLeft: return 1; + + default: + return 0; } return 0; @@ -106,8 +113,8 @@ struct AutoHideDockContainerPrivate CAutoHideDockContainer* _this; CDockAreaWidget* DockArea{nullptr}; CDockWidget* DockWidget{nullptr}; - SideBarLocation SideTabBarArea; - QBoxLayout* Layout; + SideBarLocation SideTabBarArea = SideBarNone; + QBoxLayout* Layout = nullptr; CResizeHandle* ResizeHandle = nullptr; QSize Size; // creates invalid size QPointer SideTab; @@ -124,10 +131,12 @@ struct AutoHideDockContainerPrivate { switch (area) { - case SideBarLocation::Left: return LeftDockWidgetArea; - case SideBarLocation::Right: return RightDockWidgetArea; - case SideBarLocation::Bottom: return BottomDockWidgetArea; - case SideBarLocation::Top: return TopDockWidgetArea; + case SideBarLocation::SideBarLeft: return LeftDockWidgetArea; + case SideBarLocation::SideBarRight: return RightDockWidgetArea; + case SideBarLocation::SideBarBottom: return BottomDockWidgetArea; + case SideBarLocation::SideBarTop: return TopDockWidgetArea; + default: + return LeftDockWidgetArea; } return LeftDockWidgetArea; @@ -232,17 +241,17 @@ void CAutoHideDockContainer::updateSize() switch (sideBarLocation()) { - case SideBarLocation::Top: + case SideBarLocation::SideBarTop: resize(rect.width(), qMin(rect.height() - ResizeMargin, d->Size.height())); move(rect.topLeft()); break; - case SideBarLocation::Left: + case SideBarLocation::SideBarLeft: resize(qMin(d->Size.width(), rect.width() - ResizeMargin), rect.height()); move(rect.topLeft()); break; - case SideBarLocation::Right: + case SideBarLocation::SideBarRight: { resize(qMin(d->Size.width(), rect.width() - ResizeMargin), rect.height()); QPoint p = rect.topRight(); @@ -251,7 +260,7 @@ void CAutoHideDockContainer::updateSize() } break; - case SideBarLocation::Bottom: + case SideBarLocation::SideBarBottom: { resize(rect.width(), qMin(rect.height() - ResizeMargin, d->Size.height())); QPoint p = rect.bottomLeft(); @@ -259,6 +268,9 @@ void CAutoHideDockContainer::updateSize() move(p); } break; + + default: + break; } } diff --git a/src/AutoHideSideBar.cpp b/src/AutoHideSideBar.cpp index 23babba..fdb98ed 100644 --- a/src/AutoHideSideBar.cpp +++ b/src/AutoHideSideBar.cpp @@ -62,7 +62,7 @@ struct AutoHideSideBarPrivate CTabsWidget* TabsContainerWidget; QBoxLayout* TabsLayout; Qt::Orientation Orientation; - SideBarLocation SideTabArea = SideBarLocation::Left; + SideBarLocation SideTabArea = SideBarLocation::SideBarLeft; /** * Convenience function to check if this is a horizontal side bar @@ -161,7 +161,7 @@ CAutoHideSideBar::CAutoHideSideBar(CDockContainerWidget* parent, SideBarLocation { d->SideTabArea = area; d->ContainerWidget = parent; - d->Orientation = (area == SideBarLocation::Bottom || area == SideBarLocation::Top) + d->Orientation = (area == SideBarLocation::SideBarBottom || area == SideBarLocation::SideBarTop) ? Qt::Horizontal : Qt::Vertical; setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); diff --git a/src/AutoHideTab.cpp b/src/AutoHideTab.cpp index 9377980..b8fbb2c 100644 --- a/src/AutoHideTab.cpp +++ b/src/AutoHideTab.cpp @@ -74,7 +74,7 @@ AutoHideTabPrivate::AutoHideTabPrivate(CAutoHideTab* _public) : void AutoHideTabPrivate::updateOrientation() { auto area = SideBar->sideBarLocation(); - _this->setOrientation((area == Bottom || area == Top) ? Qt::Horizontal : Qt::Vertical); + _this->setOrientation((area == SideBarBottom || area == SideBarTop) ? Qt::Horizontal : Qt::Vertical); if (_this->icon().isNull()) { @@ -84,21 +84,24 @@ void AutoHideTabPrivate::updateOrientation() bool IconOnly = false; switch (area) { - case SideBarLocation::Left: + case SideBarLocation::SideBarLeft: IconOnly = CDockManager::testAutoHideConfigFlag(CDockManager::LeftSideBarIconOnly); break; - case SideBarLocation::Right: + case SideBarLocation::SideBarRight: IconOnly = CDockManager::testAutoHideConfigFlag(CDockManager::RightSideBarIconOnly); break; - case SideBarLocation::Top: + case SideBarLocation::SideBarTop: IconOnly = CDockManager::testAutoHideConfigFlag(CDockManager::BottomSideBarIconOnly); break; - case SideBarLocation::Bottom: + case SideBarLocation::SideBarBottom: IconOnly = CDockManager::testAutoHideConfigFlag(CDockManager::TopSideBarIconOnly); break; + + default: + break; } if (IconOnly) @@ -133,7 +136,7 @@ void CAutoHideTab::removeFromSideBar() //============================================================================ CAutoHideTab::CAutoHideTab(QWidget* parent) : - Super(parent), + CPushButton(parent), d(new AutoHideTabPrivate(this)) { setAttribute(Qt::WA_NoMousePropagation); @@ -165,7 +168,7 @@ SideBarLocation CAutoHideTab::sideBarLocation() const return d->SideBar->sideBarLocation(); } - return Left; + return SideBarLeft; } diff --git a/src/DockAreaTitleBar.cpp b/src/DockAreaTitleBar.cpp index 94781b1..951a42e 100644 --- a/src/DockAreaTitleBar.cpp +++ b/src/DockAreaTitleBar.cpp @@ -53,11 +53,13 @@ #include "DockFocusController.h" #include "ElidingLabel.h" #include "AutoHideDockContainer.h" +#include "IconProvider.h" #include namespace ads { +static const char* const LocationProperty = "Location"; /** * Private data class of CDockAreaTitleBar class (pimpl) @@ -146,6 +148,19 @@ struct DockAreaTitleBarPrivate * Makes the dock area floating */ IFloatingWidget* makeAreaFloating(const QPoint& Offset, eDragState DragState); + + /** + * Helper function to create and initialize the menu entries for + * the "Auto Hide Group To..." menu + */ + QAction* createAutoHideToAction(const QString& Title, SideBarLocation Location, + QMenu* Menu) + { + auto Action = Menu->addAction(Title); + Action->setProperty("Location", Location); + QObject::connect(Action, &QAction::triggered, _this, &CDockAreaTitleBar::onAutoHideToActionClicked); + return Action; + } };// struct DockAreaTitleBarPrivate //============================================================================ @@ -511,6 +526,15 @@ void CDockAreaTitleBar::onAutoHideDockAreaActionClicked() } +//============================================================================ +void CDockAreaTitleBar::onAutoHideToActionClicked() +{ + qDebug() << "CDockAreaTitleBar::onAutoHideToActionClicked()"; + int Location = sender()->property(LocationProperty).toInt(); + d->DockArea->toggleAutoHide((SideBarLocation)Location); +} + + //============================================================================ QAbstractButton* CDockAreaTitleBar::button(TitleBarButton which) const { @@ -677,7 +701,18 @@ void CDockAreaTitleBar::contextMenuEvent(QContextMenuEvent* ev) if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled)) { Action = Menu.addAction(IsAutoHide ? tr("Dock") : tr("Auto Hide Group"), this, SLOT(onAutoHideDockAreaActionClicked())); - Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetPinnable)); + auto AreaIsPinnable = d->DockArea->features().testFlag(CDockWidget::DockWidgetPinnable); + Action->setEnabled(AreaIsPinnable); + + if (!IsAutoHide) + { + auto menu = Menu.addMenu(tr("Auto Hide Group To...")); + menu->setEnabled(AreaIsPinnable); + d->createAutoHideToAction(tr("Top"), SideBarTop, menu); + d->createAutoHideToAction(tr("Left"), SideBarLeft, menu); + d->createAutoHideToAction(tr("Right"), SideBarRight, menu); + d->createAutoHideToAction(tr("Bottom"), SideBarBottom, menu); + } } Menu.addSeparator(); } diff --git a/src/DockAreaTitleBar.h b/src/DockAreaTitleBar.h index b2c81e8..6cc8e50 100644 --- a/src/DockAreaTitleBar.h +++ b/src/DockAreaTitleBar.h @@ -63,6 +63,7 @@ private Q_SLOTS: void onCurrentTabChanged(int Index); void onAutoHideButtonClicked(); void onAutoHideDockAreaActionClicked(); + void onAutoHideToActionClicked(); protected: /** diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index 06424c2..4054ec1 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -1241,60 +1241,60 @@ SideBarLocation CDockAreaWidget::calculateSideTabBarArea() const int BorderDistance[4]; int Distance = qAbs(ContentRect.topLeft().y() - DockAreaRect.topLeft().y()); - BorderDistance[SideBarLocation::Top] = (Distance < MinBorderDistance) ? 0 : Distance; - if (!BorderDistance[SideBarLocation::Top]) + BorderDistance[SideBarLocation::SideBarTop] = (Distance < MinBorderDistance) ? 0 : Distance; + if (!BorderDistance[SideBarLocation::SideBarTop]) { borders |= BorderTop; } Distance = qAbs(ContentRect.bottomRight().y() - DockAreaRect.bottomRight().y()); - BorderDistance[SideBarLocation::Bottom] = (Distance < MinBorderDistance) ? 0 : Distance; - if (!BorderDistance[SideBarLocation::Bottom]) + BorderDistance[SideBarLocation::SideBarBottom] = (Distance < MinBorderDistance) ? 0 : Distance; + if (!BorderDistance[SideBarLocation::SideBarBottom]) { borders |= BorderBottom; } Distance = qAbs(ContentRect.topLeft().x() - DockAreaRect.topLeft().x()); - BorderDistance[SideBarLocation::Left] = (Distance < MinBorderDistance) ? 0 : Distance; - if (!BorderDistance[SideBarLocation::Left]) + BorderDistance[SideBarLocation::SideBarLeft] = (Distance < MinBorderDistance) ? 0 : Distance; + if (!BorderDistance[SideBarLocation::SideBarLeft]) { borders |= BorderLeft; } Distance = qAbs(ContentRect.bottomRight().x() - DockAreaRect.bottomRight().x()); - BorderDistance[SideBarLocation::Right] = (Distance < MinBorderDistance) ? 0 : Distance; - if (!BorderDistance[SideBarLocation::Right]) + BorderDistance[SideBarLocation::SideBarRight] = (Distance < MinBorderDistance) ? 0 : Distance; + if (!BorderDistance[SideBarLocation::SideBarRight]) { borders |= BorderRight; } - auto SideTab = SideBarLocation::Right; + auto SideTab = SideBarLocation::SideBarRight; switch (borders) { // 1. It's touching all borders - case BorderAll: SideTab = HorizontalOrientation ? SideBarLocation::Bottom : SideBarLocation::Right; break; + case BorderAll: SideTab = HorizontalOrientation ? SideBarLocation::SideBarBottom : SideBarLocation::SideBarRight; break; // 2. It's touching 3 borders - case BorderVerticalBottom : SideTab = SideBarLocation::Bottom; break; - case BorderVerticalTop : SideTab = SideBarLocation::Top; break; - case BorderHorizontalLeft: SideTab = SideBarLocation::Left; break; - case BorderHorizontalRight: SideTab = SideBarLocation::Right; break; + case BorderVerticalBottom : SideTab = SideBarLocation::SideBarBottom; break; + case BorderVerticalTop : SideTab = SideBarLocation::SideBarTop; break; + case BorderHorizontalLeft: SideTab = SideBarLocation::SideBarLeft; break; + case BorderHorizontalRight: SideTab = SideBarLocation::SideBarRight; break; // 3. Its touching horizontal or vertical borders - case BorderVertical : SideTab = SideBarLocation::Bottom; break; - case BorderHorizontal: SideTab = SideBarLocation::Right; break; + case BorderVertical : SideTab = SideBarLocation::SideBarBottom; break; + case BorderHorizontal: SideTab = SideBarLocation::SideBarRight; break; // 4. Its in a corner - case BorderTopLeft : SideTab = HorizontalOrientation ? SideBarLocation::Top : SideBarLocation::Left; break; - case BorderTopRight : SideTab = HorizontalOrientation ? SideBarLocation::Top : SideBarLocation::Right; break; - case BorderBottomLeft : SideTab = HorizontalOrientation ? SideBarLocation::Bottom : SideBarLocation::Left; break; - case BorderBottomRight : SideTab = HorizontalOrientation ? SideBarLocation::Bottom : SideBarLocation::Right; break; + case BorderTopLeft : SideTab = HorizontalOrientation ? SideBarLocation::SideBarTop : SideBarLocation::SideBarLeft; break; + case BorderTopRight : SideTab = HorizontalOrientation ? SideBarLocation::SideBarTop : SideBarLocation::SideBarRight; break; + case BorderBottomLeft : SideTab = HorizontalOrientation ? SideBarLocation::SideBarBottom : SideBarLocation::SideBarLeft; break; + case BorderBottomRight : SideTab = HorizontalOrientation ? SideBarLocation::SideBarBottom : SideBarLocation::SideBarRight; break; // 5 Ists touching only one border - case BorderLeft: SideTab = SideBarLocation::Left; break; - case BorderRight: SideTab = SideBarLocation::Right; break; - case BorderTop: SideTab = SideBarLocation::Top; break; - case BorderBottom: SideTab = SideBarLocation::Bottom; break; + case BorderLeft: SideTab = SideBarLocation::SideBarLeft; break; + case BorderRight: SideTab = SideBarLocation::SideBarRight; break; + case BorderTop: SideTab = SideBarLocation::SideBarTop; break; + case BorderBottom: SideTab = SideBarLocation::SideBarBottom; break; } return SideTab; @@ -1302,7 +1302,7 @@ SideBarLocation CDockAreaWidget::calculateSideTabBarArea() const //============================================================================ -void CDockAreaWidget::setAutoHide(bool Enable) +void CDockAreaWidget::setAutoHide(bool Enable, SideBarLocation Location) { if (!isAutoHideFeatureEnabled()) { @@ -1318,7 +1318,7 @@ void CDockAreaWidget::setAutoHide(bool Enable) return; } - auto area = calculateSideTabBarArea(); + auto area = (SideBarNone == Location) ? calculateSideTabBarArea() : Location; for (const auto DockWidget : openedDockWidgets()) { if (Enable == isAutoHide()) @@ -1337,14 +1337,14 @@ void CDockAreaWidget::setAutoHide(bool Enable) //============================================================================ -void CDockAreaWidget::toggleAutoHide() +void CDockAreaWidget::toggleAutoHide(SideBarLocation Location) { if (!isAutoHideFeatureEnabled()) { return; } - setAutoHide(!isAutoHide()); + setAutoHide(!isAutoHide(), Location); } diff --git a/src/DockAreaWidget.h b/src/DockAreaWidget.h index b79107c..fface99 100644 --- a/src/DockAreaWidget.h +++ b/src/DockAreaWidget.h @@ -401,13 +401,13 @@ public Q_SLOTS: * If the dock area is switched to auto hide mode, then all dock widgets * that are pinable will be added to the sidebar */ - void setAutoHide(bool Enable); + void setAutoHide(bool Enable, SideBarLocation Location = SideBarNone); /** * Switches the dock area to auto hide mode or vice versa depending on its * current state. */ - void toggleAutoHide(); + void toggleAutoHide(SideBarLocation Location = SideBarNone); /** * This function closes all other areas except of this area diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index a90f990..43b0594 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -1842,25 +1842,25 @@ void CDockContainerWidget::createSideTabBarWidgets() } { - auto Area = SideBarLocation::Left; + auto Area = SideBarLocation::SideBarLeft; d->SideTabBarWidgets[Area] = new CAutoHideSideBar(this, Area); d->Layout->addWidget(d->SideTabBarWidgets[Area], 1, 0); } { - auto Area = SideBarLocation::Right; + auto Area = SideBarLocation::SideBarRight; d->SideTabBarWidgets[Area] = new CAutoHideSideBar(this, Area); d->Layout->addWidget(d->SideTabBarWidgets[Area], 1, 2); } { - auto Area = SideBarLocation::Bottom; + auto Area = SideBarLocation::SideBarBottom; d->SideTabBarWidgets[Area] = new CAutoHideSideBar(this, Area); d->Layout->addWidget(d->SideTabBarWidgets[Area], 2, 1); } { - auto Area = SideBarLocation::Top; + auto Area = SideBarLocation::SideBarTop; d->SideTabBarWidgets[Area] = new CAutoHideSideBar(this, Area); d->Layout->addWidget(d->SideTabBarWidgets[Area], 0, 1); } diff --git a/src/DockWidget.cpp b/src/DockWidget.cpp index 31f3cb9..e519880 100644 --- a/src/DockWidget.cpp +++ b/src/DockWidget.cpp @@ -1157,7 +1157,7 @@ void CDockWidget::raise() //============================================================================ -void CDockWidget::setAutoHide(bool Enable) +void CDockWidget::setAutoHide(bool Enable, SideBarLocation Location) { if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled)) { @@ -1177,21 +1177,21 @@ void CDockWidget::setAutoHide(bool Enable) } else { - auto area = DockArea->calculateSideTabBarArea(); + auto area = (SideBarNone == Location) ? DockArea->calculateSideTabBarArea() : Location; dockContainer()->createAndSetupAutoHideContainer(area, this); } } //============================================================================ -void CDockWidget::toggleAutoHide() +void CDockWidget::toggleAutoHide(SideBarLocation Location) { if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled)) { return; } - setAutoHide(!isAutoHide()); + setAutoHide(!isAutoHide(), Location); } diff --git a/src/DockWidget.h b/src/DockWidget.h index 115c02c..c0d0d91 100644 --- a/src/DockWidget.h +++ b/src/DockWidget.h @@ -596,13 +596,13 @@ public Q_SLOTS: * Sets the dock widget into auto hide mode if this feature is enabled * via CDockManager::setAutoHideFlags(CDockManager::AutoHideFeatureEnabled) */ - void setAutoHide(bool Enable); + void setAutoHide(bool Enable, SideBarLocation Location = SideBarNone); /** * Switches the dock widget to auto hide mode or vice versa depending on its * current state. */ - void toggleAutoHide(); + void toggleAutoHide(SideBarLocation Location = SideBarNone); Q_SIGNALS: diff --git a/src/DockWidgetTab.cpp b/src/DockWidgetTab.cpp index aa904c7..844a9fb 100644 --- a/src/DockWidgetTab.cpp +++ b/src/DockWidgetTab.cpp @@ -56,7 +56,7 @@ namespace ads { - +static const char* const LocationProperty = "Location"; using tTabLabel = CElidingLabel; /** @@ -217,6 +217,18 @@ struct DockWidgetTabPrivate return DockWidget->dockManager()->dockFocusController(); } + /** + * Helper function to create and initialize the menu entries for + * the "Auto Hide Group To..." menu + */ + QAction* createAutoHideToAction(const QString& Title, SideBarLocation Location, + QMenu* Menu) + { + auto Action = Menu->addAction(Title); + Action->setProperty("Location", Location); + QObject::connect(Action, &QAction::triggered, _this, &CDockWidgetTab::onAutoHideToActionClicked); + return Action; + } }; // struct DockWidgetTabPrivate @@ -518,7 +530,15 @@ void CDockWidgetTab::contextMenuEvent(QContextMenuEvent* ev) if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled)) { Action = Menu.addAction(tr("Auto Hide"), this, SLOT(autoHideDockWidget())); - Action->setEnabled(d->DockWidget->features().testFlag(CDockWidget::DockWidgetPinnable)); + auto IsPinnable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetPinnable); + Action->setEnabled(IsPinnable); + + auto menu = Menu.addMenu(tr("Auto Hide To...")); + menu->setEnabled(IsPinnable); + d->createAutoHideToAction(tr("Top"), SideBarTop, menu); + d->createAutoHideToAction(tr("Left"), SideBarLeft, menu); + d->createAutoHideToAction(tr("Right"), SideBarRight, menu); + d->createAutoHideToAction(tr("Bottom"), SideBarBottom, menu); } Menu.addSeparator(); Action = Menu.addAction(tr("Close"), this, SIGNAL(closeRequested())); @@ -712,6 +732,14 @@ void CDockWidgetTab::autoHideDockWidget() } +//=========================================================================== +void CDockWidgetTab::onAutoHideToActionClicked() +{ + int Location = sender()->property(LocationProperty).toInt(); + d->DockWidget->toggleAutoHide((SideBarLocation)Location); +} + + //============================================================================ bool CDockWidgetTab::event(QEvent *e) { diff --git a/src/DockWidgetTab.h b/src/DockWidgetTab.h index df32ef0..11d0ba5 100644 --- a/src/DockWidgetTab.h +++ b/src/DockWidgetTab.h @@ -64,6 +64,7 @@ private: private Q_SLOTS: void detachDockWidget(); void autoHideDockWidget(); + void onAutoHideToActionClicked(); protected: virtual void mousePressEvent(QMouseEvent* ev) override; diff --git a/src/ads_globals.h b/src/ads_globals.h index 3260f87..1b86b01 100644 --- a/src/ads_globals.h +++ b/src/ads_globals.h @@ -136,10 +136,11 @@ enum eBitwiseOperator */ enum SideBarLocation { - Top, - Left, - Right, - Bottom + SideBarTop, + SideBarLeft, + SideBarRight, + SideBarBottom, + SideBarNone }; Q_ENUMS(SideBarLocation); From 409d4489ccaadfaa11555bea0b5d41fce22bf418 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Thu, 3 Nov 2022 16:44:40 +0100 Subject: [PATCH 4/6] Added support for auto hiding a dock area / widget to a specific border via context menu --- demo/MainWindow.cpp | 1 + src/AutoHideSideBar.h | 3 --- src/DockAreaTitleBar.cpp | 17 ++++++++--------- src/DockAreaWidget.cpp | 22 ++++++++++------------ src/DockWidgetTab.cpp | 38 +++++++++++++++++++++++--------------- 5 files changed, 42 insertions(+), 39 deletions(-) diff --git a/demo/MainWindow.cpp b/demo/MainWindow.cpp index e46bd7c..f980b84 100644 --- a/demo/MainWindow.cpp +++ b/demo/MainWindow.cpp @@ -655,6 +655,7 @@ CMainWindow::CMainWindow(QWidget *parent) : // uncomment the following line to enable focus highlighting of the dock // widget that has the focus CDockManager::setConfigFlag(CDockManager::FocusHighlighting, true); + CDockManager::setConfigFlag(CDockManager::AlwaysShowTabs, true); // uncomment if you would like to enable dock widget auto hiding CDockManager::setAutoHideConfigFlags(CDockManager::DefaultAutoHideConfig); diff --git a/src/AutoHideSideBar.h b/src/AutoHideSideBar.h index 3e57e2b..b452ee0 100644 --- a/src/AutoHideSideBar.h +++ b/src/AutoHideSideBar.h @@ -150,9 +150,6 @@ public: * Setter for spacing property - sets the spacing */ void setSpacing(int Spacing); - -Q_SIGNALS: - void sideTabAutoHideToggleRequested(); }; } // namespace ads //----------------------------------------------------------------------------- diff --git a/src/DockAreaTitleBar.cpp b/src/DockAreaTitleBar.cpp index 951a42e..ed06c18 100644 --- a/src/DockAreaTitleBar.cpp +++ b/src/DockAreaTitleBar.cpp @@ -689,22 +689,22 @@ void CDockAreaTitleBar::contextMenuEvent(QContextMenuEvent* ev) return; } - bool IsAutoHide = d->DockArea->isAutoHide(); - bool IsTopLevelArea = d->DockArea->isTopLevelArea(); + const bool isAutoHide = d->DockArea->isAutoHide(); + const bool isTopLevelArea = d->DockArea->isTopLevelArea(); QAction* Action; QMenu Menu(this); - if (!IsTopLevelArea) + if (!isTopLevelArea) { - Action = Menu.addAction(IsAutoHide ? tr("Detach") : tr("Detach Group"), + Action = Menu.addAction(isAutoHide ? tr("Detach") : tr("Detach Group"), this, SLOT(onUndockButtonClicked())); Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable)); if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled)) { - Action = Menu.addAction(IsAutoHide ? tr("Dock") : tr("Auto Hide Group"), this, SLOT(onAutoHideDockAreaActionClicked())); + Action = Menu.addAction(isAutoHide ? tr("Dock") : tr("Auto Hide Group"), this, SLOT(onAutoHideDockAreaActionClicked())); auto AreaIsPinnable = d->DockArea->features().testFlag(CDockWidget::DockWidgetPinnable); Action->setEnabled(AreaIsPinnable); - if (!IsAutoHide) + if (!isAutoHide) { auto menu = Menu.addMenu(tr("Auto Hide Group To...")); menu->setEnabled(AreaIsPinnable); @@ -716,12 +716,11 @@ void CDockAreaTitleBar::contextMenuEvent(QContextMenuEvent* ev) } Menu.addSeparator(); } - Action = Menu.addAction(IsAutoHide ? tr("Close") : tr("Close Group"), this, SLOT(onCloseButtonClicked())); + Action = Menu.addAction(isAutoHide ? tr("Close") : tr("Close Group"), this, SLOT(onCloseButtonClicked())); Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetClosable)); - if (!IsAutoHide) + if (!isAutoHide && !isTopLevelArea) { Action = Menu.addAction(tr("Close Other Groups"), d->DockArea, SLOT(closeOtherAreas())); - Action->setEnabled(!IsTopLevelArea); } Menu.exec(ev->globalPos()); } diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index 4054ec1..1697ad6 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -537,7 +537,7 @@ void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget) { setCurrentDockWidget(NextOpenDockWidget); } - else if (d->ContentsLayout->isEmpty() && DockContainer->dockAreaCount() >= 1) // Don't remove empty dock areas that are auto hidden, they'll be deleted by the auto hide dock + else if (d->ContentsLayout->isEmpty() && DockContainer->dockAreaCount() >= 1) { ADS_PRINT("Dock Area empty"); DockContainer->removeDockArea(this); @@ -827,22 +827,20 @@ void CDockAreaWidget::updateTitleBarVisibility() return; } - if (CDockManager::testConfigFlag(CDockManager::AlwaysShowTabs)) - { - return; - } - if (!d->TitleBar) { return; } - bool Hidden = Container->hasTopLevelDockWidget() && (Container->isFloating() - || CDockManager::testConfigFlag(CDockManager::HideSingleCentralWidgetTitleBar)); - Hidden |= (d->Flags.testFlag(HideSingleWidgetTitleBar) && openDockWidgetsCount() == 1); - bool IsAutoHide = isAutoHide(); - Hidden &= !IsAutoHide; // Titlebar must always be visible when auto hidden so it can be dragged - d->TitleBar->setVisible(!Hidden); + bool IsAutoHide = isAutoHide(); + if (!CDockManager::testConfigFlag(CDockManager::AlwaysShowTabs)) + { + bool Hidden = Container->hasTopLevelDockWidget() && (Container->isFloating() + || CDockManager::testConfigFlag(CDockManager::HideSingleCentralWidgetTitleBar)); + Hidden |= (d->Flags.testFlag(HideSingleWidgetTitleBar) && openDockWidgetsCount() == 1); + Hidden &= !IsAutoHide; // Titlebar must always be visible when auto hidden so it can be dragged + d->TitleBar->setVisible(!Hidden); + } if (isAutoHideFeatureEnabled()) { diff --git a/src/DockWidgetTab.cpp b/src/DockWidgetTab.cpp index 844a9fb..5d1ce04 100644 --- a/src/DockWidgetTab.cpp +++ b/src/DockWidgetTab.cpp @@ -518,32 +518,40 @@ void CDockWidgetTab::contextMenuEvent(QContextMenuEvent* ev) } d->saveDragStartMousePosition(ev->globalPos()); - QMenu Menu(this); const bool isFloatable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable); const bool isNotOnlyTabInContainer = !d->DockArea->dockContainer()->hasTopLevelDockWidget(); - + const bool isTopLevelArea = d->DockArea->isTopLevelArea(); const bool isDetachable = isFloatable && isNotOnlyTabInContainer; + QAction* Action; + QMenu Menu(this); - auto Action = Menu.addAction(tr("Detach"), this, SLOT(detachDockWidget())); - Action->setEnabled(isDetachable); - if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled)) + if (!isTopLevelArea) { - Action = Menu.addAction(tr("Auto Hide"), this, SLOT(autoHideDockWidget())); - auto IsPinnable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetPinnable); - Action->setEnabled(IsPinnable); + Action = Menu.addAction(tr("Detach"), this, SLOT(detachDockWidget())); + Action->setEnabled(isDetachable); + if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled)) + { + Action = Menu.addAction(tr("Auto Hide"), this, SLOT(autoHideDockWidget())); + auto IsPinnable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetPinnable); + Action->setEnabled(IsPinnable); - auto menu = Menu.addMenu(tr("Auto Hide To...")); - menu->setEnabled(IsPinnable); - d->createAutoHideToAction(tr("Top"), SideBarTop, menu); - d->createAutoHideToAction(tr("Left"), SideBarLeft, menu); - d->createAutoHideToAction(tr("Right"), SideBarRight, menu); - d->createAutoHideToAction(tr("Bottom"), SideBarBottom, menu); + auto menu = Menu.addMenu(tr("Auto Hide To...")); + menu->setEnabled(IsPinnable); + d->createAutoHideToAction(tr("Top"), SideBarTop, menu); + d->createAutoHideToAction(tr("Left"), SideBarLeft, menu); + d->createAutoHideToAction(tr("Right"), SideBarRight, menu); + d->createAutoHideToAction(tr("Bottom"), SideBarBottom, menu); + } } + Menu.addSeparator(); Action = Menu.addAction(tr("Close"), this, SIGNAL(closeRequested())); Action->setEnabled(isClosable()); - Menu.addAction(tr("Close Others"), this, SIGNAL(closeOtherTabsRequested())); + if (d->DockArea->openDockWidgetsCount() > 1) + { + Action = Menu.addAction(tr("Close Others"), this, SIGNAL(closeOtherTabsRequested())); + } Menu.exec(ev->globalPos()); } From 5e59a6dc3a44be277892da0186eaea068262c873 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Thu, 3 Nov 2022 16:49:20 +0100 Subject: [PATCH 5/6] Removed debug output --- src/AutoHideDockContainer.cpp | 1 - src/AutoHideSideBar.cpp | 4 +--- src/AutoHideTab.cpp | 2 +- src/DockAreaTitleBar.cpp | 2 -- src/DockAreaWidget.cpp | 1 - src/FloatingDockContainer.cpp | 1 - 6 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/AutoHideDockContainer.cpp b/src/AutoHideDockContainer.cpp index 6033596..f38c2f9 100644 --- a/src/AutoHideDockContainer.cpp +++ b/src/AutoHideDockContainer.cpp @@ -277,7 +277,6 @@ void CAutoHideDockContainer::updateSize() //============================================================================ CAutoHideDockContainer::~CAutoHideDockContainer() { - qDebug() << "~CAutoHideDockContainer()" ADS_PRINT("~CAutoHideDockContainer"); // Remove event filter in case there are any queued messages diff --git a/src/AutoHideSideBar.cpp b/src/AutoHideSideBar.cpp index fdb98ed..066c060 100644 --- a/src/AutoHideSideBar.cpp +++ b/src/AutoHideSideBar.cpp @@ -193,8 +193,6 @@ CAutoHideSideBar::CAutoHideSideBar(CDockContainerWidget* parent, SideBarLocation setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); } - qDebug() << "d->TabsLayout->count " << d->TabsLayout->count(); - hide(); } @@ -202,7 +200,7 @@ CAutoHideSideBar::CAutoHideSideBar(CDockContainerWidget* parent, SideBarLocation //============================================================================ CAutoHideSideBar::~CAutoHideSideBar() { - qDebug() << "~CSideTabBar() "; + ADS_PRINT("~CSideTabBar()"); // The SideTabeBar is not the owner of the tabs and to prevent deletion // we set the parent here to nullptr to remove it from the children auto Tabs = findChildren(QString(), Qt::FindDirectChildrenOnly); diff --git a/src/AutoHideTab.cpp b/src/AutoHideTab.cpp index b8fbb2c..85a17f8 100644 --- a/src/AutoHideTab.cpp +++ b/src/AutoHideTab.cpp @@ -147,7 +147,7 @@ CAutoHideTab::CAutoHideTab(QWidget* parent) : //============================================================================ CAutoHideTab::~CAutoHideTab() { - qDebug() << "~CDockWidgetSideTab()"; + ADS_PRINT("~CDockWidgetSideTab()"); delete d; } diff --git a/src/DockAreaTitleBar.cpp b/src/DockAreaTitleBar.cpp index ed06c18..91737c2 100644 --- a/src/DockAreaTitleBar.cpp +++ b/src/DockAreaTitleBar.cpp @@ -513,7 +513,6 @@ void CDockAreaTitleBar::onAutoHideButtonClicked() } else { - qDebug() << "d->DockArea->currentDockWidget()->toggleAutoHide()"; d->DockArea->currentDockWidget()->toggleAutoHide(); } } @@ -529,7 +528,6 @@ void CDockAreaTitleBar::onAutoHideDockAreaActionClicked() //============================================================================ void CDockAreaTitleBar::onAutoHideToActionClicked() { - qDebug() << "CDockAreaTitleBar::onAutoHideToActionClicked()"; int Location = sender()->property(LocationProperty).toInt(); d->DockArea->toggleAutoHide((SideBarLocation)Location); } diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index 1697ad6..5d7df44 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -984,7 +984,6 @@ bool CDockAreaWidget::restoreState(CDockingStateReader& s, CDockAreaWidget*& Cre // We hide the DockArea here to prevent the short display (the flashing) // of the dock areas during application startup DockArea->hide(); - qDebug() << "DockArea->addDockWidget " << DockWidget->windowTitle(); DockArea->addDockWidget(DockWidget); DockWidget->setToggleViewActionChecked(!Closed); DockWidget->setClosedState(Closed); diff --git a/src/FloatingDockContainer.cpp b/src/FloatingDockContainer.cpp index 571c5f1..2152b6b 100644 --- a/src/FloatingDockContainer.cpp +++ b/src/FloatingDockContainer.cpp @@ -721,7 +721,6 @@ CFloatingDockContainer::CFloatingDockContainer(CDockWidget *DockWidget) : //============================================================================ CFloatingDockContainer::~CFloatingDockContainer() { - qDebug() << "~CFloatingDockContainer " << windowTitle(); ADS_PRINT("~CFloatingDockContainer"); if (d->DockManager) { From 27d71eecac0f993eeeed4548da65c9545990ec74 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Thu, 3 Nov 2022 20:00:03 +0100 Subject: [PATCH 6/6] Fixed restoreDockWidgetsOpenState() function to delete legacy auto hide widgets --- src/DockManager.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/DockManager.cpp b/src/DockManager.cpp index 08b7a9c..27fcf09 100644 --- a/src/DockManager.cpp +++ b/src/DockManager.cpp @@ -156,7 +156,7 @@ struct DockManagerPrivate { for (auto DockWidget : DockWidgetsMap) { - DockWidget->setProperty("dirty", true); + DockWidget->setProperty(internal::DirtyProperty, true); } } @@ -349,6 +349,12 @@ void DockManagerPrivate::restoreDockWidgetsOpenState() { if (DockWidget->property(internal::DirtyProperty).toBool()) { + // If the DockWidget is an auto hide widget that is not assigned yet, + // then we need to delete the auto hide container now + if (DockWidget->isAutoHide()) + { + DockWidget->autoHideDockContainer()->cleanupAndDelete(); + } DockWidget->flagAsUnassigned(); Q_EMIT DockWidget->viewToggled(false); }