diff --git a/src/DockWidgetBase.cpp b/src/DockWidgetBase.cpp index 4375a669..e58aa82d 100644 --- a/src/DockWidgetBase.cpp +++ b/src/DockWidgetBase.cpp @@ -66,8 +66,10 @@ public: Q_EMIT q->isFloatingChanged(checked); // When floating, we remove from the sidebar if (checked && q->isOpen()) { - if (SideBar *sb = DockRegistry::self()->sideBarForDockWidget(q)) + if (SideBar *sb = DockRegistry::self()->sideBarForDockWidget(q)) { + sb->mainWindow()->clearSideBarOverlay(/* deleteFrame=*/false); sb->removeDockWidget(q); + } } }); diff --git a/src/MainWindowBase.cpp b/src/MainWindowBase.cpp index 2ddd690e..b0d6457a 100644 --- a/src/MainWindowBase.cpp +++ b/src/MainWindowBase.cpp @@ -486,16 +486,25 @@ void MainWindowBase::toggleOverlayOnSideBar(DockWidgetBase *dw) } } -void MainWindowBase::clearSideBarOverlay() +void MainWindowBase::clearSideBarOverlay(bool deleteFrame) { if (!d->m_overlayedDockWidget) return; Frame *frame = d->m_overlayedDockWidget->frame(); - d->m_overlayedDockWidget->setParent(nullptr); - Q_EMIT d->m_overlayedDockWidget->isOverlayedChanged(false); - d->m_overlayedDockWidget = nullptr; - delete frame; + frame->unoverlay(); + + if (deleteFrame) { + d->m_overlayedDockWidget->setParent(nullptr); + Q_EMIT d->m_overlayedDockWidget->isOverlayedChanged(false); + d->m_overlayedDockWidget = nullptr; + delete frame; + } else { + // No cleanup, just unset. When we drag the overlay it becomes a normal floating window + // meaning we reuse Frame. Don't delete it. + Q_EMIT d->m_overlayedDockWidget->isOverlayedChanged(false); + d->m_overlayedDockWidget = nullptr; + } } SideBar *MainWindowBase::sideBarForDockWidget(const DockWidgetBase *dw) const diff --git a/src/MainWindowBase.h b/src/MainWindowBase.h index b7ec660b..8c3fe797 100644 --- a/src/MainWindowBase.h +++ b/src/MainWindowBase.h @@ -156,7 +156,7 @@ public: void toggleOverlayOnSideBar(DockWidgetBase *); /// @brief closes any overlayed dock widget. The sidebar still displays them as button. - void clearSideBarOverlay(); + void clearSideBarOverlay(bool deleteFrame = true); /// @brief Returns the sidebar this dockwidget is in. nullptr if not in any. SideBar *sideBarForDockWidget(const DockWidgetBase *) const; diff --git a/src/private/Frame.cpp b/src/private/Frame.cpp index 030c7aef..d7d8db8b 100644 --- a/src/private/Frame.cpp +++ b/src/private/Frame.cpp @@ -577,6 +577,11 @@ bool Frame::isOverlayed() const return m_options & FrameOption_IsOverlayed; } +void Frame::unoverlay() +{ + m_options &= ~FrameOption_IsOverlayed; +} + bool Frame::isFloating() const { if (isInMainWindow()) diff --git a/src/private/Frame_p.h b/src/private/Frame_p.h index c0193d53..27a8d61e 100644 --- a/src/private/Frame_p.h +++ b/src/private/Frame_p.h @@ -127,6 +127,10 @@ public: ///@brief Returns whether this frame is overlayed on top of the MainWindow (auto-hide feature); bool isOverlayed() const; + ///@brief clears the FrameOption_IsOverlayed flag. + /// For example, if you drag a side-bar overlay, then it becomes a normal floating window + void unoverlay(); + /** * @brief Returns whether this frame is floating. A floating frame isn't attached to any other MainWindow, * and if it's attached to a FloatingWindow then it's considered floating if it's the only frame in that Window. @@ -295,7 +299,7 @@ private: bool event(QEvent *) override; TitleBar *const m_titleBar; DropArea *m_dropArea = nullptr; - const FrameOptions m_options; + FrameOptions m_options = FrameOption_None; QPointer m_layoutItem; bool m_updatingTitleBar = false; bool m_beingDeleted = false;