9

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

Peter
  • 1,047
  • 2
  • 18
  • 32
  • Here is my approach - http://stackoverflow.com/questions/14423372/how-to-access-items-stored-in-a-qabstractlistmodel-in-qmlby-delegates-otherwis/14424517#14424517 – Pavel Osipov May 07 '13 at 10:03

1 Answers1

10

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

Russ
  • 10,835
  • 12
  • 42
  • 57
Richard1403832
  • 673
  • 1
  • 9
  • 16
  • Thank you so much! There are numerous more current answers that involve very tedious workarounds like manually implementing a `get` method in model implementation with custom notifiers and other mess. This is a clean built-in solution that just works – Curtwagner1984 Dec 15 '21 at 08:57
  • Does the delegate item get destroyed when it scrolled out of the viewport? – Logan Aug 30 '22 at 14:53
  • @Logan Delegate items will eventually either be destroyed or *re-used*. This is why it is very important not to maintain any state in a delegate, everything must come from the model. – Richard1403832 Sep 27 '22 at 10:56
  • @Richard1403832 Yes, that's why I am asking. Looking at it now the `currentSelectedItem` is bound to the model of the current item at the time of the item changing, so the state of the `currentSelectedItem` should always be valid even if the item which the model came from scrolls out of view and gets destroyed? – Logan Sep 27 '22 at 16:02
  • As far as I know the current item will always be either null (during construction/model reassignment) or valid. It won't point to a destroyed object. – Richard1403832 Oct 26 '22 at 15:34