Desktop: Make filterWidget2 a subobject of MainWindow

In commit b0556abdd35f96b816ba11e40bf5707abe0c3ebf, the filter-widget
and the filter were connected by a direct function call. This led
to a rather obscure crash on application-close with Qt 5.12. The
crash is due to the Ui::MainWindow class being a sub-object of MainWindow,
but the FilterWidget2 being *not* a subobject.

What happens is that after calling the MainWindow destructor, the
subobjects are destructed, notably the Ui class. Then the base-class
destructor is called (which makes sense, as destructors are called
in reverse order of constructors).

But: the QObject destructor calls hide() on all still existing child-objects
according to Qt's object hierarchy, notably the visible FilterWidget2.

Now the FilterWidget2, on hiding, updates the MainWindow, which has already
destructed all its subobjects. Crash.

Prevent this crash by making FilterWidget2 a subobject of MainWindow
and thus have it destructed before running the QObject destructor.

Alternative ways would be:
1) Use signal/slot() instead of function calls, as these are automatically
   removed if an object is destroyed.
2) Make the FilterWidget2 subobject a smart-pointer. Thus, we probably
   wouldn't have to include the corresponding header.
3) Make the FilterWidget2 subobject a plain pointer and delete it
   explicitly in the constructor.

Reported-by: Jan Mulder <jlmulder@xs4all.nl>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2019-01-17 22:44:09 +01:00 committed by Dirk Hohndel
parent 36fa27050c
commit ed09e6a909
2 changed files with 3 additions and 4 deletions

View file

@ -53,7 +53,6 @@
#include "desktop-widgets/tab-widgets/maintab.h"
#include "desktop-widgets/updatemanager.h"
#include "desktop-widgets/usersurvey.h"
#include "desktop-widgets/filterwidget2.h"
#include "desktop-widgets/simplewidgets.h"
#include "profile-widget/profilewidget2.h"
@ -146,7 +145,6 @@ MainWindow::MainWindow() : QMainWindow(),
divePlannerSettingsWidget = new PlannerSettingsWidget(this);
divePlannerWidget = new DivePlannerWidget(this);
plannerDetails = new PlannerDetails(this);
auto *filterWidget2 = new FilterWidget2();
// what is a sane order for those icons? we should have the ones the user is
// most likely to want towards the top so they are always visible
@ -195,7 +193,7 @@ MainWindow::MainWindow() : QMainWindow(),
registerApplicationState("PlanDive", divePlannerWidget, profileContainer, divePlannerSettingsWidget, plannerDetails );
registerApplicationState("EditPlannedDive", divePlannerWidget, profileContainer, diveList, mapWidget );
registerApplicationState("EditDiveSite", diveSiteEdit, profileContainer, diveList, mapWidget);
registerApplicationState("FilterDive", mainTab, profileContainer, diveList, filterWidget2);
registerApplicationState("FilterDive", mainTab, profileContainer, diveList, &filterWidget2);
setStateProperties("Default", enabledList, enabledList, enabledList,enabledList);
setStateProperties("AddDive", enabledList, enabledList, enabledList,enabledList);

View file

@ -17,6 +17,7 @@
#include "ui_mainwindow.h"
#include "ui_plannerDetails.h"
#include "desktop-widgets/notificationwidget.h"
#include "desktop-widgets/filterwidget2.h"
#include "core/gpslocation.h"
#include "core/dive.h"
@ -36,7 +37,6 @@ class ProfileWidget2;
class PlannerDetails;
class PlannerSettingsWidget;
class LocationInformationWidget;
class FilterWidget2;
typedef std::pair<QByteArray, QVariant> WidgetProperty;
typedef QVector<WidgetProperty> PropertyList;
@ -186,6 +186,7 @@ slots:
private:
Ui::MainWindow ui;
FilterWidget2 filterWidget2;
QAction *actionNextDive;
QAction *actionPreviousDive;
QAction *undoAction;