[Interest] Handling QObject auto-deletion and signals emitted from destructors

Neil Williams neil at copycopy.cc
Tue Sep 1 17:06:58 CEST 2015


Below is a example program which will crash when the widget is closed.

This setup replicates the QWebview behaviour where it will emit the
loadFinished signal from inside the destructor if a page is loading.

I am wondering if anyone can suggest a clean way of handling this sort of
case, where a sibling may have been deleted but is referenced in a
connected slot of a non-deleted object.

I have considered:

1. Always using QPointer and check for object validity before accessing in
the slot. This seems like it would be somewhat tedious.

2. Using the 'context' param of QObject::connect override and splitting the
current slot into multiple smaller slots that only access a single param,
e.g:

connect(webview, &QWebView::loadFinished, ok_widget, [this] (bool ok) {

  ok_widget->setVisible(ok);

});


connect(webview, &QWebView::loadFinished, fail_widget, [this] (bool ok) {

  fail_widget->setVisible(!ok);

});


This requires more boilerplate and may not be possible for more
complex slots which need to access multiple objects.


3. Call to QObject::disconnect in the containing class destructor.
This does feel a little bit like I am micro-managing the connections
which would be nice to avoid.


4. Switch to manual memory management of the widgets so I can control
destruction order.


At the moment I am considering either 1, 3 or 4 but I would appreciate any
other views/opinions/suggestions.

Thanks.

#ifndef WIDGET_H

#define WIDGET_H


#include <QDebug>

#include <QtWidgets>

#include <QWebView>

#include <QPointer>


class QWebView;


class Widget : public QWidget

{

  Q_OBJECT


 public:

  explicit Widget() {


    QVBoxLayout* layout = new QVBoxLayout();


    webview = new QWebView();

    ok_widget = new QWidget();

    fail_widget = new QWidget();


    connect(webview, &QWebView::destroyed, [this] () {

      // replicate loadFinished being fired during qwebview/webpage destruction

      emit webview->loadFinished(false);

    });


    connect(webview, &QWebView::loadFinished, this, &Widget::onLoadFinished);


    layout->addWidget(ok_widget);

    layout->addWidget(fail_widget);

    layout->addWidget(webview);


    setLayout(layout);

  }


  ~Widget() {

    qDebug() << "Window destroyed";

  }


 private slots:

  void onLoadFinished(bool ok) {

    ok_widget->setVisible(ok);

    fail_widget->setVisible(!ok);

  }


 private:

  QWebView* webview;

  QWidget* ok_widget;

  QWidget* fail_widget;


};


#endif // WIDGET_H
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20150901/21eaa9c2/attachment.html>


More information about the Interest mailing list