PySide2 QItemEditorFactory and missing QVariant/QMetaType

python
qt
#1

On this lovely weekend I’m digging through Qt example tutorials and try to translate the examples to python (using PySide2).

I just finished this example: https://doc.qt.io/qt-5/qtwidgets-itemviews-coloreditorfactory-example.html

But PySide2 needed some special treatment because it is missing QVariant as well as QMetaType.
The PySide2 documentation says that where ever one has to use a QVariant, native python types can be used instead.

But in case of QItemEditorFactory().registerEditor this is not true, since its expecting an integer as its first parameter.

Looking at PyQt5 the type id for QColor can be easily obtained using QVariant.Color or QMetaType.QColor
in PySide2 I need to either write down 67 (since that is the userType id for QColor) or get the id using staticMetaObject from the class where I have a user property defined:

Given this class

class ColorListEditor(QComboBox):
	def __init__(self, *args, **kwargs):
		super(ColorListEditor, self).__init__(*args, **kwargs)
		self.populateList()

	def getColor(self):
		return self.itemData(self.currentIndex(), Qt.DecorationRole)

	def setColor(self, color):
		self.setCurrentIndex(self.findData(color, Qt.DecorationRole))

	color = Property(QColor, getColor, setColor, user=True)

	def populateList(self):
		color_names = QColor.colorNames()

		for index, name in enumerate(color_names):
			color = QColor(name)
			self.insertItem(index, name)
			self.setItemData(index, color, Qt.DecorationRole)

this is how I would obtain the QColor userType id then:

ColorListEditor.staticMetaObject.userProperty().userType()

Both approaches feel kind of ‘meh’ to me and I thought maybe you guys 'n girls know a smarter way for PySide2 to get the userType.

Bonus question:
How to construct a custom userType for custom classes in PySide2?

#2

Hey Pac,

Going out on a limb here but It looks like theres next to no information on UserTypes and registering them other than this thread from 2011: https://www.riverbankcomputing.com/pipermail/pyqt/2011-June/029988.html

In one part it says UserTypes are automatically registered when the class is instantiated (subclass) due to sip integration.

In an another it looks like you have to register it using a class variable, which looks like you treat kinda like a function set I guess:

class A(object):
   metaTypeId = registerPythonQMetaType(A)

qv = qvariantFromPyObject(A()) # This looks like what you want potentially.
qv.userType()

This looks a little more plausible - qRegisterMetaType is still around as of v5.12.3 (QT c++) - not sure if the bindings are exposed to python though:

https://www.riverbankcomputing.com/static/Docs/PyQt4/qmetatype.html << old.
https://doc.qt.io/qt-5/qmetatype.html < 5.12.3’

QVariant doesn’t have the …fromPyObject function by the looks of it - so either its been deprecated/superseded or maybe in the thread was a custom method created for the purpose:

https://doc.qt.io/qt-5/qvariant.html

…I’ll keep digging - this would be pretty cool to have.

EDIT: - looks like pyside does not support QVariant anymore as per this thread: https://stackoverflow.com/questions/24566940/no-qvariant-attributes

-c

#3

Hey chalk,

thank you for taking the time digging up this information!

It looks like I have to rely on the official documentation that PySide2 will take care of properly managing python objects when parameters ask for a QVariant object.

Coincidentally I found someone asking the same question as mine, not too long ago, on the official PySide bugtracker: https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-1023?filter=allopenissues

He solved it the same way as I did, but no developer has responded yet. I’ll keep watching that space and update here if there’s more valuable information to share.