XXXXXXXXXXXXXXXXXXXXXXXXX/questions/18648257/how-to-implement-wpf-like-mvvm-in-qt-c-qml
Asked 6 years, 2 months ago
Active 2 years, 7 months ago
Viewed 13k times
11
4
I'm writing a proof of concept application, that is very simple. Basically it's composed of a UI where a list of "Note" type objects is displayed in a QML ListView.
I then have a few classes which is something along the lines:
#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</string>
Then a repository:
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; };</int, shared_ptr<note></note></vector<note></note></note>
Finally a ViewModel that exposes Note to 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; };</note*></note></unitofwork></note></note>
PLEASE DON'T MIND ANY C++ MISTAKES HERE and mind they are incomplete, it's not the point at this moment as I'm constantly adapting this as I learn.
The point where I'm struggling is, how to expose a list-like object to QML? The requirement is this list must be dynamic, one should be able to add, delete and modify the text of a note. When the list is modified by C++, it should also notify the UI (signal).
I tried QQmlListProperty, but couldn't figure a way of exposing it to QML. Then I read on another SO post this type can't be modified by QML (??), and I stumbled upon QAbstractItemModel.
Anyhow, can anyone point me to the right direction?
1,85933 gold badges2727 silver badges4545 bronze badges
1
QAbstractItemModel
should be the proper direction for this. You can find more info here : XXXXXXXXXXXXXX/doc/qt-5.1/qtquick/… – koopajah Sep 6 '13 at 8:18
9
I've posted a rather complete example in another answer.
The general procedure is:
Create a model that derives from QAbstractItemModel
. You can reuse any of the models already provided by Qt, for example QStringListModel
.
Expose it to QML. E.g. use setContextProperty()
of QML Engine's rootContext()
.
The model's roles are visible in the context of the delegate in QML. Qt provides default mapping between names and roles for the DisplayRole
(display
) and EditRole
(edit
) in a default implementation of 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 } }
You can create intermediate viewmodels, if needed, by attaching proxy models between the views and the backend models. You can derive from QAbstractProxyModel
or one of its subclasses.
时段 | 个数 |
---|---|
{{f.startingTime}}点 - {{f.endTime}}点 | {{f.fileCount}} |