-
Notifications
You must be signed in to change notification settings - Fork 252
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement wrapInstance and getCppPointer (#59) #190
Changes from 2 commits
281fc04
284cd37
91c45ff
e93859a
3a978fc
666111e
ec26a56
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -645,6 +645,50 @@ def _setup(module, extras): | |
setattr(Qt, name, _new_module(name)) | ||
|
||
|
||
def _wrapinstance(func, ptr, base=None): | ||
"""Enable implicit cast of pointer to most suitable class | ||
|
||
This behaviour is available in sip per default. | ||
|
||
Based on http://nathanhorne.com/pyqtpyside-wrap-instance | ||
|
||
Usage: | ||
This mechanism kicks in under these circumstances. | ||
1. Qt.py is using PySide 1 or 2. | ||
2. A `base` argument is not provided. | ||
|
||
See :func:`QtCompat.wrapInstance()` | ||
|
||
Arguments: | ||
func (function): Original function | ||
ptr (long): Pointer to QObject in memory | ||
base (QObject, optional): Base class to wrap with. Defaults to QObject, | ||
which should handle anything. | ||
|
||
""" | ||
|
||
assert isinstance(ptr, long), "Argument 'ptr' must be of type <long>" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As far as I know, in Python3 there is no longer a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm, you're right. This wasn't caught by Travis, I'll take a closer look as to why that is tomorrow. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, this has been fixed. Turns out |
||
assert (base is None) or issubclass(base, Qt.QtCore.QObject), ( | ||
"Argument 'base' must be of type <QObject>") | ||
|
||
if base is None: | ||
q_object = func(long(ptr), Qt.QtCore.QObject) | ||
meta_object = q_object.metaObject() | ||
class_name = meta_object.className() | ||
super_class_name = meta_object.superClass().className() | ||
|
||
if hasattr(Qt.QtWidgets, class_name): | ||
base = getattr(Qt.QtWidgets, class_name) | ||
|
||
elif hasattr(Qt.QtWidgets, super_class_name): | ||
base = getattr(Qt.QtWidgets, super_class_name) | ||
|
||
else: | ||
base = Qt.QtCore.QObject | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Out of curiosity, in which scenario(s) will There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Likely never, all objects you could get from this function are subclasses of QObject. It's set as default here as a fallback, as anything, even a |
||
|
||
return func(long(ptr), base) | ||
|
||
|
||
def _pyside2(): | ||
"""Initialise PySide2 | ||
|
||
|
@@ -660,6 +704,18 @@ def _pyside2(): | |
|
||
Qt.__binding_version__ = module.__version__ | ||
|
||
try: | ||
import shiboken2 | ||
Qt.QtCompat.wrapInstance = ( | ||
lambda ptr, base=None: _wrapinstance( | ||
shiboken2.wrapInstance, ptr, base) | ||
) | ||
Qt.QtCompat.getCppPointer = lambda object: \ | ||
shiboken2.getCppPointer(object)[0] | ||
|
||
except ImportError: | ||
pass # Optional | ||
|
||
if hasattr(Qt, "_QtUiTools"): | ||
Qt.QtCompat.loadUi = lambda fname: \ | ||
Qt._QtUiTools.QUiLoader().load(fname) | ||
|
@@ -694,6 +750,18 @@ def _pyside(): | |
|
||
Qt.__binding_version__ = module.__version__ | ||
|
||
try: | ||
import shiboken | ||
Qt.QtCompat.wrapInstance = ( | ||
lambda ptr, base=None: _wrapinstance( | ||
shiboken.wrapInstance, ptr, base) | ||
) | ||
Qt.QtCompat.getCppPointer = lambda object: \ | ||
shiboken.getCppPointer(object)[0] | ||
|
||
except ImportError: | ||
pass # Optional | ||
|
||
if hasattr(Qt, "_QtUiTools"): | ||
Qt.QtCompat.loadUi = lambda fname: \ | ||
Qt._QtUiTools.QUiLoader().load(fname) | ||
|
@@ -738,6 +806,18 @@ def _pyqt5(): | |
import PyQt5 as module | ||
_setup(module, ["uic"]) | ||
|
||
try: | ||
import sip | ||
Qt.QtCompat.wrapInstance = ( | ||
lambda ptr, base=None: _wrapinstance( | ||
sip.wrapinstance, ptr, base) | ||
) | ||
Qt.QtCompat.getCppPointer = lambda object: \ | ||
sip.unwrapinstance(object) | ||
|
||
except ImportError: | ||
pass # Optional | ||
|
||
if hasattr(Qt, "_uic"): | ||
Qt.QtCompat.loadUi = lambda fname: Qt._uic.loadUi(fname) | ||
|
||
|
@@ -803,6 +883,18 @@ def _pyqt4(): | |
import PyQt4 as module | ||
_setup(module, ["uic"]) | ||
|
||
try: | ||
import sip | ||
Qt.QtCompat.wrapInstance = ( | ||
lambda ptr, base=None: _wrapinstance( | ||
sip.wrapinstance, ptr, base) | ||
) | ||
Qt.QtCompat.getCppPointer = lambda object: \ | ||
sip.unwrapinstance(object) | ||
|
||
except ImportError: | ||
pass # Optional | ||
|
||
if hasattr(Qt, "_uic"): | ||
Qt.QtCompat.loadUi = lambda fname: Qt._uic.loadUi(fname) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we should add a "Returns:" to the docstring to make it easier to understand the different types of return values are possible here, as I'm guessing it's not always a
QObject
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, and
long
must also change.Not sure how to tackle the fact that
long
is absent from Python 3. I had a look at us internally takingint
for both Python 2 and 3, but then we stray from the originalPySide2.wrapInstance
argument signature.