How to access ListView's current item from qml

Peter picture Peter · May 6, 2013 · Viewed 9.7k times · Source

I have an application that stores and edits notes. The list of notes is displayed in a listview like this:

Page {
        id: noteList
        title: i18n.tr("QNote")
        visible: false

        Column {
            anchors.fill: parent

            ListView {
                anchors.fill: parent
                model: notes
                delegate: ListItem.Standard {
                    text: Title
                    onClicked: editNote(NoteText, Title, modelData);
                    progression: true
                }
            }
        }
    }

function editNote(text, title, item) {
    pageStack.push(noteEdit, {title: title, text: text});
    handler.setActiveItem(item);
}

The notes item is a NoteListModel that subclasses the QAbstractListModel and contains NoteListItems. What I would like to do is to store the currently selected NoteListItem so I could easily access the Note object inside when the user wants to save the modified note. However, I don't know how to access the backing NoteListItem from the qml delegate. the modelData seems to be something else. Is there any way to do so? If i could wrap the Note object in a QVariant I could access it easily through roles but when I tried it like this

QVariant NoteListItem::data(int role) {
    switch (role) {
    case Title:
        return note.getTitle();
    case NoteText:
        return note.getText();
    case NoteObject:
        return QVariant::fromValue(note);
    default:
        return QVariant();
    }
}

it resulted in a compiler error saying

qmetatype.h:642: error: invalid application of 'sizeof' to incomplete type 'QStaticAssertFailure'

Or should i try to access the selected list item from the backing code? Is there any way for that? Dou you have any ideas?

Thanks for your time. Regards, Peter

Answer

Richard1403832 picture Richard1403832 · Jul 3, 2015

This took me a very long time to find, as there are many incorrect solutions on Stackoverflow.

The pure QML way is to use a DelegateModel and access it from QML as follows:

import QtQuick 2.4
import QtQml.Models 2.1

ListView {
    property var currentSelectedItem

    onCurrentItemChanged{
            // Update the currently-selected item
            currentSelectedItem = myDelegateModel.items.get(currentIndex).model;
            // Log the Display Role
            console.log(currentSelectedItem.display);
    }

    model: DelegateModel {
        id: myDelegateModel
        model: myAbstractItemModel
        delegate: {
            // Define delegates here
        }
    }
}

This line returns an object (var) that you can access in the same way as within a delegate: myDelegateModel.items.get(currentIndex).model

This example assumes you are only using the default DelegateModelGroup.

See http://doc.qt.io/qt-5/qml-qtqml-models-delegatemodel.html and http://doc.qt.io/qt-5/qml-qtqml-models-delegatemodelgroup.html#get-method method