Должен ли я получить доступ к элементу ListView вне делегата и как? - PullRequest
0 голосов
/ 29 октября 2019

У меня вопрос 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
    }
}

Я пробовал несколько вещей, но я не понимаю, как мне следует редактироватьодин контакт и уведомить два элемента, когда что-то изменилось (либо текущий индекс, либо контактную информацию).

...