From c0247fc02a0ebcda4088c5a14ff8922948895d57 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Fri, 4 Nov 2022 08:51:17 +0100 Subject: [PATCH] Added option ShowAutoHideOnMouseOver that enables showing of auto hide widgets by hovering over auto hide tab --- src/AutoHideDockContainer.cpp | 52 +++++++++++++++++--- src/AutoHideDockContainer.h | 10 ++-- src/AutoHideTab.cpp | 45 +++++++++++++++++ src/AutoHideTab.h | 3 ++ src/DockContainerWidget.cpp | 93 +++++++++++++++++++++++++++++++++-- src/DockContainerWidget.h | 13 ++++- src/DockManager.h | 1 + 7 files changed, 202 insertions(+), 15 deletions(-) diff --git a/src/AutoHideDockContainer.cpp b/src/AutoHideDockContainer.cpp index f38c2f9..7ddec6f 100644 --- a/src/AutoHideDockContainer.cpp +++ b/src/AutoHideDockContainer.cpp @@ -147,7 +147,7 @@ struct AutoHideDockContainerPrivate */ void updateResizeHandleSizeLimitMax() { - auto Rect = _this->parentContainer()->contentRect(); + auto Rect = _this->dockContainer()->contentRect(); const auto maxResizeHandleSize = ResizeHandle->orientation() == Qt::Horizontal ? Rect.width() : Rect.height(); ResizeHandle->setMaxResizeSize(maxResizeHandleSize - ResizeMargin); @@ -161,6 +161,18 @@ struct AutoHideDockContainerPrivate return isHorizontalArea(SideTabBarArea); } + /** + * Forward this event to the dock container + */ + void forwardEventToDockContainer(QEvent* event) + { + auto DockContainer = _this->dockContainer(); + if (DockContainer) + { + DockContainer->handleAutoHideWidgetEvent(event, _this); + } + } + }; // struct AutoHideDockContainerPrivate @@ -174,7 +186,7 @@ AutoHideDockContainerPrivate::AutoHideDockContainerPrivate( //============================================================================ -CDockContainerWidget* CAutoHideDockContainer::parentContainer() const +CDockContainerWidget* CAutoHideDockContainer::dockContainer() const { if (d->DockArea) { @@ -231,7 +243,7 @@ CAutoHideDockContainer::CAutoHideDockContainer(CDockWidget* DockWidget, SideBarL //============================================================================ void CAutoHideDockContainer::updateSize() { - auto dockContainerParent = parentContainer(); + auto dockContainerParent = dockContainer(); if (!dockContainerParent) { return; @@ -281,9 +293,9 @@ CAutoHideDockContainer::~CAutoHideDockContainer() // Remove event filter in case there are any queued messages qApp->removeEventFilter(this); - if (parentContainer()) + if (dockContainer()) { - parentContainer()->removeAutoHideWidget(this); + dockContainer()->removeAutoHideWidget(this); } if (d->SideTab) @@ -297,7 +309,7 @@ CAutoHideDockContainer::~CAutoHideDockContainer() //============================================================================ CAutoHideSideBar* CAutoHideDockContainer::sideBar() const { - return parentContainer()->sideTabBar(d->SideTabBarArea); + return dockContainer()->sideTabBar(d->SideTabBarArea); } @@ -366,7 +378,7 @@ void CAutoHideDockContainer::moveContentsToParent() // location like it had as a auto hide widget. This brings the least surprise // to the user and he does not have to search where the widget was inserted. d->DockWidget->setDockArea(nullptr); - parentContainer()->addDockWidget(d->getDockWidgetArea(d->SideTabBarArea), d->DockWidget); + dockContainer()->addDockWidget(d->getDockWidgetArea(d->SideTabBarArea), d->DockWidget); } @@ -479,7 +491,7 @@ bool CAutoHideDockContainer::eventFilter(QObject* watched, QEvent* event) } else if (event->type() == QEvent::MouseButtonPress) { - auto Container = parentContainer(); + auto Container = dockContainer(); // First we check, if the mouse button press is inside the container // widget. If it is not, i.e. if someone resizes the main window or // clicks into the application menu or toolbar, then we ignore the @@ -543,5 +555,29 @@ void CAutoHideDockContainer::resizeEvent(QResizeEvent* event) } } + +//============================================================================ +void CAutoHideDockContainer::leaveEvent(QEvent *event) +{ + d->forwardEventToDockContainer(event); + Super::leaveEvent(event); +} + + +//============================================================================ +void CAutoHideDockContainer::enterEvent(QEvent *event) +{ + d->forwardEventToDockContainer(event); + Super::enterEvent(event); +} + + +//============================================================================ +void CAutoHideDockContainer::hideEvent(QHideEvent *event) +{ + d->forwardEventToDockContainer(event); + Super::hideEvent(event); +} + } diff --git a/src/AutoHideDockContainer.h b/src/AutoHideDockContainer.h index 9823ac0..7c222f4 100644 --- a/src/AutoHideDockContainer.h +++ b/src/AutoHideDockContainer.h @@ -61,8 +61,12 @@ private: friend SideTabBarPrivate; protected: - bool eventFilter(QObject* watched, QEvent* event) override; - void resizeEvent(QResizeEvent* event) override; + virtual bool eventFilter(QObject* watched, QEvent* event) override; + virtual void resizeEvent(QResizeEvent* event) override; + virtual void leaveEvent(QEvent *event) override; + virtual void enterEvent(QEvent *event) override; + virtual void hideEvent(QHideEvent *event) override; + /** * Updates the size considering the size limits and the resize margins @@ -126,7 +130,7 @@ public: /** * Returns the parent container that hosts this auto hide container */ - CDockContainerWidget* parentContainer() const; + CDockContainerWidget* dockContainer() const; /** * Moves the contents to the parent container widget diff --git a/src/AutoHideTab.cpp b/src/AutoHideTab.cpp index 85a17f8..9a81260 100644 --- a/src/AutoHideTab.cpp +++ b/src/AutoHideTab.cpp @@ -30,6 +30,7 @@ #include "AutoHideTab.h" #include +#include #include "AutoHideDockContainer.h" #include "AutoHideSideBar.h" @@ -59,6 +60,26 @@ struct AutoHideTabPrivate * the side bar */ void updateOrientation(); + + /** + * Convenience function to ease dock container access + */ + CDockContainerWidget* dockContainer() const + { + return DockWidget ? DockWidget->dockContainer() : nullptr; + } + + /** + * Forward this event to the dock container + */ + void forwardEventToDockContainer(QEvent* event) + { + auto DockContainer = dockContainer(); + if (DockContainer) + { + DockContainer->handleAutoHideWidgetEvent(event, _this); + } + } }; // struct DockWidgetTabPrivate @@ -228,4 +249,28 @@ void CAutoHideTab::setDockWidget(CDockWidget* DockWidget) setIcon(d->DockWidget->icon()); } + +//============================================================================ +void CAutoHideTab::enterEvent(QEvent *event) +{ + d->forwardEventToDockContainer(event); + Super::enterEvent(event); +} + + +//============================================================================ +void CAutoHideTab::leaveEvent(QEvent *event) +{ + d->forwardEventToDockContainer(event); + Super::leaveEvent(event); +} + + +//============================================================================ +void CAutoHideTab::mousePressEvent(QMouseEvent* event) +{ + d->forwardEventToDockContainer(event); + Super::mousePressEvent(event); +} + } diff --git a/src/AutoHideTab.h b/src/AutoHideTab.h index d3783b9..2a942b4 100644 --- a/src/AutoHideTab.h +++ b/src/AutoHideTab.h @@ -67,6 +67,9 @@ protected: void setSideBar(CAutoHideSideBar *SideTabBar); void removeFromSideBar(); + virtual void enterEvent(QEvent *event) override; + virtual void leaveEvent(QEvent *event) override; + virtual void mousePressEvent(QMouseEvent* event) override; public: using Super = CPushButton; diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index 43b0594..141debc 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -28,9 +28,6 @@ //============================================================================ // INCLUDES //============================================================================ -#include -#include -#include #include "DockContainerWidget.h" #include @@ -42,6 +39,10 @@ #include #include #include +#include +#include +#include +#include #include "DockManager.h" #include "DockAreaWidget.h" @@ -54,6 +55,9 @@ #include "DockWidgetTab.h" #include "DockAreaTitleBar.h" #include "DockFocusController.h" +#include "AutoHideDockContainer.h" +#include "AutoHideSideBar.h" +#include "AutoHideTab.h" #include #include @@ -146,6 +150,9 @@ public: CDockAreaWidget* LastAddedAreaCache[5]; int VisibleDockAreaCount = -1; CDockAreaWidget* TopLevelDockArea = nullptr; + QTimer DelayedAutoHideTimer; + CAutoHideTab* DelayedAutoHideTab; + bool DelayedAutoHideShow = false; /** * Private data constructor @@ -371,6 +378,14 @@ DockContainerWidgetPrivate::DockContainerWidgetPrivate(CDockContainerWidget* _pu _this(_public) { std::fill(std::begin(LastAddedAreaCache),std::end(LastAddedAreaCache), nullptr); + DelayedAutoHideTimer.setSingleShot(true); + DelayedAutoHideTimer.setInterval(500); + QObject::connect(&DelayedAutoHideTimer, &QTimer::timeout, [this](){ + qDebug() << "DelayedAutoHideTimer timeout"; + auto GlobalPos = DelayedAutoHideTab->mapToGlobal(QPoint(0, 0)); + qApp->sendEvent(DelayedAutoHideTab, new QMouseEvent(QEvent::MouseButtonPress, + QPoint(0, 0), GlobalPos, Qt::LeftButton, {Qt::LeftButton}, Qt::NoModifier)); + }); } @@ -2045,6 +2060,78 @@ CDockManager* CDockContainerWidget::dockManager() const { return d->DockManager; } + + +//=========================================================================== +void CDockContainerWidget::handleAutoHideWidgetEvent(QEvent* e, QWidget* w) +{ + if (!CDockManager::testAutoHideConfigFlag(CDockManager::ShowAutoHideOnMouseOver)) + { + return; + } + + if (dockManager()->isRestoringState()) + { + return; + } + + auto AutoHideTab = qobject_cast(w); + if (AutoHideTab) + { + qDebug() << "Event AutoHideTab " << e; + switch (e->type()) + { + case QEvent::Enter: + if (!AutoHideTab->dockWidget()->isVisible()) + { + d->DelayedAutoHideTab = AutoHideTab; + d->DelayedAutoHideShow = true; + d->DelayedAutoHideTimer.start(); + } + else + { + d->DelayedAutoHideTimer.stop(); + } + break; + + case QEvent::Leave: + case QEvent::MouseButtonPress: + d->DelayedAutoHideTimer.stop(); + break; + + default: + break; + } + return; + } + + auto AutoHideContainer = qobject_cast(w); + if (AutoHideContainer) + { + qDebug() << "Event AutoHideContainer " << e; + switch (e->type()) + { + case QEvent::Enter: + case QEvent::Hide: + d->DelayedAutoHideTimer.stop(); + break; + + case QEvent::Leave: + if (AutoHideContainer->isVisible()) + { + d->DelayedAutoHideTab = AutoHideContainer->autoHideTab(); + d->DelayedAutoHideShow = false; + d->DelayedAutoHideTimer.start(); + } + break; + + default: + break; + } + return; + return; + } +} } // namespace ads //--------------------------------------------------------------------------- diff --git a/src/DockContainerWidget.h b/src/DockContainerWidget.h index 247c698..dd73e50 100644 --- a/src/DockContainerWidget.h +++ b/src/DockContainerWidget.h @@ -52,6 +52,9 @@ class CFloatingDragPreview; struct FloatingDragPreviewPrivate; class CDockingStateReader; class CAutoHideSideBar; +class CAutoHideTab; +struct AutoHideTabPrivate; +struct AutoHideDockContainerPrivate; /** @@ -76,7 +79,10 @@ private: friend class CDockWidget; friend class CFloatingDragPreview; friend struct FloatingDragPreviewPrivate; - friend class CAutoHideDockContainer; + friend CAutoHideDockContainer; + friend CAutoHideTab; + friend AutoHideTabPrivate; + friend AutoHideDockContainerPrivate; protected: /** @@ -190,6 +196,11 @@ protected: */ void removeAutoHideWidget(CAutoHideDockContainer* AutoHideWidget); + /** + * Handles widget events of auto hide widgets to trigger delayed show + * or hide actions for auto hide container on auto hide tab mouse over + */ + void handleAutoHideWidgetEvent(QEvent* e, QWidget* w); public: /** diff --git a/src/DockManager.h b/src/DockManager.h index ed6d2cf..ceb16f3 100644 --- a/src/DockManager.h +++ b/src/DockManager.h @@ -243,6 +243,7 @@ public: BottomSideBarIconOnly = 0x40,//!< If the flag is set bottom side show only icon if a the dock widget has an icon assigned TopSideBarIconOnly = 0x80, //!< If the flag is set top side bar show only icon if a the dock widget has an icon assigned AutoHideSideBarsIconOnly = LeftSideBarIconOnly | RightSideBarIconOnly | BottomSideBarIconOnly | TopSideBarIconOnly, + ShowAutoHideOnMouseOver = 0x100, ///< show the auto hide window on mouse over tab and hide it if mouse leaves auto hide container DefaultAutoHideConfig = AutoHideFeatureEnabled | DockAreaHasAutoHideButton ///< the default configuration for left and right side bars