From 38d28085ab9274d132d5ed301ce95551c6ba11de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20S=C3=B8rvig?= <morten.sorvig@qt.io> Date: Wed, 20 Mar 2024 13:23:53 +0100 Subject: [PATCH] Add example which demonstrates app cleanup Don't call exec(), instead allocate objects on the heap and then delete at quit() time. --- examples/application_exit/CMakeLists.txt | 22 +++++++++ examples/application_exit/Main.qml | 22 +++++++++ examples/application_exit/main.cpp | 57 ++++++++++++++++++++++++ 3 files changed, 101 insertions(+) create mode 100644 examples/application_exit/CMakeLists.txt create mode 100644 examples/application_exit/Main.qml create mode 100644 examples/application_exit/main.cpp diff --git a/examples/application_exit/CMakeLists.txt b/examples/application_exit/CMakeLists.txt new file mode 100644 index 0000000..cd7380c --- /dev/null +++ b/examples/application_exit/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.16) + +project(application_exit) + +find_package(Qt6 REQUIRED COMPONENTS Quick) + +qt_standard_project_setup(REQUIRES 6.6) + +qt_add_executable(application_exit + main.cpp +) + +qt_add_qml_module(application_exit + URI applicationexit + VERSION 1.0 + QML_FILES Main.qml +) + +target_link_libraries(application_exit + PRIVATE Qt6::Quick +) + diff --git a/examples/application_exit/Main.qml b/examples/application_exit/Main.qml new file mode 100644 index 0000000..ecc308d --- /dev/null +++ b/examples/application_exit/Main.qml @@ -0,0 +1,22 @@ +import QtQuick +import QtQuick.Window + +Window { + width: 640 + height: 480 + visible: true + + Text { + text: "Click To Quit" + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + MouseArea { + anchors.fill: parent + onClicked: { + deleter.quit(); + } + } +} diff --git a/examples/application_exit/main.cpp b/examples/application_exit/main.cpp new file mode 100644 index 0000000..15d029a --- /dev/null +++ b/examples/application_exit/main.cpp @@ -0,0 +1,57 @@ +#include <QGuiApplication> +#include <QQmlApplicationEngine> +#include <QQmlContext> + +#include <emscripten.h> + +class Deleter; + +QGuiApplication *g_app = nullptr; +QQmlApplicationEngine *g_engine = nullptr; + +class Deleter : public QObject +{ + Q_OBJECT +public: + explicit Deleter(QObject *parent = nullptr) + : QObject(parent) {} + + Q_INVOKABLE void quit() { + + // QCoreApplication does not support deleting itself from inside + // an event callback. Make a native zero-timer callback to make sure + // we are deleting without Qt on the stack. + emscripten_async_call([](void *deleter){ + + // Delete self + delete static_cast<Deleter *>(deleter); + + // Delete the QQmlApplicationEngine and QGuiApplication instances. + delete g_engine; g_engine = nullptr; + delete g_app; g_app = nullptr; + + // Optinally trigger runtime exit as well. + emscripten_force_exit(0); + }, this, 0); + } +}; + +int main(int argc, char *argv[]) +{ + // This example demonstrates how to cleanly exit a Qt application. + // + // This is done by creating the QML application engine and Qt application + // on the heap, and then returning from main() without calling exec(). + // + // Qt for WebAssembly supports omitting the exec() call, since the native + // event loop is already running by the time main() is called. Emscripten + // supports returning from main() without exiting the runtime, see the + // EXIT_RUNTIME linker option. + + g_app = new QGuiApplication(argc, argv); + g_engine = new QQmlApplicationEngine(); + g_engine->loadFromModule("applicationexit", "Main"); + g_engine->rootContext()->setContextProperty("deleter", new Deleter); +} + +#include "main.moc" -- GitLab