Should I access an element of a ListView outside of a delegate and How?
-
I have a QML / C++ question. How to use and edit an element of QAbstractListModel outside of a view delegate ?
I created a toy example of what I try to do. I have the feeling that I'm missing some understanding on MVC in QML.
On the c++ side I have a "Contact" class derived from
QObject
storing all my contact data, a list of those contacts (ContactList), and aQAbstractListModel(ContactListModel) based on this list.On the QML side I want 2 separate Components. On the left a
QListView
displaying a list of contacts, only some part of the contact class are used here (e.g name). On the right side I have an another Component that display the current Contact (the one selected in the listview) this component should also allow to edit the content of the Contact, eg name/description etc.. and update the list view accordingly.C++:
Contact:class Contact : public QObject{ Q_OBJECT Q_PROPERTY(QString description READ description WRITE setDescription NOTIFY descriptionChanged) public: explicit Contact(QObject* parent=nullptr, QString i_name =QString(), QString i_desc =QString(), bool i_checked = false); QString description() const; void setDescription(QString desc); QString name; bool checked; signals: void descriptionChanged(); private: QString m_description; };
ContactList:
class ContactList : public QObject { Q_OBJECT Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex ) Q_PROPERTY(Contact* currentItem READ currentContact WRITE setCurrentContact ) public: explicit ContactList(QObject *parent = nullptr); QVector<Contact*> contacts() const; bool setItemAt(int index, Contact* item); int currentIndex() const; void setCurrentIndex(int index); Contact* currentContact() const; void setCurrentContact(Contact* contact); signals: void preItemAppended(); void postItemAppended(); void preItemRemoved(int index); void postItemRemoved(); public slots: void appendItem(); void removeItem(int index); private: QVector<Contact*> m_contacts; int m_currentIndex; Contact* m_currentContact; };
ContactListModel:
class ContactListModel : public QAbstractListModel { Q_OBJECT Q_PROPERTY(ContactList* list READ list WRITE setList ) public: explicit ContactListModel(QObject *parent = nullptr); enum { CheckRole = Qt::UserRole, NameRole, DescriptionRole }; // Basic functionality: int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; // Editable: bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; Qt::ItemFlags flags(const QModelIndex& index) const override; virtual QHash<int, QByteArray> roleNames() const override; ContactList* list() const; void setList(ContactList *list); private: ContactList *m_list; };
On the QML side I have my listView
Layout.fillWidth: true Layout.fillHeight: true id: contacts_list_view clip: true model: ContactModel { id: _contactmodel list: contactList } delegate: RowLayout { CheckBox { checked: model.checked onCheckStateChanged: { console.log(" current Index before " + contacts_list_view.currentIndex) contacts_list_view.currentIndex = index; console.log(" current Index after " + contacts_list_view.currentIndex) contactList.currentIndex = index } } TextField { text: model.name } } }
and my other Component that should display and edit the data from a single Contact:
ColumnLayout{ id: contact_sheet Layout.fillWidth: true Layout.preferredWidth: 800 TextInput{ id: _contact_description Layout.fillWidth: true Layout.preferredHeight: 100 text: "Contact Description " } TextField { text: contactList.currentContact.description } }
I've tried several things but I don't understand how I should edit a single Contact and notify the two items when something changed (either current index, or contact info ).