From e30e0c161b2b4d50484314bf006e9e5e8ff6b380 Mon Sep 17 00:00:00 2001 From: Christian Tismer Date: Sat, 30 Sep 2017 12:43:22 +0200 Subject: Support the qApp macro correctly, final version incl. debug For short the new features: - there is a qApp in QtCore, QtGui and QtWidgets for compatibility, and also in __builtins__ for a true macro-like experience. - if you delete any qApp variable, the Q*Application is reset and you can start over. Long description: There is a qApp macro in Qt5 which is equivalent to Q*Application.instance() . Python does not have macros. Both PyQt5 and PySide2 have an according structure in QtWidgets. In the case of PySide2, the qApp variable is first initialized to None and later to QApplication(). This does not reflect the original sense of the qApp macro, because - it only handles QApplication, - it does not handle destruction. This "macro" should live in QtCore, but both PyQt5 and PySide2 decided to put this in QtWidgets. As a compromize, I propose to put qApp into all three modules, and into __builtins__ as well, so wherever you create an application, you find this "macro" in place. While changing the code, I stumbled over the template set_qapp_parent_for_orphan. I tried to make sense out of it and finally removed it. There were no side effects but bug PYSIDE-85 is gone, now. With some extra effort, I created a singleton qApp that changes itself. This way, a true macro was simulated. Note that this was not possible with a garbage collected variable, and I had to make shiboken aware of this. As the final optimization, I turned qApp also into a fuse variable: Delete any qApp variable and Q*Application will finish when there is no extra reference. Task-number: PYSIDE-85 Task-number: PYSIDE-571 Change-Id: I7a56b19858f63349c98b95778759a6a6de856938 Reviewed-by: Christian Tismer --- .../PySide2/QtCore/glue/qcoreapplication_init.cpp | 22 +++++++--------------- .../PySide2/QtCore/typesystem_core_common.xml | 19 ++++++++++--------- 2 files changed, 17 insertions(+), 24 deletions(-) (limited to 'sources/pyside2/PySide2/QtCore') diff --git a/sources/pyside2/PySide2/QtCore/glue/qcoreapplication_init.cpp b/sources/pyside2/PySide2/QtCore/glue/qcoreapplication_init.cpp index fec8cf416..b2dfae38f 100644 --- a/sources/pyside2/PySide2/QtCore/glue/qcoreapplication_init.cpp +++ b/sources/pyside2/PySide2/QtCore/glue/qcoreapplication_init.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of PySide2. @@ -37,22 +37,14 @@ ** ****************************************************************************/ -// Global variables used to store argc and argv values -static int QCoreApplicationArgCount; -static char** QCoreApplicationArgValues; - -void QCoreApplication_constructor(PyObject* self, PyObject* argv, QCoreApplicationWrapper** cptr) +static void QCoreApplicationConstructor(PyObject *self, PyObject *pyargv, QCoreApplicationWrapper **cptr) { - if (QCoreApplication::instance()) { - PyErr_SetString(PyExc_RuntimeError, "A QCoreApplication instance already exists."); - return; - } - - PyObject *stringlist = PyTuple_GET_ITEM(argv, 0); - if (Shiboken::listToArgcArgv(stringlist, &QCoreApplicationArgCount, &QCoreApplicationArgValues, "PySideApp")) { - *cptr = new QCoreApplicationWrapper(QCoreApplicationArgCount, QCoreApplicationArgValues); + static int argc; + static char **argv; + PyObject *stringlist = PyTuple_GET_ITEM(pyargv, 0); + if (Shiboken::listToArgcArgv(stringlist, &argc, &argv, "PySideApp")) { + *cptr = new QCoreApplicationWrapper(argc, argv); Shiboken::Object::releaseOwnership(reinterpret_cast(self)); PySide::registerCleanupFunction(&PySide::destroyQCoreApplication); - Py_INCREF(self); } } diff --git a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml index 03991af38..41a20a617 100644 --- a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml +++ b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml @@ -3215,7 +3215,7 @@ - QCoreApplication_constructor(%PYSELF, args, &%0); + QCoreApplicationConstructor(%PYSELF, args, &%0); @@ -3226,23 +3226,24 @@ - QCoreApplication* app = QCoreApplication::instance(); - PyObject* pyApp = Py_None; + QCoreApplication *app = QCoreApplication::instance(); + PyObject *pyApp = Py_None; if (app) { - pyApp = reinterpret_cast<PyObject*>(Shiboken::BindingManager::instance().retrieveWrapper(app)); + pyApp = reinterpret_cast<PyObject*>( + Shiboken::BindingManager::instance().retrieveWrapper(app)); if (!pyApp) - pyApp = %CONVERTTOPYTHON[QCoreApplication*](app); // this will keep app live after python exit (extra ref) + pyApp = %CONVERTTOPYTHON[QCoreApplication*](app); + // this will keep app live after python exit (extra ref) } + // PYSIDE-571: make sure that we return the singleton "None" + if (pyApp == Py_None) + Py_DECREF(MakeSingletonQAppWrapper(0)); // here qApp and instance() diverge %PYARG_0 = pyApp; Py_XINCREF(%PYARG_0); - -- cgit v1.2.3