How to read properties for the currenetly selected item in a ListView



  • I want to be able to click on an elemnt in a ListView in order to select it and show a detail view for it.

    This is what I've tried:

    ListView {
    	id: list
    	width: 180; height: 200
    
    	model: myModel // QAbstractListModel
    
    	onCurrentItemChanged: {
    		// how to get the current item?
                    var title1 = myModel[currentIndex].title; // not working
                    var title2 = myModel.data(currentIndex).title; // not working
                    var title3 = currentItem.data.title; // not working
                    var title4 = currentItem.get(currentIndex).title; // not working
    	}
    
    	delegate: Component {
    		Item {
    			width: 200
    			height: 30
    			Text {
    				id: text
    				text: title
    			}
    			MouseArea {
    				anchors.fill: parent
    				onClicked: {
    					list.currentIndex = index;
    				}
    			}
    		}
    	}
    }
    


  • Why don't you do it inside your MouseArea?

    MouseArea {
    	anchors.fill: parent
    	onClicked: {
    		list.currentIndex = index;
    		console.log(title);
    	}
    }
    

    If that's not possible for some reason, you should try:

    var title1 = myModel.get(currentIndex).title
    


  • Duh! I knew my focus was wrong. Doing it inside MouseArea's onClicked is a lot easier!

    Side note: myModel.get() doesn't seem to work. I assume this is implemented for ListModel only, not AbstractItemModel.



  • If anyone has an example of reading properties from the currentItem inside onCurrentItemChanged that would be nice for later reference. Even though I've solved my case by moving work to onClicked.

    I'll mark the question as solved after a while.



  • You can do this by multiple ways.

    Since you have access to the currentItem you could expose its context properties (that's how it can access to the model roles) as normal properties in your delegate: property string title: model.title, then you could do onCurrentItemChanged: { var title = currentItem.title; }. This has the inconvenient that the item can possibly be destroyed (if it gets scrolled out of the viewport for example) and then you won't be able to reference it. Maybe there's a special case where currentItem don't get destroyed but I don't know, it's not really documented.

    Another way is to access the context properties of the current item yourself without exposing them in the delegate. Sadly it's not possible from QML out of the box. One could write an attached object in c++ but this is fairly advanced. The API could be of the form: onCurrentItemChanged: { var title = currentItem.Context.title; }. This has the same limitation as above.

    Like Leonardo said, you could also access it from the model directly with the currentIndex. The model however has to provide an invokable method to expose this, like the get() method in ListModel. It's not standard in QAbstractItemModel so models have to implement that themselves. If you can modify your model, you can add a method like that, it's pretty straightforward.

    A last solution would be a generic way to access data from a model in QML, like I said earlier there's no standardized way to get data out a of a model from QML but all QAbstractItemModel has to implement data(). The problem is that it's not callable from QML. I wrote a library to help with that : https://github.com/oKcerG/QmlModelHelper
    Just include the .pri in your .pro, in your qml file add import ModelHelper 0.1 and then you could use it like that : onCurrentIndexChanged: { var title = myModel.ModelHelper.get(currentIndex).title; }
    Here's the WIP readme : https://gist.github.com/oKcerG/eeea734bdacc51b3ae58650de5f05943



  • @tskardal , you can write a get function in the QAbstractListModel as below

    //declaration
    Q_INVOKABLE QVariantMap get(int row);
    
    //definition
    QVariantMap get(int row) {
        QHash<int,QByteArray> names = roleNames();
        QHashIterator<int, QByteArray> i(names);
        QVariantMap res;
        while (i.hasNext()) {
            i.next();
            QModelIndex idx = index(row, 0);
            QVariant data = idx.data(i.key());
            res[i.value()] = data;
            //cout << i.key() << ": " << i.value() << endl;
        }
        return res;
    }
    

    and in the QML you can use it as below

    myModel.get(1).title  //where 1 is an valid index.
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.