Как реализовать WPF-подобный MVVM в Qt/C++/QML?

Я пишу доказательство концепции приложения, это очень просто. В основном он состоит из пользовательского интерфейса, в котором список объектов типа "Примечание" отображается в QML ListView.

Затем у меня есть несколько классов, которые есть что-то вроде строк:

#ifndef NOTE_H
#define NOTE_H

#include <string>

using namespace std;
class Note
{
public:
    Note(QObject* parent = 0)
        : QObject(parent)
    {

    }

    Note(const int id, const string& text)
        : _id(id), _text(text)
    {
    }

    int id()
    {
        return _id;
    }

    const string text()
    {
        return _text;
    }

    void setText(string newText)
    {
        _text = newText;
    }

private:
    int _id;
    string _text;
};

#endif // NOTE_H

Затем репозиторий:

class NoteRepository : public Repository<Note>
{
public:
    NoteRepository();
    ~NoteRepository();

    virtual shared_ptr<Note> getOne(const int id);
    virtual const unique_ptr<vector<Note>> getAll();
    virtual void add(shared_ptr<Note> item);
private:
    map<int, shared_ptr<Note>> _cachedObjects;
};

Наконец, ViewModel, который предоставляет примечание к QML

class MainViewModel : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QQmlListProperty<Note> notes READ notes NOTIFY notesChanged)
    Q_PROPERTY(int count READ count() NOTIFY countChanged)
public:
    MainViewModel(QObject *newParent = 0);
    int count();
    QQmlListProperty<Note> notes();
signals:
    void notesChanged();
    void countChanged();
public slots:
private:
    std::shared_ptr<UnitOfWork> _unitOfWork;
    static void appendNote(QQmlListProperty<Note> *list, Note *note);
    QList<Note*> _notes;
};

ПОЖАЛУЙСТА, НЕ УКАЗЫВАЙТЕ ЛЮБОЙ C++ ОШИБКИ ЗДЕСЬ и помните, что они неполны, это не пункт в этот момент, поскольку я постоянно адаптирую это, когда я учусь.

То, в чем я борюсь, как открыть объект, похожий на список, на QML? Требование состоит в том, чтобы этот список был динамическим, чтобы можно было добавлять, удалять и изменять текст заметки. Когда список изменен C++, он также должен уведомить UI (сигнал).

Я пробовал QQmlListProperty, но не мог понять способ разоблачения его в QML. Затем я читаю на другом сообщении SO, этот тип не может быть изменен QML (??), и я наткнулся на QAbstractItemModel.

Так или иначе, может ли кто-нибудь указать мне правильное направление?

Ответ 1

В другом ответе я привел довольно полный пример.

Общая процедура:

  1. Создайте модель, которая основана на QAbstractItemModel. Вы можете повторно использовать любую из моделей, уже предоставленных Qt, например QStringListModel.

  2. Выставить его в QML. Например, используйте setContextProperty() QML Engine rootContext().

  3. Роли модели видны в контексте делегата в QML. Qt обеспечивает сопоставление имен между именами и ролями для DisplayRole (display) и EditRole (edit) в реализации по умолчанию roleNames().

    delegate: Component {
        TextInput {
            width: view.width // assuming that view is the id of the view object
            text: edit // "edit" role of the model, to break the binding loop
            onTextChanged: model.display = text // "display" role of the model
        }
    }
    
  4. Вы можете создать промежуточные модели просмотра, если необходимо, путем присоединения прокси-моделей между представлениями и базовыми моделями. Вы можете получить из QAbstractProxyModel или одного из его подклассов.