TableView does't update, but list into model is full
-
Hello,
I am trying to update a table with data coming from an external process (into QML I lunch a CLI tool that returns a lot of strings and with that, I update the table). I am using TableView to show these data, and I wrote a Model class and a List class: the Model class extend QAbstractTableModel, indeed the list class extend QObject.
I am sure that the list is full (I print the contents with qDebug()), but the table is always empty! Can you help me?
I put the classes below!
Thanks
Marco#ifndef PAYEELIST_H #define PAYEELIST_H #include <QObject> #include <QList> #include "payee.h" class PayeeList : public QObject { Q_OBJECT public: explicit PayeeList(QObject *parent = nullptr); QList<Payee> items() const; // bool setItemAt (int index, const Payee &item); void clear (void); void append (const Payee& item); signals: void preItemAppended (); void postItemAppended (); void preItemRemoved (int index); void postItemRemoved (); //public slots: // void appendItem (); private: QList<Payee> mItems; }; #endif // PAYEELIST_H
#include "payeelist.h" PayeeList::PayeeList(QObject *parent) : QObject(parent) { } QList<Payee> PayeeList::items() const { return mItems; } void PayeeList::clear() { mItems.clear(); } void PayeeList::append(const Payee &item) { emit preItemAppended(); mItems.append(item); emit postItemAppended(); }
#ifndef PAYEEMODEL_H #define PAYEEMODEL_H #include <QAbstractTableModel> #include "payeelist.h" //class PayeeList; class PayeeModel : public QAbstractTableModel { Q_OBJECT Q_PROPERTY(PayeeList *list READ list WRITE setList) public: explicit PayeeModel(QObject *parent = nullptr); enum { HeadingRole = Qt::UserRole + 1, DataRole }; enum { IdColumn = 0, NameColumn, TypeColumn }; // Basic functionality: int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; virtual QHash<int, QByteArray> roleNames() const override; PayeeList *list (void) const; void setList (PayeeList *list); private: PayeeList *mList; }; #endif // PAYEEMODEL_H
#include "payeemodel.h" PayeeModel::PayeeModel(QObject *parent) : QAbstractTableModel(parent), mList(nullptr) { } int PayeeModel::rowCount(const QModelIndex &parent) const { // For list models only the root node (an invalid parent) should return the list's size. For all // other (valid) parents, rowCount() should return 0 so that it does not become a tree model. if (parent.isValid() || !mList) return 0; qDebug() << "LIST SIZE:" << mList->items().size(); return mList->items().size() + 1; } int PayeeModel::columnCount(const QModelIndex &parent) const { if (parent.isValid() || !mList) return 0; return 3; } QVariant PayeeModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || !mList) return QVariant(); switch (role) { case DataRole: { qDebug() << "INDEX ROW:" << index.row(); if (index.row() > 0) { const Payee item = mList->items().at(index.row() - 1); switch (index.column()) { case IdColumn: return QString::number(item.id()); break; case NameColumn: return QString(item.name()); break; case TypeColumn: return QString(item.type().name()); break; } } else { switch (index.column()) { case IdColumn: return QString("Id"); break; case NameColumn: return QString("Name"); break; case TypeColumn: return QString("Type"); break; } } } break; case HeadingRole: if (index.row() == 0) { return true; } else { return false; } break; default: break; } return QVariant(); } QHash<int, QByteArray> PayeeModel::roleNames() const { QHash<int, QByteArray> names; names[HeadingRole] = "tableheading"; names[DataRole] = "tabledata"; return names; } PayeeList *PayeeModel::list (void) const { return mList; } void PayeeModel::setList (PayeeList *list) { beginResetModel(); if (mList) { mList->disconnect(this); } mList = list; if (mList) { connect(mList, &PayeeList::preItemAppended, this, [=]() { const int index = mList->items().size(); beginInsertRows(QModelIndex(), index, index); }); connect(mList, &PayeeList::postItemAppended, this, [=]() { endInsertRows(); }); } endResetModel(); }
The QML file is:
import QtQuick 2.12 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.3 import PlutoTool 1.0 Rectangle { id: payeePage Layout.fillWidth: true property var title: "TITLE" TableView { columnSpacing: 1 rowSpacing: 1 anchors.fill: parent clip: false property var columnWidths: [50, (parent.width - 220), 150] columnWidthProvider: function (column) { return columnWidths[column] } model: PayeeModel { list: lPayeeList } delegate: Rectangle { implicitWidth: 200 implicitHeight: 30 border.color: "black" border.width: 0 color: (tableheading == true) ? "#990033":"#EEEEEE" Text { text: model.tabledata color: (tableheading == true) ? "#FFFFFF":"#000000" font.bold: (tableheading == true) ? true : false anchors.centerIn: parent } Component.onCompleted: { console.log(model.tabledata); } } } }
-
Hello,
I added some debug prints and I can see that the rowCount function of the model is called a lot of time and return the correct length of the list, but the data function is called every time with index.row() equal to zero! I don't understand why!Any ideas?
Marco
-
@warcomeb said in TableView does't update, but list into model is full:
but the table is always empty!
What does "empty" mean? No data? No delegates shown?
model.tabledata
Why are you prefixing tabledata with model. ?
id: payeePage
What is the height of this Rectangle?
-
@fcarney said in TableView does't update, but list into model is full:
@warcomeb said in TableView does't update, but list into model is full:
but the table is always empty!
What does "empty" mean? No data? No delegates shown?
No delegates shown
model.tabledata
Why are you prefixing tabledata with model. ?
I tried both solutions: with and without model as a prefix.
id: payeePage
What is the height of this Rectangle?
mmmm I don't set the height....
-
Make a role for Qt::DisplayRole and call it "display". Then return data by column like you are doing to support tables. If I remember correctly TableViews are stuck on using the display role. ListViews seem to be more flexible. I don't know why though. I had to use 2 methods to support both listviews and tableviews if I remember corrrectly.
You should only have to use the word "display" to support this role in your delegates. You can add it as another case to your role case so you can support both types of views.