Hi List,
If anyone's interested, please find attached my example of a
QAbstractListModel that is kept synchronized with a QML ListView.
I wrote the code by merging these two guides and examples:
http://developer.qt.nokia.com/wiki/Selectable_list_of_Python_objects_in_QML
and
http://blog.rburchell.com/2010/02/pyside-tutorial-model-view-programming_22.html
Best regards,
Vladimir
Dne 20.12.2010 12:16, Thomas Perl napsal(a):
Hi Vladimir,
2010/12/16 Vláďa<[email protected]>:
Please find an example of my solution for the problem in attachment. I'm
sorry for the comments, which are not always very clear, but part of the
code is still a "black box" for me. Also since English is not my native
language, some sentences may not make much sense.
What the example does is, that it shows a list of cars. If you click one of
them, it will reduce the list so that it will only contain cars from the
same manufacturer as the one you clicked. If you have any questions, do not
hesitate to ask.
Please feel free to share this example on the PySide mailing list, so
the PySide developers can merge this into pyside-examples :)
Thanks!
Thomas
from PySide import QtCore, QtGui, QtDeclarative
import sys
# The object which will be represented as an item in the list
# Each Item has 2 properties - model and manufacturer, which we will acces from
Python
# The QtCore.Property "name" will be used in QML for ListView delegate text
class ListItem(QtCore.QObject):
def __init__(self, model, manufacturer):
QtCore.QObject.__init__(self)
self.model = model
self.manufacturer = manufacturer
def _name(self):
return self.model
changed = QtCore.Signal()
name = QtCore.Property(unicode, _name, notify=changed)
# The model contains only one column. It contains ListItem instancies
# To allow modification of the model content we need to implelemnt functions
"removeRows" and "addItem"
# from the QtCore.QAbstractListModel. These functions do nothing by default and
return false.
# The function "replaceItems" fills the model with completely new list of
ListItems
class ItemListModel(QtCore.QAbstractListModel):
COLUMNS = ('cars',)
def __init__(self, items):
QtCore.QAbstractListModel.__init__(self)
self._items = items
self.setRoleNames(dict(enumerate(self.COLUMNS)))
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self._items)
def data(self, index, role):
if index.isValid() and role == self.COLUMNS.index('cars'):
return self._items[index.row()]
return None
def removeRows(self,firstRow,rowCount,parent = QtCore.QModelIndex()):
self.beginRemoveRows(parent, firstRow, firstRow+rowCount-1)
while rowCount != 0:
del self._items[firstRow]
rowCount -= 1
self.endRemoveRows()
def addItem(self, item):
self.beginInsertRows(QtCore.QModelIndex(), len(self._items),
len(self._items))
self._items.append(item)
self.endInsertRows()
def replaceItems(self, items):
self.removeRows(0,len(self._items))
self.beginInsertRows(QtCore.QModelIndex(), len(self._items),
len(self._items))
self._items = items
self.endInsertRows()
# This is just a simple function which returns a list of ListItems containing
car models and their manufacturers
def fillCars(filter):
cars =
[['Ascona','Vectra','Omega','Cruze','Octavia','Charger','Fiesta','Focus','Mondeo'],['Opel','Opel','Opel','Chevrolet','Skoda','Dodge','Ford','Ford','Ford']]
_carList = []
for i in range(len(cars[0])):
if filter == "all" or filter == cars[1][i]:
_carList.append(ListItem(cars[0][i],cars[1][i]))
return _carList
# The Controller receives signals from QML. It will receive 2 parameters of
QObject type:
# the selected item and the model.
class Controller(QtCore.QObject):
@QtCore.Slot(QtCore.QObject, QtCore.QObject)
def itemSelected(self, listItem, listModel): # This function is called from
QML when an item is selected
print 'User clicked on:', listItem.model, 'produced by',
listItem.manufacturer
carList = fillCars(listItem.manufacturer) # Returns a list of ListItems
filtered by manufacturer of selected item
listModel.replaceItems(carList) # Raplaces the model content to only
contain cars from one manufacturer
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
view = QtDeclarative.QDeclarativeView()
view.setResizeMode(QtDeclarative.QDeclarativeView.SizeRootObjectToView)
rc = view.rootContext()
carList = fillCars("all") # Creates a list of ListItems containing all cars
listModel = ItemListModel(carList) # Creates and fills the model
rc.setContextProperty('listModel', listModel) # Sets the model so it can be
used from QML
controller = Controller()
rc.setContextProperty('controller', controller) # Sets the controller so it
can be used from QML
view.setSource('ListView.qml')
view.show()
sys.exit(app.exec_())import Qt 4.7
Rectangle {
id: main
color: "#343434"
width: 200
height: 200
Component {
id: listDelegate
Item {
id: listItem
property string text
anchors.right: parent.right
anchors.left: parent.left
height: 40
Rectangle {
id: frame
anchors.fill: parent
anchors.rightMargin: 5
anchors.leftMargin: 5
anchors.topMargin: 5
anchors.bottomMargin: 5
color: "#00000000"
radius: 20
border.width: 2
border.color: "#ffffff"
Text {
id: itemText
color: "#ffffff"
text: model.cars.name // Here we get the value from the
model, it's column and it's item
anchors.fill: parent
anchors.rightMargin: 5
anchors.leftMargin: 10
anchors.bottomMargin: 5
anchors.topMargin: 5
clip: false
style: Text.Normal
wrapMode: Text.NoWrap
elide: Text.ElideRight
smooth: false
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
font.pointSize: 14
}
}
MouseArea {
anchors.fill: parent
onClicked: {
listView.currentIndex = index
controller.itemSelected(model.cars, listModel) // We call
the Python function with 2 parameters
}
}
}
}
ListView {
id: listView
anchors.fill: parent
model: listModel // We assign here the model created by PySide script
delegate: listDelegate
focus: true
clip: true
}
}
_______________________________________________
PySide mailing list
[email protected]
http://lists.openbossa.org/listinfo/pyside