0

Im trying to get my first QML TableView to work in Qt 5.2 (since we are stuck on that version right now at work) using a QAbstractTableModel on the backend.

My main issue is that for some reason the itemDelegate is never firing so I never see anything in the View except the outline of the TableView. I have also verified that theData_ is filled with 2 dimensional numbers in every row/column in the constructor and I do an emit layoutChanged() as well as an emit dataChanged() in the constructor.

I realize I have no error checking for an invalid QModelIndex in the data() call at this time.

I also did not implement index() at all.

Also is there any need to use a ROLE here?

The data Im displaying is a single integer (as a QString) per cell, nothing more at this time.

Thanks for your help

qml:

TableView {
  width: 600
  height: 600

  model: myModel
  visible: true

  itemDelegate: Rectangle {
     color: "lightgray"
     width: 100
     height: 20

     Text {
        text: styleData.value
        color: "black"
     }
   }
}

relevant code from subclassed QAbstractTableModel:

int MyModel::rowCount(const QModelIndex&) const
{
return 10;
}

int MyModel::columnCount(const QModelIndex&) const
{
return 3;
}

QVariant MyModel::data(const QModelIndex& index, int role) const
{
const int row = index.row();
const int col = index.column();

return QString("%1").arg(this->theData_[col][row]);
}
Tim
  • 647
  • 1
  • 10
  • 21

1 Answers1

0

Before Qt 5.12 there was only a TableView component that belongs to Qt QuickControl 1 that only supports a list type model where each column reflects the information of a role so this is probably your problem since you have not created any TableViewColumn. On the other hand, as of >= Qt5.12, another TableView already exists, which it supports as a table type model.

mymodel.h

#ifndef MYMODEL_H
#define MYMODEL_H

#include <QAbstractListModel>

struct Data{
    int number;
    QString text;
};

class MyModel : public QAbstractListModel
{
    Q_OBJECT
public:
    enum CustomRoles{
        NumberRole = Qt::UserRole,
        TextRole
    };
    explicit MyModel(QObject *parent = nullptr);
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    QHash<int, QByteArray> roleNames() const override;
private:
    QList<Data> m_data;
};

#endif // MYMODEL_H

mymodel.cpp

#include "mymodel.h"

MyModel::MyModel(QObject *parent)
    : QAbstractListModel(parent)
{
    // for test
    for(int i=0; i< 10; i++){
        Data d{i, QString::number(i)};
        m_data.push_back(d);
    }
}

int MyModel::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;
    return m_data.count();
}

QVariant MyModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();
    if(role == NumberRole)
        return m_data.at(index.row()).number;
    if(role == TextRole)
        return m_data.at(index.row()).text;
    return QVariant();
}

QHash<int, QByteArray> MyModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[NumberRole] = "number";
    roles[TextRole] = "text";
    return roles;
}

main.qml

// ...
TableView {
    width: 600
    height: 600

    model: myModel
    visible: true

    TableViewColumn {
        role: "number"
        title: "Number"
        width: 100
    }
    TableViewColumn {
        role: "text"
        title: "Text"
        width: 200
    }

    itemDelegate: Rectangle {
        color: "lightgray"
        width: 100
        height: 20

        Text {
            text: styleData.value
            color: "black"
        }
    }
}
// ...
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Ok thanks for that info. Yes Ive used ListView and Repeaters before so didn't want to use the TableViewColumn. We have 2 dimensional data that seemed perfect for an itemDelegate, but it sounds like itemDelegate doesn't work 2 dimensionally until >= 5.12? Is there any 'View' that works 2 dimensionally for set row/columns with a single delegate the way I was describing? – Tim Apr 23 '20 at 23:14
  • @Tim 1) The problem doesn't have to do with itemDelegate but your Tableview only uses the first column. 2) Why don't you use a list type model like the one in my example? 3) There is no such "View" – eyllanesc Apr 23 '20 at 23:20
  • I would do that but my coworker who is my lead and doesn't know Qt doesn't like the fact that you can't use a single delegate for every Cell in the View. It looks like GridView does but its not row/column driven it just seems that it lays out however big the window is. Ive always used ListView and Repeaters and unfortunately have little experience on the newer 5.x versions of QML. – Tim Apr 24 '20 at 00:44
  • @Tim 1) GridView is a view that orders the items horizontally and when there is no more space then a new row is created. 2) If someone does not know about Qt, it seems strange to me that he has so much preponderance in a decision about the Qt models. 3) Qt 5.2 is 6 years old (we are already in Qt 5.14.2 and Qt6 will come out in a few months) so it has many limitations (and bugs) so I would recommend updating your version of Qt. 4) One possible solution is to use a proxy. – eyllanesc Apr 24 '20 at 00:50
  • Thank you for all your advice, I really appreciate it. We are currently stuck on Centos6 so the best we can do at the moment is upgrade to 5.6.2 I believe. I agree on your comments. Can you explain the 'proxy' further? I know of the QSortFilterProxyModel. Thats just for sorting a list though? Sorting isn't an issue here. It sounds like what you both are saying is that the best I can do until later versions of Qt is to lay things out in a list only and organize them by rows or columns (As Ive been doing all along), correct? – Tim Apr 24 '20 at 01:32