Skip to content

Commit f848df7

Browse files
authored
Improve safety in code (#588)
Delete areas later so that that they can be accessed by (inherited) dock widgets in dtor. Add some QPointer to prevent crashes. Hence allow users to do more while dock widgets etc are being destroyed.
1 parent 6c98c29 commit f848df7

File tree

5 files changed

+69
-37
lines changed

5 files changed

+69
-37
lines changed

src/DockAreaWidget.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -756,7 +756,7 @@ int CDockAreaWidget::openDockWidgetsCount() const
756756
int Count = 0;
757757
for (int i = 0; i < d->ContentsLayout->count(); ++i)
758758
{
759-
if (!dockWidget(i)->isClosed())
759+
if (dockWidget(i) && !dockWidget(i)->isClosed())
760760
{
761761
++Count;
762762
}
@@ -772,7 +772,7 @@ QList<CDockWidget*> CDockAreaWidget::openedDockWidgets() const
772772
for (int i = 0; i < d->ContentsLayout->count(); ++i)
773773
{
774774
CDockWidget* DockWidget = dockWidget(i);
775-
if (!DockWidget->isClosed())
775+
if (DockWidget && !DockWidget->isClosed())
776776
{
777777
DockWidgetList.append(dockWidget(i));
778778
}
@@ -786,7 +786,7 @@ int CDockAreaWidget::indexOfFirstOpenDockWidget() const
786786
{
787787
for (int i = 0; i < d->ContentsLayout->count(); ++i)
788788
{
789-
if (!dockWidget(i)->isClosed())
789+
if (dockWidget(i) && !dockWidget(i)->isClosed())
790790
{
791791
return i;
792792
}
@@ -809,7 +809,6 @@ CDockWidget* CDockAreaWidget::dockWidget(int Index) const
809809
return qobject_cast<CDockWidget*>(d->ContentsLayout->widget(Index));
810810
}
811811

812-
813812
//============================================================================
814813
void CDockAreaWidget::reorderDockWidget(int fromIndex, int toIndex)
815814
{

src/DockContainerWidget.cpp

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ class DockContainerWidgetPrivate
141141
CDockContainerWidget* _this;
142142
QPointer<CDockManager> DockManager;
143143
unsigned int zOrderIndex = 0;
144-
QList<CDockAreaWidget*> DockAreas;
144+
QList<QPointer<CDockAreaWidget>> DockAreas;
145145
QList<CAutoHideDockContainer*> AutoHideWidgets;
146146
QMap<SideBarLocation, CAutoHideSideBar*> SideTabBarWidgets;
147147
QGridLayout* Layout = nullptr;
@@ -299,7 +299,11 @@ class DockContainerWidgetPrivate
299299
VisibleDockAreaCount = 0;
300300
for (auto DockArea : DockAreas)
301301
{
302-
VisibleDockAreaCount += DockArea->isHidden() ? 0 : 1;
302+
if (!DockArea)
303+
{
304+
continue;
305+
}
306+
VisibleDockAreaCount += (DockArea->isHidden() ? 0 : 1);
303307
}
304308
}
305309

@@ -924,7 +928,10 @@ void DockContainerWidgetPrivate::addDockAreasToList(const QList<CDockAreaWidget*
924928
//============================================================================
925929
void DockContainerWidgetPrivate::appendDockAreas(const QList<CDockAreaWidget*> NewDockAreas)
926930
{
927-
DockAreas.append(NewDockAreas);
931+
for (auto *newDockArea : NewDockAreas)
932+
{
933+
DockAreas.append(newDockArea);
934+
}
928935
for (auto DockArea : NewDockAreas)
929936
{
930937
QObject::connect(DockArea,
@@ -1641,7 +1648,7 @@ CDockAreaWidget* CDockContainerWidget::dockAreaAt(const QPoint& GlobalPos) const
16411648
{
16421649
for (const auto& DockArea : d->DockAreas)
16431650
{
1644-
if (DockArea->isVisible() && DockArea->rect().contains(DockArea->mapFromGlobal(GlobalPos)))
1651+
if (DockArea && DockArea->isVisible() && DockArea->rect().contains(DockArea->mapFromGlobal(GlobalPos)))
16451652
{
16461653
return DockArea;
16471654
}
@@ -1678,7 +1685,7 @@ int CDockContainerWidget::visibleDockAreaCount() const
16781685
int Result = 0;
16791686
for (auto DockArea : d->DockAreas)
16801687
{
1681-
Result += DockArea->isHidden() ? 0 : 1;
1688+
Result += (!DockArea || DockArea->isHidden()) ? 0 : 1;
16821689
}
16831690

16841691
return Result;
@@ -1802,7 +1809,7 @@ QList<CDockAreaWidget*> CDockContainerWidget::openedDockAreas() const
18021809
QList<CDockAreaWidget*> Result;
18031810
for (auto DockArea : d->DockAreas)
18041811
{
1805-
if (!DockArea->isHidden())
1812+
if (DockArea && !DockArea->isHidden())
18061813
{
18071814
Result.append(DockArea);
18081815
}
@@ -1818,7 +1825,7 @@ QList<CDockWidget*> CDockContainerWidget::openedDockWidgets() const
18181825
QList<CDockWidget*> DockWidgetList;
18191826
for (auto DockArea : d->DockAreas)
18201827
{
1821-
if (!DockArea->isHidden())
1828+
if (DockArea && !DockArea->isHidden())
18221829
{
18231830
DockWidgetList.append(DockArea->openedDockWidgets());
18241831
}
@@ -1833,7 +1840,7 @@ bool CDockContainerWidget::hasOpenDockAreas() const
18331840
{
18341841
for (auto DockArea : d->DockAreas)
18351842
{
1836-
if (!DockArea->isHidden())
1843+
if (DockArea && !DockArea->isHidden())
18371844
{
18381845
return true;
18391846
}
@@ -2058,6 +2065,10 @@ QList<CDockWidget*> CDockContainerWidget::dockWidgets() const
20582065
QList<CDockWidget*> Result;
20592066
for (const auto DockArea : d->DockAreas)
20602067
{
2068+
if (!DockArea)
2069+
{
2070+
continue;
2071+
}
20612072
Result.append(DockArea->dockWidgets());
20622073
}
20632074

@@ -2090,6 +2101,10 @@ CDockWidget::DockWidgetFeatures CDockContainerWidget::features() const
20902101
CDockWidget::DockWidgetFeatures Features(CDockWidget::AllDockWidgetFeatures);
20912102
for (const auto DockArea : d->DockAreas)
20922103
{
2104+
if (!DockArea)
2105+
{
2106+
continue;
2107+
}
20932108
Features &= DockArea->features();
20942109
}
20952110

@@ -2109,7 +2124,7 @@ void CDockContainerWidget::closeOtherAreas(CDockAreaWidget* KeepOpenArea)
21092124
{
21102125
for (const auto DockArea : d->DockAreas)
21112126
{
2112-
if (DockArea == KeepOpenArea)
2127+
if (!DockArea || DockArea == KeepOpenArea)
21132128
{
21142129
continue;
21152130
}

src/DockFocusController.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ DockFocusControllerPrivate::DockFocusControllerPrivate(
115115
//============================================================================
116116
void DockFocusControllerPrivate::updateDockWidgetFocus(CDockWidget* DockWidget)
117117
{
118+
if (!DockWidget) return;
118119
if (!DockWidget->features().testFlag(CDockWidget::DockWidgetFocusable))
119120
{
120121
return;

src/DockManager.cpp

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ static QString FloatingContainersTitle;
103103
struct DockManagerPrivate
104104
{
105105
CDockManager* _this;
106-
QList<CFloatingDockContainer*> FloatingWidgets;
107-
QList<CFloatingDockContainer*> HiddenFloatingWidgets;
106+
QList<QPointer<CFloatingDockContainer>> FloatingWidgets;
107+
QList<QPointer<CFloatingDockContainer>> HiddenFloatingWidgets;
108108
QList<CDockContainerWidget*> Containers;
109109
CDockOverlay* ContainerOverlay;
110110
CDockOverlay* DockAreaOverlay;
@@ -153,7 +153,10 @@ struct DockManagerPrivate
153153
// Hide updates of floating widgets from user
154154
for (auto FloatingWidget : FloatingWidgets)
155155
{
156-
FloatingWidget->hide();
156+
if (FloatingWidget)
157+
{
158+
FloatingWidget->hide();
159+
}
157160
}
158161
}
159162

@@ -333,7 +336,8 @@ bool DockManagerPrivate::restoreStateFromXml(const QByteArray &state, int versi
333336
int FloatingWidgetIndex = DockContainerCount - 1;
334337
for (int i = FloatingWidgetIndex; i < FloatingWidgets.count(); ++i)
335338
{
336-
auto* floatingWidget = FloatingWidgets[i];
339+
CFloatingDockContainer* floatingWidget = FloatingWidgets[i];
340+
if (!floatingWidget) continue;
337341
_this->removeDockContainer(floatingWidget->dockContainer());
338342
floatingWidget->deleteLater();
339343
}
@@ -536,32 +540,40 @@ CDockManager::CDockManager(QWidget *parent) :
536540
CDockManager::~CDockManager()
537541
{
538542
// fix memory leaks, see https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/307
539-
std::vector<ads::CDockAreaWidget*> areas;
540-
for ( int i = 0; i != dockAreaCount(); ++i )
541-
{
542-
auto area = dockArea(i);
543-
if ( area->dockManager() == this )
544-
areas.push_back( area );
545-
// else, this is surprising, looks like this CDockAreaWidget is child of two different CDockManager
546-
// this is reproductible by https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/585 testcase
547-
// then, when a CDockManager deletes itself, it deletes the CDockAreaWidget, then, the other
548-
// CDockManager will try to delete the CDockAreaWidget again and this will crash
549-
// So let's just delete CDockAreaWidget we are the parent of!
550-
}
551-
for ( auto area : areas )
552-
{
553-
for ( auto widget : area->dockWidgets() )
554-
delete widget;
543+
std::vector<QPointer<ads::CDockAreaWidget>> areas;
544+
for (int i = 0; i != dockAreaCount(); ++i)
545+
{
546+
areas.push_back( dockArea(i) );
547+
}
548+
for ( auto area : areas )
549+
{
550+
if (!area || area->dockManager() != this) continue;
555551

556-
delete area;
557-
}
552+
// QPointer delete safety - just in case some dock wigdet in destruction
553+
// deletes another related/twin or child dock widget.
554+
std::vector<QPointer<QWidget>> deleteWidgets;
555+
for ( auto widget : area->dockWidgets() )
556+
{
557+
deleteWidgets.push_back(widget);
558+
}
559+
for ( auto ptrWdg : deleteWidgets)
560+
{
561+
delete ptrWdg;
562+
}
563+
}
558564

559565
auto FloatingWidgets = d->FloatingWidgets;
560566
for (auto FloatingWidget : FloatingWidgets)
561567
{
562568
delete FloatingWidget;
563569
}
564570

571+
// Delete Dock Widgets before Areas so widgets can access them late (like dtor)
572+
for ( auto area : areas )
573+
{
574+
delete area;
575+
}
576+
565577
delete d;
566578
}
567579

@@ -732,7 +744,12 @@ const QList<CDockContainerWidget*> CDockManager::dockContainers() const
732744
//============================================================================
733745
const QList<CFloatingDockContainer*> CDockManager::floatingWidgets() const
734746
{
735-
return d->FloatingWidgets;
747+
QList<CFloatingDockContainer*> res;
748+
for (auto &fl : d->FloatingWidgets)
749+
{
750+
if (fl) res.append(fl);
751+
}
752+
return res;
736753
}
737754

738755

src/DockWidget.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ struct DockWidgetPrivate
8181
CDockWidgetTab* TabWidget = nullptr;
8282
CDockWidget::DockWidgetFeatures Features = CDockWidget::DefaultDockWidgetFeatures;
8383
CDockManager* DockManager = nullptr;
84-
CDockAreaWidget* DockArea = nullptr;
84+
QPointer<CDockAreaWidget> DockArea;
8585
QAction* ToggleViewAction = nullptr;
8686
bool Closed = false;
8787
QScrollArea* ScrollArea = nullptr;

0 commit comments

Comments
 (0)