Modify c++ model data from QML Repeater
Hi all!
I would like to create something similar to the corkboard qml example. On a screen I have some items, which I can move, resize, rotate, and I can store these properties.
I created a model inherited from QAbstractListModel on C++ side. It populates data well.
On the QML side I show it in a Repeater, like this:
Code:
Repeater {
id: myRepeater
model: dayScreenModel
DayScreenEntry {
x: position.x
y: position.y
text: title
}
position, title, size, rotation comes from the C++ model.
It works fine.
But how can I achieve modification of these data?
I found a way:
in the model, created a public slot:
void updateData(int index, QString role, QVariant value);
and, in the DayScreenEntry.qml I can call like this:
myRepeater.model.updateData(index, "title", "NewTitle")
I can refresh the data in code, and it populates also to the qml side, shows the changes.
But, I have some problems with it:
- it's not 'elegant' - Is it possible somehow to call the 'setData' function of the model?
- on QML side, i have to write the model name in the delegate - I can use it only for this model, have to know the model name.
Do You know any other way to get this stuff working?
Re: Modify c++ model data from QML Repeater
Since the delegate is a component, it should be possible to have it contain an item that allows you to edit the content it displays (like the TextEdit element). If you bind the model's property to a property that is editable by the component, there is a good chance the change will be propagated to the model.
1 Attachment(s)
Re: Modify c++ model data from QML Repeater
Hello!
Thank You for your reply. I want expect what you write. But I don't know, how...
I attach a simple example.
The interesting part is in the qml file's mousearea section. I can reach the index, and the title also... But I cannot change the title :(
Maybe only I forgot to set a flag or something like this.
I think, that 'setData' should be called somehow as when the data populates from the model to the view - it's achieved by the 'data' function.
Attachment 5910
main.cpp
Code:
#include <QApplication>
#include <QMessageBox>
#include "mainwidget.h"
int main(int argc, char** argv)
{
MainWidget* mainWidget=new MainWidget();
mainWidget->show();
int r=0;
try
{
r=a.exec();
}catch (...)
{
r=-1;
}
delete mainWidget;
return r;
}
mainwidget.h
Code:
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QtDeclarative/QDeclarativeView>
#include "dummymodel.h"
class MainWidget : public QDeclarativeView
{
Q_OBJECT;
public:
~MainWidget();
public slots:
private:
QDeclarativeContext* m_context;
DummyModel model;
};
#endif // MAINWIDGET_H
mainwidget.cpp
Code:
#include "mainwidget.h"
#include <QtDeclarative>
#include <QDeclarativeContext>
MainWidget
::MainWidget(QWidget* parent
) : QDeclarativeView
(parent
){
setResizeMode(QDeclarativeView::SizeRootObjectToView);
setMinimumSize(300,300);
m_context=rootContext();
m_context->setContextProperty("dummyModel", &model);
setSource
(QUrl("qml/qmlModel/main.qml"));
}
MainWidget::~MainWidget()
{
}
dummymodel.h
Code:
#ifndef DUMMYMODEL_H
#define DUMMYMODEL_H
#include <QAbstractListModel>
#include <QStringList>
{
Q_OBJECT
public:
enum DummyRoles {
TitleRole=Qt::UserRole+1
};
~DummyModel();
private:
void fillData();
};
#endif // DUMMYMODEL_H
dummymodel.cpp
Code:
#include "dummymodel.h"
#include <QDateTime>
{
m_data.clear();
QHash<int, QByteArray> roles;
roles[TitleRole]="title";
setRoleNames(roles);
fillData();
}
DummyModel::~DummyModel()
{
}
int DummyModel
::rowCount(const QModelIndex &parent
) const {
return m_data.count();
}
{
qDebug("dummymodel::data");
qDebug("Role: %d", role);
if (!index.
isValid()) return QVariant();
if ((index.
row()<
0) ||
(index.
row()>
=m_data.
count())) return QVariant();
if (role==TitleRole)
return m_data.at(index.row());
}
void DummyModel::fillData()
{
beginResetModel();
m_data.clear();
int num=1+qrand()%8;
for (int i=0; i<num; i++)
{
m_data.
append(QString("DummyText%1").
arg(i
+1));
}
endResetModel();
}
{
qDebug("SetData called");
return true;
}
and the qml file:
main.qml
Code:
import QtQuick 1.0
Rectangle {
id: base
width: 500
height: 360
Repeater {
model: dummyModel
delegate: myDelegate
}
Component {
id: myDelegate
Rectangle {
x: 10
y: index*35+10
width: 200
height: 30
color: "yellow"
TextEdit {
text: title
font.pointSize: 18
}
MouseArea {
anchors.fill: parent
onClicked: {
console.log("Clicked index:",index);
title="test"
}
}
}
}
}
Re: Modify c++ model data from QML Repeater
Try implementing flags() for your model and return ItemIsEditable.
Re: Modify c++ model data from QML Repeater
Already tried.
Code:
Qt
::ItemFlags DummyModel
::flags(const QModelIndex &index
) const{
qDebug("DummyModel::Flags");
return Qt::ItemIsEditable;
}
But unfortunately it doesn't help, but even the function is not called. (No qDebug output)
Re: Modify c++ model data from QML Repeater
You have to return other flags as well.Like ItemIsEnabled. Make sure the signature fits and verify using QListView that your model is editable.
Re: Modify c++ model data from QML Repeater
It is a good idea to test also with a QListView...
I found that the behavior is a little different.
From QML the flags function never called. In the data function the role is just the roles I have defined with setRoleNames call.
If I use a form with QListView flags is called many times, and role is DisplayRole, and others, so I had to extend the model, to implement the displayrole also.
But from QML, the answer is always: Cannot assign to read-only property 'title'
Any other idea?
Maybe I should use the solution with calling the slots...
Re: Modify c++ model data from QML Repeater
I am also trying to use QAbstractItemModel::setData from QML, but it is not possible. QML model-view-controller connection with C++ Qt is build-in hardcoded suck, thats all.