QAbstractTableModel + QML TableView: How to call setData?
-
Namemight be a reserved word. Try changingName = 0,tocolName = 0,and usetext: colNameandcolName = text -
Just BTW... Figured out why doesnt the
dataChangedsignal fire the table update. I was calling it like this:emit dataChanged(index, index, {role});and
rolewas alwaysQt::EditRole. Now I call it without roles parameter:emit dataChanged(index, index);And the TableView cells are being updated! Thanks for the help @VRonin, it led me to the right place for this one.
I still havent figured out how to automatically callsetDatafrom the QML though (using the presented workaround). If you have any more ideas please let me know. -
Are you sure you are inside
delegate:?
This is a minimal working example:#include <QGuiApplication> #include <QQmlContext> #include <QQmlApplicationEngine> #include <QStringListModel> #include <QDebug> class MyModel : public QStringListModel{ public: MyModel(QObject *parent = nullptr) : QStringListModel(parent) {} QHash<int, QByteArray> roleNames() const override { QHash<int, QByteArray> roles; roles[Qt::EditRole] = QByteArrayLiteral("TestRole"); roles[Qt::DisplayRole] = QByteArrayLiteral("AnotherRole"); return roles; } }; int main(int argc, char *argv[]) { #if defined(Q_OS_WIN) QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #endif QGuiApplication app(argc, argv); QQmlApplicationEngine engine; MyModel model; QObject::connect(&model,&MyModel::dataChanged,[](const QModelIndex& idx){ qDebug() << "Changed: " << idx.row() << " " << idx.data().toString(); }); model.setStringList(QStringList{"aaa","bbb","ccc"}); engine.rootContext()->setContextProperty("mymodel", &model); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); }import QtQml 2.2 import QtQuick 2.7 import QtQuick.Window 2.2 import QtQuick.Controls 2.3 Window { visible: true width: 640 height: 480 title: qsTr("Test Edit") ListView { anchors.fill: parent; width: 200; height: 250 model: mymodel delegate: TextInput { text: TestRole onEditingFinished: { TestRole = text } } } } -
Are you sure you are inside
delegate:?
This is a minimal working example:#include <QGuiApplication> #include <QQmlContext> #include <QQmlApplicationEngine> #include <QStringListModel> #include <QDebug> class MyModel : public QStringListModel{ public: MyModel(QObject *parent = nullptr) : QStringListModel(parent) {} QHash<int, QByteArray> roleNames() const override { QHash<int, QByteArray> roles; roles[Qt::EditRole] = QByteArrayLiteral("TestRole"); roles[Qt::DisplayRole] = QByteArrayLiteral("AnotherRole"); return roles; } }; int main(int argc, char *argv[]) { #if defined(Q_OS_WIN) QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #endif QGuiApplication app(argc, argv); QQmlApplicationEngine engine; MyModel model; QObject::connect(&model,&MyModel::dataChanged,[](const QModelIndex& idx){ qDebug() << "Changed: " << idx.row() << " " << idx.data().toString(); }); model.setStringList(QStringList{"aaa","bbb","ccc"}); engine.rootContext()->setContextProperty("mymodel", &model); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); }import QtQml 2.2 import QtQuick 2.7 import QtQuick.Window 2.2 import QtQuick.Controls 2.3 Window { visible: true width: 640 height: 480 title: qsTr("Test Edit") ListView { anchors.fill: parent; width: 200; height: 250 model: mymodel delegate: TextInput { text: TestRole onEditingFinished: { TestRole = text } } } }@VRonin Hmmm... Here is the thing- I am inside
itemDelegatenotdelegate.delegateis available in differentQtQuick.Controlsversion. If I switch to it, I will no longer have my other components available, iePopup. IsntitemDelegateanddelegatethe same thing?Look at the docs,
TableViewhas nodelegatemember: https://doc.qt.io/qt-5/qml-qtquick-controls-tableview.html#rowDelegate-prop -
Looks like you are still using Qt Quick controls 1.
Qt Quick controls 2 is already 3 years old.If I switch to it, I will no longer have my other components available, ie Popup
Qt Quick Controls 2 has https://doc.qt.io/qt-5/qml-qtquick-controls2-popup.html
-
Looks like you are still using Qt Quick controls 1.
Qt Quick controls 2 is already 3 years old.If I switch to it, I will no longer have my other components available, ie Popup
Qt Quick Controls 2 has https://doc.qt.io/qt-5/qml-qtquick-controls2-popup.html
-
@VRonin
QtQuick.Controls 2.5do havedelegatebut dont haveTableViewColumnwhich I am using for columns setting. Is there a better way now?@Bremenpl said in QAbstractTableModel + QML TableView: How to call setData?:
Is there a better way now?
@VRonin said in QAbstractTableModel + QML TableView: How to call setData?:
Looks like columns and roles are the same thing here but since 1 year ago they are now 2 distinct things (as they are in QtWidgets): https://blog.qt.io/blog/2018/08/29/tableview/
-
@Bremenpl said in QAbstractTableModel + QML TableView: How to call setData?:
Is there a better way now?
@VRonin said in QAbstractTableModel + QML TableView: How to call setData?:
Looks like columns and roles are the same thing here but since 1 year ago they are now 2 distinct things (as they are in QtWidgets): https://blog.qt.io/blog/2018/08/29/tableview/
@VRonin Ok... So now everything I got ahead of with
styleDatais no longer working. This time I am really confused. Those links threat about animations the most and what I need for now is to be able to send/ receive data from the C++ model. Is there any example for that? -
@VRonin Ok... So now everything I got ahead of with
styleDatais no longer working. This time I am really confused. Those links threat about animations the most and what I need for now is to be able to send/ receive data from the C++ model. Is there any example for that? -
@Bremenpl said in QAbstractTableModel + QML TableView: How to call setData?:
So now everything I got ahead of with
styleDatais no longer working.What is
styleData? -
@VRonin It was available in
itemDelegate: https://doc.qt.io/qt-5/qml-qtquick-controls-tableview.html#itemDelegate-prop
One could use it to locate itself in the table as well as read model data.@Bremenpl said in QAbstractTableModel + QML TableView: How to call setData?:
One could use it to locate itself in the table as well as read model data.
now you don't need it anymore. you just access role names directly to read data and you can use
index,rowandcolumndirectly to locate yourself within the modelBtw, this doesnt call setData:
Yes it does. If the
dataChangedsignal is not enough to convince you you can add the below toMyModelbool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override{ qDebug() << "Called setData"; return QStringListModel::setData(index,value,role); } -
@Bremenpl said in QAbstractTableModel + QML TableView: How to call setData?:
One could use it to locate itself in the table as well as read model data.
now you don't need it anymore. you just access role names directly to read data and you can use
index,rowandcolumndirectly to locate yourself within the modelBtw, this doesnt call setData:
Yes it does. If the
dataChangedsignal is not enough to convince you you can add the below toMyModelbool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override{ qDebug() << "Called setData"; return QStringListModel::setData(index,value,role); }@VRonin Ok, you are right! Thanks.
It feels like we are really close this time. So this is the components now:TableView { anchors.fill: parent; model: tableModel; delegate: TextInput { text: Name; onEditingFinished: { Name = text } } }My columns and roles are still mixed together because of the obsolete behavior- this needs to be disconnected. In this case, what should the
roleNamesoverride method return actually? -
@Bremenpl said in QAbstractTableModel + QML TableView: How to call setData?:
hat should the roleNames override method return actually?
I would not override it at all and just use the default
edittext: edit onEditingFinished: { edit = text } -
@Bremenpl said in QAbstractTableModel + QML TableView: How to call setData?:
hat should the roleNames override method return actually?
I would not override it at all and just use the default
edittext: edit onEditingFinished: { edit = text }@VRonin , yeah I just came to realize that too. I did:
delegate: TextInput { text: display; onEditingFinished: { edit = text } }Which I believe in this context gives the same effect.
Alright... Thank you very much for your feedback, you helped me a lot.
Now I only need to figure out eitherheaderDatacan be utilized and that would be it. -
@VRonin , yeah I just came to realize that too. I did:
delegate: TextInput { text: display; onEditingFinished: { edit = text } }Which I believe in this context gives the same effect.
Alright... Thank you very much for your feedback, you helped me a lot.
Now I only need to figure out eitherheaderDatacan be utilized and that would be it.@Bremenpl said in QAbstractTableModel + QML TableView: How to call setData?:
Now I only need to figure out either headerData can be utilized and that would be it.
I'm afraid that part has not been developed by Qt yet
We’re also working on a TableHeader, TableModel, as well as a DelegateChooser.
-
@Bremenpl said in QAbstractTableModel + QML TableView: How to call setData?:
Now I only need to figure out either headerData can be utilized and that would be it.
I'm afraid that part has not been developed by Qt yet
We’re also working on a TableHeader, TableModel, as well as a DelegateChooser.
-
Not exactly what I would call a header. There's this: https://doc.qt.io/qt-5/qml-qtquick-tableview.html#overlays-and-underlays but it's far from anything that is actually useful
-
Not exactly what I would call a header. There's this: https://doc.qt.io/qt-5/qml-qtquick-tableview.html#overlays-and-underlays but it's far from anything that is actually useful
@VRonin Yes, I have just checked this. It overlaps my first row... Do you know either rows inserting and removing work? Meaning- If I remove or insert a row at runtime, will it update the view?
This seems to still be a very beta thing, I wonder either old or new controls should be used. -
Hello there,
I have a custom model class subclassing theQAbstractTableModel. On the QML side, I have aTableViewcomponent. I am trying to connect those 2 things. As for now, I have the TableView reading the data correctly using thedatamethod on C++ side.Now, I am editing the cells on the QML side and after I am done, I dont know how to make the TreeView call the
setDatamethod. I could call it by hand, but the problem is that it requires a validQModelIndexobject:bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;I dont know how to create one one the QML side. I think there should be a method to call it indirectly from QML, but I dont know how. I would appreciate all help regarding this issue. This is my QML test component:
import QtQuick 2.12 import QtQuick.Controls 2.3 import QtQuick.Controls 1.4 import QtGraphicalEffects 1.0 import "." Popup { id: thePopup; modal: true; focus: true; closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside; leftPadding: 0; rightPadding: 0; topPadding: 0; bottomPadding: 0; property real closeMargin: 20; property real localScale: 1; property real fontSizeVal: 15; property Ucolors cg; property variant tableModel; Rectangle { id: popRect; width: parent.width; height: parent.height; color: cg.canvas; TableView { anchors.fill: parent; model: tableModel; // TEMP solution TableViewColumn {title: "1"; role: tableModel ? tableModel.role(0) : ""; width: 70 } TableViewColumn {title: "2"; role: tableModel ? tableModel.role(1) : ""; width: 70 } TableViewColumn {title: "3"; role: tableModel ? tableModel.role(2) : ""; width: 70 } itemDelegate: Rectangle { id: delegateRec; color: colGlob.canvas; Text { id: theCellText; anchors { verticalCenter: parent.verticalCenter; left: parent.left; margins: 10; } //color: colGlob.text; text: tableModel ? styleData.value : ""; //font.pixelSize: fontSize; //font.family: Uconsts.roboFont.name; } MouseArea { id: cellMouseArea anchors.fill: parent; onClicked: { theCellText.visible = false; theLoader.visible = true; theLoader.item.forceActiveFocus(); } } Loader { id: theLoader; anchors { verticalCenter: parent.verticalCenter; left: parent.left; margins: 10; } height: parent.height; width: parent.width; visible: false; sourceComponent: visible ? theInputComp : undefined; Component { id: theInputComp; TextInput { id: textInputId; anchors.fill: parent; onEditingFinished: { console.log("Edited"); theLoader.visible = false; theCellText.visible = true; // TODO how to call setData? } } } } } } } }I also dont know how to force the QML TreeView to call the C++
headerDatamethod, but this is of less importance thansetData...
I would appreciate all help.@Bremenpl said in QAbstractTableModel + QML TableView: How to call setData?:
I also dont know how to force the QML TreeView to call the C++ headerData method
since you use QtQuick.Controls 1 TableView you need to use the TableViewColumn element, which only supports roles.
So you can add custom role names and forward those header roles to the headerData() method in the data() method.virtual QHash<int, QByteArray> roleNames() const { QHash<int, QByteArray> rn = QAbstractItemModel::roleNames(); rn[MyHeaderRole1] = QByteArrayLiteral("header1"); return rn; } QVariantdata(const QModelIndex &index, int role = Qt::DisplayRole) const { switch( role ) { case MyHeaderRole1: return headerData(0, Qt::Horizontal); ... } return QVariant(); }