Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QtQuick: how to override window close event?

Tags:

qt

qml

qtquick2

My experience in Qt is about two weeks, excuse me if I happen to ask a stupid question.

My program uses QtQuick-based GUI. I initialise it in my main.cpp

#include <QGuiApplication>
#include <QtQuick/QQuickView>

#include "VeryVeryImportantItem.h"

extern
int main(int argc, char * argv[])
{
    qmlRegisterType<VeryVeryImportantItem>("com.my.stuff", 1, 0, "VeryVeryImportantItem");

    QQuickView      quickView(QUrl("MyView.qml"));

    quickView.show();

    QGuiApplication app;

    return app.exec();
}

And MyView.qml looks like this:

import QtQuick 2.1
import QtQuick.Window 2.1
import com.my.stuff 1.0

Item VeryVeryImportantItem {
    id : veryVeryImportantItem
    ...
}

And VeryVeryImportantItem.h is as follows:

#include <QtQuick/QQuickItem>

class VeryVeryImportantItem : public QQuickItem
{
    Q_OBJECT
public:
    Q_INVOKABLE void cleanup();
    ...
};

And now the problem. How do I intercept close event on my root window/view, call VeryVeryImportantItem::cleanup(); and only after that close the application?

What I've found out by now is that QQuickItem::window() can give me the pointer to the window I need and that the window has signal QQuickWindow::closing(QQuickCloseEvent *); and that in theory I can prevent the window from closing by manipulating the given QQuickCloseEvent object. But it's not public, I don't have access to its methods!

Ok. Another way might be that I could do something similar from QML. QML type QWindow has closing(CloseEvent) signal and if I set CloseEvent.accepted false in a slot connected to it that would prevent the window from immediate closing and enable me to call veryVeryImportantItem.cleanup() method. But then I have another problem: how do I get the reference to my root window if I've created it not in QML but in C++ start-up code.

I guess this is the very common situation and there obviously ought to be a well-defined way to handle this but I've been googling for some four hours and still haven't found any decent explanation.

like image 860
krokoziabla Avatar asked Oct 16 '15 13:10

krokoziabla


2 Answers

You can intercept the close event on QQuickView. To do it, create a derived class and overrides the event method:

class NewQuickView: public QQuickView {
public:
    NewQuickView(QUrl url):
        QQuickView(url) {}
public:
    bool event(QEvent *event) override
    {
        if (event->type() == QEvent::Close) {
            // your code here
        }
        return QQuickView::event(event);
    }
};

on main, instance your new class:

NewQuickView quickView(QUrl("MyView.qml"));
like image 23
mabg Avatar answered Sep 21 '22 23:09

mabg


I guess this is the very common situation and there obviously ought to be a well-defined way to handle this

Yes, one could say that.

The easiest thing to do would be to switch to using QQmlApplicationEngine and on the QML side ApplicationWindow as your root component.

Then you can simply use the onClosing signal handler to run your cleanup. I have a similar scenario, where the app would crash if closed before cleanup was invoked, and this approach works flawlessly.

//main.cpp
QQmlApplicationEngine engine;
engine.load(QUrl("MyView.qml"));

.

ApplicationWindow {
    visible: true
    width: 1280
    height: 720    

    BoxView {
        id: view
    }

    onClosing: {
        view.deleteView()
    }
}
like image 190
dtech Avatar answered Sep 20 '22 23:09

dtech