Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Is it possible to use QAbstractTableModel with TableView from QtQuick.Controls?
Forum Updated to NodeBB v4.3 + New Features

Is it possible to use QAbstractTableModel with TableView from QtQuick.Controls?

Scheduled Pinned Locked Moved QML and Qt Quick
8 Posts 2 Posters 4.0k Views 1 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.
  • U Offline
    U Offline
    usovalx
    wrote on last edited by
    #1

    Hi,

    I'm trying to implement following case:

    There is 2d table with values. I need to implement UI for viewing data and editing it.
    To simplify synchronisation between edits from UI and table updates coming from the back-end, I want model to store uncommitted edited values and expose a couple of methods to accept/reject pending changes.

    From what I understand this is reasonably easy to do with QtWidgets + models:

    • Base model on QAbstractTableModel
    • Add a few extra roles for storing/querying pending changes, etc.
    • Use QTableView with custom item delegate, which can query model whether cell is editable, show uncommitted changes, etc.

    But I'm puzzled about how to implement it QtQuick.Controls.TableView.
    From my experiments, TableView doesn't work with QAbstractTableModel -- it iterates over the first column of the model and uses roles to simulate second dimension.

    • Is there a way to make TableView work with QAbstractTableModel correctly?

    • As an alternative -- I can change model to use roles for columns, but I'm not sure how to handle other aspects of cell data (modified flag, uncommited value, etc.). The only idea I have so far is to return composite (dictionary) value for each cell. E.g. return QMap<QString, QVariant> or QJsonObject as a value of "cell" and interpret it on QML side.

    Are there any other ways to do it?
    What's more effective if I decide to implement my second solution -- QMap or QJsonObject?

    1 Reply Last reply
    0
    • O Offline
      O Offline
      onek24
      wrote on last edited by
      #2

      Hey,

      your TableView should request data based on the index, that way you'll just return in your Cpp data function the data based on the index(row/column). You just have to pass the QAbstractTableModel to QML as a model of your TableView and access in the names of your roles in your rowDelegate of your TableView.

      1 Reply Last reply
      0
      • U Offline
        U Offline
        usovalx
        wrote on last edited by
        #3

        Hi,

        I figured so far that TableView can access first column of the model and query "columns" data by role's. Problem is -- this way model can provide just 1 data element for the ItemDelegate, while I would really want to have more.

        From what I have figured out so far I can do this by returning QMap<QString, QVariant> or QJsonObject from Cpp model.

        1 Reply Last reply
        0
        • O Offline
          O Offline
          onek24
          wrote on last edited by
          #4

          I have not worked with QAbstractTableModels and TableViews yet, but with QAbstractListModel. I'll provide you a quick example code, maybe it'll help you to find out what you are searching for:

          model.h
          @#ifndef MODEL_H
          #define MODEL_H

          #include <QModelIndex>

          class Model : public QAbstractListModel
          {
          Q_OBJECT
          public:
          Model(QObject *parent);
          ~Model();
          int rowCount(const QModelIndex &parent = QModelIndex()) const;
          int columnCount(const QModelIndex &parent = QModelIndex()) const;
          QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
          enum Roles {
          NameRole = Qt::UserRole
          };
          QHash<int, QByteArray> roleNames() const {
          QHash<int ,QByteArray> roles;
          roles[NameRole] = "name";
          return roles;
          }
          };

          #endif // MODEL_H@

          main.cpp
          @#include "Model.h"
          #include <QDeclarativeContext>
          #include <QDeclarativeView>
          #include <QApplication>
          #include <QTableView>

          int main(int argc, char *argv[])
          {
          QApplication a(argc, argv);

          QDeclarativeView *view = new QDeclarativeView;
          QDeclarativeContext *context = view->rootContext();
          QObject *object = (QObject *)view->rootObject();
          
          Model *model = new Model(0);
          
          view->setSource(QUrl("qrc:/qml/qmlview.qml"));
          context->setContextProperty("listModel", model);
          view->show();
          
          return a.exec&#40;&#41;;
          

          }@

          model.cpp
          @#include "Model.h"
          #include <QImage>

          Model::Model(QObject *parent)
          :QAbstractListModel(parent)
          {
          }

          int Model::rowCount(const QModelIndex &parent) const
          {
          return 4;
          }
          int Model::columnCount(const QModelIndex &parent) const
          {
          return 2;
          }
          QVariant Model::data(const QModelIndex &index, int role) const
          {
          if(role == NameRole)
          {
          return QString("Row%1, Column%2")
          .arg(index.row() + 1)
          .arg(index.column() +1);
          }
          return QVariant();
          }
          Model::~Model(){

          }@

          qmlview.qml
          @import QtQuick 1.1

          Rectangle {
          id: main
          height: 400; width: 200

          ListView {
              id: view
              width: 100; height: 100
          
              model: listModel
          
              delegate: Rectangle {
                  height: 25
                  width: 100
                  Text { text: name }
              }
          }
          

          }@

          src.qrc
          @<RCC>
          <qresource prefix="/qml">
          <file>qmlview.qml</file>
          <file>image.bmp</file>
          </qresource>
          </RCC>@

          1 Reply Last reply
          0
          • U Offline
            U Offline
            usovalx
            wrote on last edited by
            #5

            Have you tried running your example? Here's my screenshot

            !http://s29.postimg.org/y22qbf5yv/Screenshot_070314_15_04_06.png(screenshot)!

            It only shows first column of the model.

            1 Reply Last reply
            0
            • O Offline
              O Offline
              onek24
              wrote on last edited by
              #6

              Sorry, i forgot to write that it is only ListView, but the principles are close to each other.

              [quote author="onek24" date="1394195015"] maybe it’ll help you to find out what you are searching for: [/quote]

              I don't know the answer but i did want at least to provide you an example on how to make it work with a List.
              Maybe "this":http://qt-project.org/forums/viewthread/39333/ thread which is currently going on might help you.

              1 Reply Last reply
              0
              • U Offline
                U Offline
                usovalx
                wrote on last edited by
                #7

                I'm pretty convinced by now that it is impossible to properly use table models with TableView.

                I looked at the sources, and it appears TableView is built around ListView.

                The only question I have left -- as I would have to simulate complex data structure, I'm wondering which representation is more effective: QMap<String, QVariant> or QJsonObject? Which one is cheaper to store in the model and return into QML?

                1 Reply Last reply
                0
                • O Offline
                  O Offline
                  onek24
                  wrote on last edited by
                  #8

                  [quote author="usovalx" date="1394227143"]I'm pretty convinced by now that it is impossible to properly use table models with TableView.

                  I looked at the sources, and it appears TableView is built around ListView.

                  The only question I have left -- as I would have to simulate complex data structure, I'm wondering which representation is more effective: QMap<String, QVariant> or QJsonObject? Which one is cheaper to store in the model and return into QML?[/quote]

                  Since you can parse a ListModel to QML, i am pretty sure that it also should work with a more complex Model. I will give it a try and tell you how and if it worked.

                  About the QJsonObject/QMap-Question: A QMap basically provides a fast-lookup assosiated with the key, so i am not sure if a QJsonObject is faster, and based on the simplicity i would say a QMap should be a very little bit easier, but i haven't worked with QJsonObject, yet. My info is based on what i found out.

                  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