Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct


    Qt World Summit: Early-Bird Tickets

    Unsolved TableView does't update, but list into model is full

    QML and Qt Quick
    tableview qml empty table
    2
    5
    279
    Loading More Posts
    • 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.
    • W
      warcomeb last edited by

      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);
                      }
                  }
              }
      }
      
      fcarney 1 Reply Last reply Reply Quote 0
      • W
        warcomeb last edited by

        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

        1 Reply Last reply Reply Quote 0
        • fcarney
          fcarney @warcomeb last edited by

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

          C++ is a perfectly valid school of magic.

          W 1 Reply Last reply Reply Quote 0
          • W
            warcomeb @fcarney last edited by

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

            1 Reply Last reply Reply Quote 0
            • fcarney
              fcarney last edited by

              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.

              C++ is a perfectly valid school of magic.

              1 Reply Last reply Reply Quote 0
              • First post
                Last post