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 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 only when index.row() is equal to zero! I don't understand why!
#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);
}
}
}
}