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.
This commit is contained in:
Syarif Fakhri 2022-09-14 12:16:36 +08:00
parent 0e5329fd3e
commit ee97b03e53
3 changed files with 37 additions and 4 deletions

View File

@ -1666,6 +1666,7 @@ void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
CDockWidget::emitTopLevelEventForWidget(TopLevelWidget, true); CDockWidget::emitTopLevelEventForWidget(TopLevelWidget, true);
dumpLayout(); dumpLayout();
d->emitDockAreasRemoved(); d->emitDockAreasRemoved();
area->overlayDockContainer()->clearDockArea();
area->setOverlayDockContainer(nullptr); area->setOverlayDockContainer(nullptr);
area->updateAutoHideButtonCheckState(); area->updateAutoHideButtonCheckState();
area->updateTitleBarButtonToolTip(); area->updateTitleBarButtonToolTip();

View File

@ -158,6 +158,11 @@ COverlayDockContainer::COverlayDockContainer(CDockManager* DockManager, CDockWid
//============================================================================ //============================================================================
void COverlayDockContainer::updateMask() void COverlayDockContainer::updateMask()
{ {
if (d->DockArea == nullptr)
{
return;
}
const auto rect = d->DockArea->frameGeometry(); const auto rect = d->DockArea->frameGeometry();
const auto topLeft = rect.topLeft(); const auto topLeft = rect.topLeft();
const auto handleSize = d->Splitter->handleWidth(); const auto handleSize = d->Splitter->handleWidth();
@ -222,6 +227,8 @@ CDockWidget* COverlayDockContainer::dockWidget() const
//============================================================================ //============================================================================
void COverlayDockContainer::addDockWidget(CDockWidget* DockWidget) 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) if (d->DockWidget)
{ {
// Remove the old dock widget at this area // Remove the old dock widget at this area
@ -384,15 +391,27 @@ void COverlayDockContainer::collapseView(bool Enable)
if (Enable) if (Enable)
{ {
hide(); hide();
if (d->DockArea)
{
d->DockArea->hide(); d->DockArea->hide();
}
if (d->DockWidget)
{
d->DockWidget->hide(); d->DockWidget->hide();
} }
}
else else
{ {
show(); show();
if (d->DockArea)
{
d->DockArea->show(); d->DockArea->show();
}
if (d->DockWidget)
{
d->DockWidget->show(); 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) bool COverlayDockContainer::eventFilter(QObject* watched, QEvent* event)
{ {

View File

@ -150,6 +150,12 @@ public:
* Convenience function fr determining if area exists in config * Convenience function fr determining if area exists in config
*/ */
static bool areaExistsInConfig(CDockWidgetSideTab::SideTabBarArea area); static bool areaExistsInConfig(CDockWidgetSideTab::SideTabBarArea area);
/**
* Sets internal DockArea to nullptr
* Called when removing the dock area from this overlay widget
*/
void clearDockArea();
}; };
} }