From ee97b03e5336a085f6c868800a79b124f606fc76 Mon Sep 17 00:00:00 2001 From: Syarif Fakhri Date: Wed, 14 Sep 2022 12:16:36 +0800 Subject: [PATCH] Fix crash when restoring state - when restoring state, the old dock widgets would remove themselves from their old dock areas and add themselves to the new dock areas. The old dock areas that are empty would then delete themselves. - That is a problem when the old overlay dock container would still try to access the old dock areas, not knowing their deleted, causing a crash. --- src/DockContainerWidget.cpp | 1 + src/OverlayDockContainer.cpp | 34 ++++++++++++++++++++++++++++++---- src/OverlayDockContainer.h | 6 ++++++ 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index bcf53bd..77f2d09 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -1666,6 +1666,7 @@ void CDockContainerWidget::removeDockArea(CDockAreaWidget* area) CDockWidget::emitTopLevelEventForWidget(TopLevelWidget, true); dumpLayout(); d->emitDockAreasRemoved(); + area->overlayDockContainer()->clearDockArea(); area->setOverlayDockContainer(nullptr); area->updateAutoHideButtonCheckState(); area->updateTitleBarButtonToolTip(); diff --git a/src/OverlayDockContainer.cpp b/src/OverlayDockContainer.cpp index 1aca25e..cec961d 100644 --- a/src/OverlayDockContainer.cpp +++ b/src/OverlayDockContainer.cpp @@ -158,6 +158,11 @@ COverlayDockContainer::COverlayDockContainer(CDockManager* DockManager, CDockWid //============================================================================ void COverlayDockContainer::updateMask() { + if (d->DockArea == nullptr) + { + return; + } + const auto rect = d->DockArea->frameGeometry(); const auto topLeft = rect.topLeft(); const auto handleSize = d->Splitter->handleWidth(); @@ -222,6 +227,8 @@ CDockWidget* COverlayDockContainer::dockWidget() const //============================================================================ void COverlayDockContainer::addDockWidget(CDockWidget* DockWidget) { + Q_ASSERT_X(d->DockArea != nullptr, "COverlayDockContainer::addDockWidget", "You should not be using the overlay dock container after the dock area is set to nullptr."); + if (d->DockWidget) { // Remove the old dock widget at this area @@ -384,14 +391,26 @@ void COverlayDockContainer::collapseView(bool Enable) if (Enable) { hide(); - d->DockArea->hide(); - d->DockWidget->hide(); + if (d->DockArea) + { + d->DockArea->hide(); + } + if (d->DockWidget) + { + d->DockWidget->hide(); + } } else { show(); - d->DockArea->show(); - d->DockWidget->show(); + if (d->DockArea) + { + d->DockArea->show(); + } + if (d->DockWidget) + { + d->DockWidget->show(); + } } } @@ -419,6 +438,13 @@ bool COverlayDockContainer::areaExistsInConfig(CDockWidgetSideTab::SideTabBarAre } +//============================================================================ +void COverlayDockContainer::clearDockArea() +{ + d->DockArea = nullptr; +} + + //============================================================================ bool COverlayDockContainer::eventFilter(QObject* watched, QEvent* event) { diff --git a/src/OverlayDockContainer.h b/src/OverlayDockContainer.h index 175a1b8..e9d9fa9 100644 --- a/src/OverlayDockContainer.h +++ b/src/OverlayDockContainer.h @@ -150,6 +150,12 @@ public: * Convenience function fr determining if area exists in config */ static bool areaExistsInConfig(CDockWidgetSideTab::SideTabBarArea area); + + /** + * Sets internal DockArea to nullptr + * Called when removing the dock area from this overlay widget + */ + void clearDockArea(); }; }