Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QAbstractTableModel + QML TableView: How to call setData?
Forum Updated to NodeBB v4.3 + New Features

QAbstractTableModel + QML TableView: How to call setData?

Scheduled Pinned Locked Moved Unsolved General and Desktop
40 Posts 3 Posters 10.3k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • VRoninV Offline
    VRoninV Offline
    VRonin
    wrote on last edited by
    #10

    Name might be a reserved word. Try changing Name = 0, to colName = 0, and use text: colName and colName = text

    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
    ~Napoleon Bonaparte

    On a crusade to banish setIndexWidget() from the holy land of Qt

    B 1 Reply Last reply
    0
    • VRoninV VRonin

      Name might be a reserved word. Try changing Name = 0, to colName = 0, and use text: colName and colName = text

      B Offline
      B Offline
      Bremenpl
      wrote on last edited by
      #11

      @VRonin Doesnt matter how I call it:

      qrc:/UBasicTable.qml:109: Error: Invalid write to global property "colName"
      qrc:/UBasicTable.qml:109: Error: Invalid write to global property "colName1" // this doesnt exist
      

      Any other hints :/?

      lprzenioslo.zut.edu.pl

      1 Reply Last reply
      0
      • B Offline
        B Offline
        Bremenpl
        wrote on last edited by
        #12

        Just BTW... Figured out why doesnt the dataChanged signal fire the table update. I was calling it like this:

        emit dataChanged(index, index, {role});
        

        and role was always Qt::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 call setData from the QML though (using the presented workaround). If you have any more ideas please let me know.

        lprzenioslo.zut.edu.pl

        1 Reply Last reply
        0
        • VRoninV Offline
          VRoninV Offline
          VRonin
          wrote on last edited by VRonin
          #13

          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
                          }
                      }
                  }
          }
          

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          B 1 Reply Last reply
          1
          • VRoninV VRonin

            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
                            }
                        }
                    }
            }
            
            B Offline
            B Offline
            Bremenpl
            wrote on last edited by Bremenpl
            #14

            @VRonin Hmmm... Here is the thing- I am inside itemDelegate not delegate. delegate is available in different QtQuick.Controls version. If I switch to it, I will no longer have my other components available, ie Popup. Isnt itemDelegate and delegate the same thing?

            Look at the docs, TableView has no delegate member: https://doc.qt.io/qt-5/qml-qtquick-controls-tableview.html#rowDelegate-prop

            lprzenioslo.zut.edu.pl

            1 Reply Last reply
            0
            • VRoninV Offline
              VRoninV Offline
              VRonin
              wrote on last edited by VRonin
              #15

              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

              "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
              ~Napoleon Bonaparte

              On a crusade to banish setIndexWidget() from the holy land of Qt

              B 1 Reply Last reply
              1
              • VRoninV VRonin

                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

                B Offline
                B Offline
                Bremenpl
                wrote on last edited by
                #16

                @VRonin QtQuick.Controls 2.5 do have delegate but dont have TableViewColumn which I am using for columns setting. Is there a better way now?

                lprzenioslo.zut.edu.pl

                VRoninV 1 Reply Last reply
                0
                • B Bremenpl

                  @VRonin QtQuick.Controls 2.5 do have delegate but dont have TableViewColumn which I am using for columns setting. Is there a better way now?

                  VRoninV Offline
                  VRoninV Offline
                  VRonin
                  wrote on last edited by
                  #17

                  @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/

                  "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                  ~Napoleon Bonaparte

                  On a crusade to banish setIndexWidget() from the holy land of Qt

                  B 1 Reply Last reply
                  1
                  • VRoninV VRonin

                    @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/

                    B Offline
                    B Offline
                    Bremenpl
                    wrote on last edited by
                    #18

                    @VRonin Ok... So now everything I got ahead of with styleData is 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?

                    lprzenioslo.zut.edu.pl

                    VRoninV 1 Reply Last reply
                    0
                    • B Bremenpl

                      @VRonin Ok... So now everything I got ahead of with styleData is 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?

                      VRoninV Offline
                      VRoninV Offline
                      VRonin
                      wrote on last edited by
                      #19

                      @Bremenpl said in QAbstractTableModel + QML TableView: How to call setData?:

                      So now everything I got ahead of with styleData is no longer working.

                      What is styleData?

                      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                      ~Napoleon Bonaparte

                      On a crusade to banish setIndexWidget() from the holy land of Qt

                      B 1 Reply Last reply
                      1
                      • VRoninV VRonin

                        @Bremenpl said in QAbstractTableModel + QML TableView: How to call setData?:

                        So now everything I got ahead of with styleData is no longer working.

                        What is styleData?

                        B Offline
                        B Offline
                        Bremenpl
                        wrote on last edited by Bremenpl
                        #20

                        @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.

                        lprzenioslo.zut.edu.pl

                        VRoninV 1 Reply Last reply
                        0
                        • B Bremenpl

                          @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.

                          VRoninV Offline
                          VRoninV Offline
                          VRonin
                          wrote on last edited by
                          #21

                          @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, row and column directly to locate yourself within the model

                          Btw, this doesnt call setData:

                          Yes it does. If the dataChanged signal is not enough to convince you you can add the below to MyModel

                          bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override{
                                  qDebug() << "Called setData";
                                  return QStringListModel::setData(index,value,role);
                              }
                          

                          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                          ~Napoleon Bonaparte

                          On a crusade to banish setIndexWidget() from the holy land of Qt

                          B 1 Reply Last reply
                          1
                          • VRoninV VRonin

                            @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, row and column directly to locate yourself within the model

                            Btw, this doesnt call setData:

                            Yes it does. If the dataChanged signal is not enough to convince you you can add the below to MyModel

                            bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override{
                                    qDebug() << "Called setData";
                                    return QStringListModel::setData(index,value,role);
                                }
                            
                            B Offline
                            B Offline
                            Bremenpl
                            wrote on last edited by
                            #22

                            @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 roleNames override method return actually?

                            lprzenioslo.zut.edu.pl

                            1 Reply Last reply
                            0
                            • VRoninV Offline
                              VRoninV Offline
                              VRonin
                              wrote on last edited by VRonin
                              #23

                              @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 edit

                              				text: edit
                              
                              				onEditingFinished:
                              				{
                              					edit = text
                              				}
                              

                              "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                              ~Napoleon Bonaparte

                              On a crusade to banish setIndexWidget() from the holy land of Qt

                              B 1 Reply Last reply
                              1
                              • VRoninV VRonin

                                @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 edit

                                				text: edit
                                
                                				onEditingFinished:
                                				{
                                					edit = text
                                				}
                                
                                B Offline
                                B Offline
                                Bremenpl
                                wrote on last edited by
                                #24

                                @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 either headerData can be utilized and that would be it.

                                lprzenioslo.zut.edu.pl

                                VRoninV 1 Reply Last reply
                                0
                                • B Bremenpl

                                  @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 either headerData can be utilized and that would be it.

                                  VRoninV Offline
                                  VRoninV Offline
                                  VRonin
                                  wrote on last edited by
                                  #25

                                  @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.

                                  "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                                  ~Napoleon Bonaparte

                                  On a crusade to banish setIndexWidget() from the holy land of Qt

                                  B 1 Reply Last reply
                                  0
                                  • VRoninV VRonin

                                    @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.

                                    B Offline
                                    B Offline
                                    Bremenpl
                                    wrote on last edited by
                                    #26

                                    @VRonin So as for now, is there a way to set the column header at all?

                                    lprzenioslo.zut.edu.pl

                                    1 Reply Last reply
                                    0
                                    • VRoninV Offline
                                      VRoninV Offline
                                      VRonin
                                      wrote on last edited by
                                      #27

                                      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

                                      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                                      ~Napoleon Bonaparte

                                      On a crusade to banish setIndexWidget() from the holy land of Qt

                                      B 1 Reply Last reply
                                      0
                                      • VRoninV VRonin

                                        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

                                        B Offline
                                        B Offline
                                        Bremenpl
                                        wrote on last edited by
                                        #28

                                        @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.

                                        lprzenioslo.zut.edu.pl

                                        VRoninV 1 Reply Last reply
                                        0
                                        • B Bremenpl

                                          Hello there,
                                          I have a custom model class subclassing the QAbstractTableModel. On the QML side, I have a TableView component. I am trying to connect those 2 things. As for now, I have the TableView reading the data correctly using the data method 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 setData method. I could call it by hand, but the problem is that it requires a valid QModelIndex object:

                                          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++ headerData method, but this is of less importance than setData...
                                          I would appreciate all help.

                                          raven-worxR Offline
                                          raven-worxR Offline
                                          raven-worx
                                          Moderators
                                          wrote on last edited by raven-worx
                                          #29

                                          @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();
                                          }
                                          

                                          --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                                          If you have a question please use the forum so others can benefit from the solution in the future

                                          B 1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved