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

Reply via email to