Qt.py
Qt.py copied to clipboard
wrapInstance: Search inheritance hierarchy for a suitable class
Hi, I would like to suggest a change to the implementation of QtCompat.wrapInstance.
Issue
In the current implementation, wrapInstance only checks if the direct superclass is a QtWidgets class. Therefore if the class has a deeper inheritance hierarchy you end up getting a QObject.
In the below example, a pointer to an instance of class B will return a QObject instead of a QDialog.
class A(QtWidgets.QDialog):
pass
class B(A):
pass
Implementation
I've made changes for when base is None
. Here the loop will eventually find QObject if nothing more significant is found. Alternatively you could use while meta_object is not None
and add an else
clause to check if the loop broke but I don't think it is necessary.
def _wrapinstance(ptr, base=None):
assert isinstance(ptr, long), "Argument 'ptr' must be of type <long>"
assert (base is None) or issubclass(base, Qt.QtCore.QObject), (
"Argument 'base' must be of type <QObject>")
if Qt.IsPyQt4 or Qt.IsPyQt5:
func = getattr(Qt, "_sip").wrapinstance
elif Qt.IsPySide2:
func = getattr(Qt, "_shiboken2").wrapInstance
elif Qt.IsPySide:
func = getattr(Qt, "_shiboken").wrapInstance
else:
raise AttributeError("'module' has no attribute 'wrapInstance'")
if base is None:
q_object = func(long(ptr), Qt.QtCore.QObject)
meta_object = q_object.metaObject()
while True:
class_name = meta_object.className()
try:
base = getattr(Qt.QtWidgets, class_name)
except AttributeError:
try:
base = getattr(Qt.QtCore, class_name)
except AttributeError:
meta_object = meta_object.superClass()
continue
break
return func(long(ptr), base)
Yes, this is fantastic. Could you transform this into a PR? That way we can get tests running and hunt down any potential issue. The idea is sound, and from a glance it looks solid.
Hey Marcus, I've added the PR. I'm a bit new to this so let me know if I there's anything wrong. Thanks