Ask confirmation before closing a QQuickView or QApplication

qml, qt5, qtquick2

Solution

I don't know why `QWindow` hasn't a `closeEvent` convenience event handler. Looks like a mistake, and sadly it can't be added before Qt 6.0. Anyhow, any QWindow definitely gets a `QCloseEvent` when it gets closed. So just override `event` and perform your event handling there.

Proofs:

- QGuiApplication source code

this test program:

#include <QtGui>

class Window : public QWindow
{
protected:
    bool event(QEvent *e) Q_DECL_OVERRIDE
    {
        int type = e->type();
        qDebug() << "Got an event of type" << type;
        if (type == QEvent::Close)
            qDebug() << "... and it was a close event!";

        return QWindow::event(e);
    }
};

int main(int argc, char **argv) 
{
    QGuiApplication app(argc, argv);
    Window w;
    w.create();
    w.show();
    return app.exec();
}

prints this

Got an event of type 17 
Got an event of type 14 
Got an event of type 13 
Got an event of type 105 
Got an event of type 13 
Got an event of type 206 
Got an event of type 206 
Got an event of type 8 
Got an event of type 207 
Got an event of type 19 
... and it was a close event! 
Got an event of type 18 

Problem

I am trying to catch a close event either in my `MyApplication` instance inheriting from `QApplication` or in my `WindowQML` instance inheriting from `QQuickView`. The goal is to ask confirmation to quit before really closing the application. Before my application was relying on `QMainWindow` where I implemented the `closeEvent()` method like this: ``` // MainWindow inherits from QMainWindow void MainWindow::closeEvent(QCloseEvent *event) { event->ignore(); confirmQuit(); // ask for confirmation first } ``` The problem is that my class `WindowQML` which inherits from `QQuickView` never pass inside the `closeEvent()` method. I then tried to overload the `event()` method like this: ``` // WindowQML inherits from QQuickView bool WindowQML::event(QEvent *event) { if(event->type() == QEvent::Close) { qDebug() << "CLOSE EVENT IN QML WINDOW"; } } ``` but this event never happened either. The next road I tried to take was to catch the close event in `MyApplication` like this: ``` // We need to check for the quit event to ask confirmation in the QML view bool MyApplication::event(QEvent *event) { bool handled = false; switch (event->type()) { case QEvent::Close: qDebug() << "Close event received"; event->ignore(); // mandatory? handled = true; Q_EMIT quitSignalReceived(); break; default: qDebug() << "Default event received"; handled = QApplication::event(event); break; } qDebug() << "Event handled set to : " << handled; return handled; } ``` The signal `quitSignalReceived()` is emitted properly but the event is not "blocked" properly and my application still closes. So I have two questions: - Is there a way to detect the closing event of a `QQuickView` instance? - If it is not possible, is the `MyApplication::event()` way the best course of action? Why do I need to call `event->ignore()` here? I would have thought that returning `true` would be enough.

Original source