У меня вопрос QML / C ++. Как использовать и редактировать элемент QAbstractListModel вне делегата представления?
Я создал игрушечный пример того, что я пытаюсь сделать. У меня такое ощущение, что мне не хватает некоторого понимания MVC в QML.
На стороне c ++ у меня есть класс "Contact", полученный из QObject
, в котором хранятся все мои контактные данные, список этих контактов (ContactList) и aQAbstractListModel (ContactListModel) на основе этого списка.
На стороне QML я хочу 2 отдельных компонента. Слева QListView
, отображающий список контактов, здесь используется только некоторая часть класса контактов (например, имя). С правой стороны у меня есть другой Компонент, который отображает текущий Контакт (тот, который выбран в просмотре списка), этот компонент также должен позволять редактировать содержимое Контакта, например, имя / описание и т. Д., И соответственно обновлять представление списка.
C ++: Контакт:
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;
};
На стороне QML у меня есть свой 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
}
}
}
и мой другой компонент, который должен отображать и редактировать данные из одного контакта:
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
}
}
Я пробовал несколько вещей, но я не понимаю, как мне следует редактироватьодин контакт и уведомить два элемента, когда что-то изменилось (либо текущий индекс, либо контактную информацию).