Details
Description
qApp present implementation
The qApp macro has been invented in 2017 as the attempt to produce a "macro" in Python.
Macros are not possible, but the behavior of qApp tried to mimick the C++ equivalent as much as possible.
In order to accomplish that, a quite uncommon trick was used: The qApp variable was implemented as a singleton variable that could change its content completely. This variable existed for compatibility in QtCore, QtGui, QtWidgets, but mainly in the builtins! So this variable could be used directly after importing PySide2.
The basic advantage of this was: By writing
qApp
, you got the content of Q*Application.instance() immediately.
You could also delete the application by
del __builtins__.qApp
There were no properties used and no function calls. qApp was just passively in the right place.
This also had drawbacks: When no application was initialized, we could not put the singleton None into qApp because it is a singleton itself. We used an object with PyNone_Type and boolean value False, but that was probably too confusing.
We could easily change that by providing a i.e. NoApp object, but that is a minor issue.
The real problem:
The qApp macro had quite good behavior and was considered to stay this way. But when using embedded applications, :Pjects.
- the assignment of qApp is therefore not flexible, but must be correct in the first place. For that reason,
- the timing problem could not be solved for
PYSIDE-1135. qApp assigns QApplication.instance() too early, which breaks the Falcon application.
This is the reason to abandon the whole qApp implementation: Because we can't find a general solution in the embedded case that works in every configuration, here the proposed, incompatible change:
The new qApp function (Proposal)
The reason why we supported qApp at all was brevity. You always can write QApplication.instance() instead. Therefore, also properties make not much sense. Besides the problem that modules cannot have properties easily before Python 3.7, having to write QtWidgets.qApp is long. The easiest way out of the dilemma is this:
qApp is now a regular function object that must be imported from QtWidgets. the usage
qApp()
is equivalent to
QtWidgets.QApplication.instance()
It is still possible to delete an application by calling
qApp.shutDown()
Before | After |
---|---|
qApp | qApp() |
del _builtins_.qApp | qApp.shutdown() |
qApp is also in QtCore QtGui QtWidgets |
Alternate Proposal
Another, less intrusive approach is to keep qApp almost as it is. Only two things are changed:
- when qApp returned "None", it now says "noApp". The type is still NoneType.
- deletion is implemented now as qApp.shutdown()
There is still a problem with the "Falkon" browser reported. This will probably be fixable in Falkon, or as last resort we disable qApp when embedding (which avoids imports during initialization).
Update: Final Solution
We do the alternate implementation, with the following addition:
qApp does no longer exist in embedded mode. This solves all problems
Attachments
Issue Links
- relates to
-
PYSIDE-1135 [Q(Core/Gui)Application]: Wrong function type classification after sublcassing
- Closed
-
PYSIDE-1158 None != None; pyside2 internally uses wrong "None".
- Closed
-
PYSIDE-1164 scriptableapplication: qApp returns QCoreApplication instead of QApplication
- Closed
-
PYSIDE-571 Support the qApp macro correctly
- Closed