Skip to content

Instantly share code, notes, and snippets.

@mottosso
Last active February 3, 2020 10:54
Show Gist options
  • Save mottosso/406595cd9771c9c903d8 to your computer and use it in GitHub Desktop.
Save mottosso/406595cd9771c9c903d8 to your computer and use it in GitHub Desktop.
QObject list-model with defaults

QObject list-model with defaults

In addition to declarative syntax, default values are stored in each subclass from which type is derived.

>>> class Item(AbstractItem):
...   name = "default name"
...   age = 10
...   alive = True
...
>>> item = Item(age=5)
>>> assert item.name == "default name"
>>> assert item.age == 5
>>> assert item.alive == True

See QObject list-model with declarative syntax for more information.

See also

from PyQt5 import QtCore
class PropertyType(QtCore.pyqtWrapperType):
"""Metaclass for converting class attributes into pyqtProperties
Usage:
>>> class AbstractClass(QtCore.QObject):
... __metaclass__ = PropertyType
"""
prefix = "__pyqtproperty__"
def __new__(cls, name, bases, attrs):
attrs["type"] = name
properties = list()
for key, default in attrs.copy().items():
if key.startswith("__"):
continue
attrs[key] = QtCore.pyqtProperty(
type(default),
fget=lambda self, k=key, d=default: getattr(
self, cls.prefix + k, d),
constant=True)
properties.append(key)
attrs["__pyqtproperties__"] = properties
return super(PropertyType, cls).__new__(cls, name, bases, attrs)
class AbstractItem(QtCore.QObject):
"""Baseclass for QAbstractListModel items
Any class attributes are converted into pyqtProperties
and must be declared with its type as value.
..note:: Supports methods and properties, in addition to
class attributes.
Usage:
>>> class Item(AbstractItem):
... name = "default name"
... age = 10
... alive = True
...
>>> item = Item(age=5)
>>> assert item.name == "default name"
>>> assert item.age == 5
>>> assert item.alive == True
"""
__metaclass__ = PropertyType
def __init__(self, **kwargs):
super(AbstractItem, self).__init__()
for key, value in kwargs.items():
if hasattr(self, key):
key = PropertyType.prefix + key
setattr(self, key, value)
class Model(QtCore.QAbstractListModel):
def __init__(self, parent=None):
super(Model, self).__init__(parent)
self.items = []
def add_item(self, item):
self.beginInsertRows(QtCore.QModelIndex(),
self.rowCount(),
self.rowCount())
self.items.append(item)
self.endInsertRows()
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self.items)
def data(self, index, role=QtCore.Qt.DisplayRole):
try:
return self.items[index.row()]
except IndexError:
return QtCore.QVariant()
def roleNames(self):
return {
QtCore.Qt.UserRole: "item"
}
class MyItem(AbstractItem):
"""Demonstrates the use of AbstractItem"""
name = "default"
color = "purple"
alive = True
if __name__ == '__main__':
import sys
from PyQt5 import QtGui, QtQuick
# Example
class Application(QtGui.QGuiApplication):
def __init__(self):
super(Application, self).__init__(sys.argv)
window = QtQuick.QQuickView()
window.setResizeMode(window.SizeRootObjectToView)
window.setWidth(400)
window.setHeight(600)
engine = window.engine()
engine.addImportPath(".")
model = Model()
# Add a number of items
model.add_item(MyItem(name="Linus", color="yellow"))
model.add_item(MyItem(name="Marcus", color="brown"))
model.add_item(MyItem(name="Richard", color="red"))
context = engine.rootContext()
context.setContextProperty("objModel", model)
window.setSource(QtCore.QUrl.fromLocalFile("test.qml"))
window.show()
self.window = window
self.model = model
app = Application()
app.exec_()
import QtQuick 2.0
Rectangle {
color: "steelblue"
anchors.fill: parent
ListView {
anchors.fill: parent
model: objModel
delegate: Text {
text: item.name
color: item.color
font.pixelSize: 50
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment