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



  • 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?



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



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



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



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



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



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


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.