I am trying to strictly separate the data (in C++) from the visualization (lists in QML). On the model side, data is stored in instances of a C++ class (Data.cpp) and pointers to that instances are arranged in two lists (completeList and selectedList) by another C++ class (Parser.cpp). Those two lists should be displayed in QML, with the following restrictions:
- the data in completeList is displayed in different QML ListViews (for example according to the name)
- this separation must be done in QML, not by Parses.cpp (which only provides the complete list)
- it must be possible to add list items from completeList to selectedList (for example by clicking on it)
- if values of Data are changed in one ListView, the Data itself and the other views displaying this Data should change accordingly
Thanks to ksimons, I found a way to do half of it, but I cant figure out the rest. Here is what I got so far:
Data.h
class Data : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
public:
Data(const QString &n) : _name(n) { }
QString name() const { return _name; }
void setName(const QString &n) {
if (_name == n)
return;
_name = n;
emit nameChanged(n);
}
signals:
void nameChanged(const QString &n);
private:
QString _name;
};
Parser.h
class Parser : public QObject
{
Q_OBJECT
Q_PROPERTY(QQmlListProperty<Data> completeList READ completeList CONSTANT)
Q_PROPERTY(QQmlListProperty<Data> selectedList READ selectedList CONSTANT)
public:
Parser(QObject *parent = 0) {
Data* d1 = new Data(QStringLiteral("a1"));
Data* d2 = new Data(QStringLiteral("a2"));
Data* d3 = new Data(QStringLiteral("a3"));
Data* d4 = new Data(QStringLiteral("b1"));
Data* d5 = new Data(QStringLiteral("b2"));
_completeList.append(d1);
_completeList.append(d2);
_completeList.append(d3);
_completeList.append(d4);
_completeList.append(d5);
_selectedList.append(d1);
_selectedList.append(d4);
}
QQmlListProperty<Data> completeList() {
return QQmlListProperty<Data>(this, _completeList);
}
QQmlListProperty<Data> selectedList() {
return QQmlListProperty<Data>(this, _selectedList);
}
private:
QList<Data*> _completedList;
QList<Data*> _selectedList;
};
QML part:
ListView
{
id: startsWithA
anchors.fill: parent
delegate: delegateItem
}
ListView
{
id: startsWithB
anchors.fill: parent
delegate: delegateItem
}
ListView
{
id: selectedData
anchors.fill: parent
delegate: delegateItem
}
Item
{
id: delegateItem
height: 30
width: parent.width
Text { text: name }
MouseArea { //change name of corresponding Data and other views accordingly
anchors.fill: parent
onClicked: model.name = "newName";} //does not work
MouseArea { //add to selectedList in Parser
anchors.fill: parent
onClicked: ?????? }
}
Component.onCompleted:
{
selectedData.model = parser.seletedList;
var listAll = parser.completeList;
var listA, listB;
for(var i=0; i<listAll.length; i++)
{
if(listAll[i].name.charAt(0) == 'a')
{
//changing values in startsWithA does not affect anything else with that :(
listA.append(listAll[i]);
}
else if(listAll[i].name.charAt(0) == 'b')
{
//changing values in startsWithB does not affect anything else with that :(
listB.append(listAll[i]);
}
//...
}
startsWithA.model = listA;
startsWithB.model = listB;
//...
}
I hope this question is not to specific and somebody can help me. Thank you in advance.