From 8ea7c265a7cad33caa9842f025ca2430a88e369c Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Wed, 27 Nov 2019 15:50:18 +0100 Subject: [PATCH] Fixed emission of top level changed signal to properly support transparent docking --- src/DockContainerWidget.cpp | 84 +++++++++++++++++++++++++---------- src/DockManager.h | 2 + src/DockWidgetTab.cpp | 2 +- src/FloatingDockContainer.cpp | 10 +++++ 4 files changed, 74 insertions(+), 24 deletions(-) diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index 44bba5b..75c293b 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -81,6 +81,12 @@ namespace ads { static unsigned int zOrderCounter = 0; +enum eDropMode +{ + DropModeIntoArea,///< drop widget into a dock area + DropModeIntoContainer,///< drop into container + DropModeInvalid///< invalid mode - do not drop +}; /** * Converts dock area ID to an index for array access @@ -234,6 +240,11 @@ public: */ void dumpRecursive(int level, QWidget* widget); + /** + * Calculate the drop mode from the given target position + */ + eDropMode getDropMode(const QPoint& TargetPos); + /** * Initializes the visible dock area count variable if it is not initialized * yet @@ -312,6 +323,46 @@ DockContainerWidgetPrivate::DockContainerWidgetPrivate(CDockContainerWidget* _pu } +//============================================================================ +eDropMode DockContainerWidgetPrivate::getDropMode(const QPoint& TargetPos) +{ + CDockAreaWidget* DockArea = _this->dockAreaAt(TargetPos); + auto dropArea = InvalidDockWidgetArea; + auto ContainerDropArea = DockManager->containerOverlay()->dropAreaUnderCursor(); + + if (DockArea) + { + auto dropOverlay = DockManager->dockAreaOverlay(); + dropOverlay->setAllowedAreas(AllDockAreas); + dropArea = dropOverlay->showOverlay(DockArea); + if (ContainerDropArea != InvalidDockWidgetArea && + ContainerDropArea != dropArea) + { + dropArea = InvalidDockWidgetArea; + } + + if (dropArea != InvalidDockWidgetArea) + { + ADS_PRINT("Dock Area Drop Content: " << dropArea); + return DropModeIntoArea; + } + } + + // mouse is over container + if (InvalidDockWidgetArea == dropArea) + { + dropArea = ContainerDropArea; + ADS_PRINT("Container Drop Content: " << dropArea); + if (dropArea != InvalidDockWidgetArea) + { + return DropModeIntoContainer; + } + } + + return DropModeInvalid; +} + + //============================================================================ void DockContainerWidgetPrivate::onVisibleDockAreaCountChanged() { @@ -340,8 +391,6 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float CDockContainerWidget* FloatingDockContainer = FloatingWidget->dockContainer(); auto NewDockAreas = FloatingDockContainer->findChildren( QString(), Qt::FindChildrenRecursively); - CDockWidget* SingleDroppedDockWidget = FloatingDockContainer->topLevelDockWidget(); - CDockWidget* SingleDockWidget = _this->topLevelDockWidget(); QSplitter* Splitter = RootSplitter; if (DockAreas.count() <= 1) @@ -378,8 +427,6 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float RootSplitter = Splitter; addDockAreasToList(NewDockAreas); FloatingWidget->deleteLater(); - CDockWidget::emitTopLevelEventForWidget(SingleDroppedDockWidget, false); - CDockWidget::emitTopLevelEventForWidget(SingleDockWidget, false); // If we dropped the floating widget into the main dock container that does // not contain any dock widgets, then splitter is invisible and we need to @@ -613,6 +660,7 @@ void DockContainerWidgetPrivate::moveToContainer(QWidget* Widget, DockWidgetArea CDockWidget* DroppedDockWidget = qobject_cast(Widget); CDockAreaWidget* DroppedDockArea = qobject_cast(Widget); CDockAreaWidget* NewDockArea; + if (DroppedDockWidget) { NewDockArea = new CDockAreaWidget(DockManager, _this); @@ -630,7 +678,6 @@ void DockContainerWidgetPrivate::moveToContainer(QWidget* Widget, DockWidgetArea } addDockArea(NewDockArea, area); - //NewDockArea->updateTitleBarVisibility(); LastAddedAreaCache[areaIdToIndex(area)] = NewDockArea; } @@ -1324,11 +1371,11 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi const QPoint& TargetPos) { ADS_PRINT("CDockContainerWidget::dropFloatingWidget"); + CDockWidget* SingleDroppedDockWidget = FloatingWidget->topLevelDockWidget(); + CDockWidget* SingleDockWidget = topLevelDockWidget(); CDockAreaWidget* DockArea = dockAreaAt(TargetPos); auto dropArea = InvalidDockWidgetArea; auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor(); - CDockWidget* FloatingTopLevelDockWidget = FloatingWidget->topLevelDockWidget(); - CDockWidget* TopLevelDockWidget = topLevelDockWidget(); if (DockArea) { @@ -1359,19 +1406,13 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi } } + // If we dropped a floating widget with only one single dock widget, then we + // drop a top level widget that changes from floating to docked now + CDockWidget::emitTopLevelEventForWidget(SingleDroppedDockWidget, false); + // If there was a top level widget before the drop, then it is not top // level widget anymore - if (TopLevelDockWidget) - { - TopLevelDockWidget->emitTopLevelChanged(false); - } - - // If we drop a floating widget with only one single dock widget, then we - // drop a top level widget that changes from floating to docked now - if (FloatingTopLevelDockWidget) - { - FloatingTopLevelDockWidget->emitTopLevelChanged(false); - } + CDockWidget::emitTopLevelEventForWidget(SingleDockWidget, false); } @@ -1379,10 +1420,10 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi void CDockContainerWidget::dropWidget(QWidget* Widget, const QPoint& TargetPos) { ADS_PRINT("CDockContainerWidget::dropFloatingWidget"); + CDockWidget* SingleDockWidget = topLevelDockWidget(); CDockAreaWidget* DockArea = dockAreaAt(TargetPos); auto dropArea = InvalidDockWidgetArea; auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor(); - CDockWidget* TopLevelDockWidget = topLevelDockWidget(); if (DockArea) { @@ -1415,10 +1456,7 @@ void CDockContainerWidget::dropWidget(QWidget* Widget, const QPoint& TargetPos) // If there was a top level widget before the drop, then it is not top // level widget anymore - if (TopLevelDockWidget) - { - TopLevelDockWidget->emitTopLevelChanged(false); - } + CDockWidget::emitTopLevelEventForWidget(SingleDockWidget, false); } diff --git a/src/DockManager.h b/src/DockManager.h index 49f21ff..d96b6f3 100644 --- a/src/DockManager.h +++ b/src/DockManager.h @@ -52,6 +52,7 @@ struct DockManagerPrivate; class CFloatingDockContainer; struct FloatingDockContainerPrivate; class CDockContainerWidget; +class DockContainerWidgetPrivate; class CDockOverlay; class CDockAreaTabBar; class CDockWidgetTab; @@ -80,6 +81,7 @@ private: friend class CFloatingDockContainer; friend struct FloatingDockContainerPrivate; friend class CDockContainerWidget; + friend class DockContainerWidgetPrivate; friend class CDockAreaTabBar; friend class CDockWidgetTab; friend struct DockAreaWidgetPrivate; diff --git a/src/DockWidgetTab.cpp b/src/DockWidgetTab.cpp index f3c74df..4701f68 100644 --- a/src/DockWidgetTab.cpp +++ b/src/DockWidgetTab.cpp @@ -270,7 +270,7 @@ bool DockWidgetTabPrivate::startFloating(eDragState DraggingState) { FloatingWidget->startFloating(DragStartMousePosition, Size, DraggingInactive, nullptr); } - DockWidget->emitTopLevelChanged(true); + return true; } diff --git a/src/FloatingDockContainer.cpp b/src/FloatingDockContainer.cpp index eb2cab9..6fa861f 100644 --- a/src/FloatingDockContainer.cpp +++ b/src/FloatingDockContainer.cpp @@ -275,6 +275,11 @@ CFloatingDockContainer::CFloatingDockContainer(CDockAreaWidget *DockArea) : #ifdef Q_OS_LINUX d->TitleBar->enableCloseButton(isClosable()); #endif + auto TopLevelDockWidget = topLevelDockWidget(); + if (TopLevelDockWidget) + { + TopLevelDockWidget->emitTopLevelChanged(true); + } } //============================================================================ @@ -285,6 +290,11 @@ CFloatingDockContainer::CFloatingDockContainer(CDockWidget *DockWidget) : #ifdef Q_OS_LINUX d->TitleBar->enableCloseButton(isClosable()); #endif + auto TopLevelDockWidget = topLevelDockWidget(); + if (TopLevelDockWidget) + { + TopLevelDockWidget->emitTopLevelChanged(true); + } } //============================================================================