Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Subclass QAbstractListModel - count issue
Forum Updated to NodeBB v4.3 + New Features

Subclass QAbstractListModel - count issue

Scheduled Pinned Locked Moved Solved QML and Qt Quick
9 Posts 2 Posters 749 Views 1 Watching
  • 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.
  • D Offline
    D Offline
    DeltaSim
    wrote on last edited by DeltaSim
    #1

    Hello,

    I have an issue using subclass of QAbstractListModel.
    I want to use a custom model in a standard QML ListView.
    The data is correctly updated but if the row size changed, the size of the listview doesn't change.

    Here is my code (simplified):
    QML

    ListView{
       id: rectangleListMenu
       anchors.fill: parent
       clip: true
       interactive: height < contentHeight
       ScrollBar.vertical: ScrollBar {
                                  id: scrollBar
                                  policy: rectangleListMenu.interactive?ScrollBar.AlwaysOn:ScrollBar.AlwaysOff
                               }
       
       model: g_rectangleModel
    
       delegate: Rectangle{
          width: rectangleListMenu.width - (rectangleListMenu.interactive ? (scrollBar.width + rectangleListMenu.anchors.margins) : 0)
          height: rectangleListMenu.itemHeight
          color: s_recColor
       }
    }
    

    rectangleModel.h

    class RectangleModel: public QAbstractListModel
    {
       Q_OBJECT
    
    public:
    
       enum RectangleModelRoles{
          RectangleColorRole = Qt::UserRole + 1
       };
    
       explicit RectangleModel(QObject *op_parent = nullptr);
       ~RectangleModel();
    
       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;
    
       void gv_updateRectangleList(QList<QString*> newRectangleColorList);
    
    
    private:
       QList<QString*> m_rectangleColorList;
    };
    

    rectangleModel.cpp

    #include "rectangleModel.h"
    
    RectangleModel::RectangleModel(QObject *op_parent)
    {
       Q_UNUSED(op_parent)
    }
    
    int RectangleModel::rowCount(const QModelIndex &parent) const
    {
       Q_UNUSED(parent)
    
       return m_rectangleColorList.length();
    }
    
    QVariant RectangleModel::data(const QModelIndex &index, int role) const
    {
       if (!index.isValid())
       {
          return QVariant();
       }
    
       if(index.row() >= m_rectangleColorList.length())
       {
          return QVariant();
       }
    
       switch(role)
       {
       case(RectangleColorRole):
          return m_rectangleColorList.at(index.row());
          break;
       default:
          return QVariant();
          break;
       }
    }
    
    
    QHash<int, QByteArray> RectangleModel::roleNames() const
    {
    
       static QHash<int, QByteArray> mapping{
          {RectangleColorRole, "s_recColor"},
       };
       return mapping;
    }
    
    
    void RectangleModel::gv_updateRectangleList(QList<QString*> newRectangleColorList)
    {
       m_rectangleColorList = newRectangleColorList;
       
       const QModelIndex startIndex = index(0,0);
       const QModelIndex stopIndex = index(m_rectangleColorList.size()-1,0);
       emit dataChanged(startIndex,stopIndex);
    }
    
    RectangleModel::~RectangleModel(){}
    

    I tried multiple things:

    • Adding a count Q_PROPERTY with countChanged signal
    • Removing rows and emitting beginRemoveRows and endRemoveRows then add new rows with related signals
    • Emitting layoutChanged
      But without any success...

    Thanks for your help.

    1 Reply Last reply
    0
    • sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by sierdzio
      #2

      You are returning wrong count in rowCount() - it should be the size of m_rectangleColorList but you return size of m_closeParcelList (different variable).

      When changing items you absolutely should use begin...() and end...() methods, without them the ListView will not know that anything has changed.

      (Z(:^

      1 Reply Last reply
      0
      • D Offline
        D Offline
        DeltaSim
        wrote on last edited by
        #3

        Yes, sorry about the rowCount I made a mistake in this code example, on my real program it is the righ array (I edited the post).
        Wich begin... end... methiod should I call, I tried all of it without any success.

        1 Reply Last reply
        0
        • sierdzioS Offline
          sierdzioS Offline
          sierdzio
          Moderators
          wrote on last edited by
          #4

          @DeltaSim said in Subclass QAbstractListModel - count issue:

          RectangleModel::gv_updateRectangleList(QList<QString*> newRectangleColorList)

          IN this method, you are replacing all items, so you should call:

          beginResetModel();
          m_rectangleColorList = newRectangleColorList;
          endResetModel();
          

          (Z(:^

          1 Reply Last reply
          1
          • D Offline
            D Offline
            DeltaSim
            wrote on last edited by DeltaSim
            #5

            @sierdzio thanks for your feedback.

            I tried to emit those signals but the list size still doesn't change and I have this error:

            QObject::connect: Cannot queue arguments of type 'QQmlChangeSet'
            (Make sure 'QQmlChangeSet' is registered using qRegisterMetaType().)
            
            1 Reply Last reply
            0
            • sierdzioS Offline
              sierdzioS Offline
              sierdzio
              Moderators
              wrote on last edited by
              #6

              They are not signals.

              I don't think QML can handle a pointer to QString. Try changing your data to a QStringList.

              Also, your constructor does not initialize the base class. This is very likely the root cause of your troubles.

              RectangleModel::RectangleModel(QObject *op_parent) : QAbstractListModel(parent)
              {
              }
              

              Regarding the error:

              QObject::connect: Cannot queue arguments of type 'QQmlChangeSet'

              I don't know where it comes from, the code you shared does not seem to try to do anything QQmlChangeSet.

              (Z(:^

              1 Reply Last reply
              0
              • D Offline
                D Offline
                DeltaSim
                wrote on last edited by
                #7

                Ok I created a small project with only this part using resetModel functions and it works.
                The problem is actually a thread problem.
                The function "gv_updateRectangleList" is called in another tread this is why I have the QQmlChangeSet... error.

                On main.ccp I create the model and the thread

                RectangleModel * p_rectangleModel = new RectangleModel();
                DummyThread *p_dummyThread = new DummyThread(p_rectangleModel);
                p_dummyThread->start();
                

                And on the run I call the update function, example:

                void DummyThread::run()
                {
                   QList<QString*> rectList;
                
                   while(true)
                   {
                      rectList.clear();
                
                      if(msn_rectCount < 20)
                      {
                         msn_rectCount++;
                      }
                      else
                      {
                         msn_rectCount = 1;
                      }
                
                      for(int i=0; i<msn_rectCount; i++)
                      {
                         QString *s_string = new QString("#0000FF");
                         rectList.push_back(s_string);
                      }
                
                      mp_rectangleModel->gv_updateRectangleList(rectList);
                
                      sleep(3);
                   }
                }
                
                1 Reply Last reply
                0
                • sierdzioS Offline
                  sierdzioS Offline
                  sierdzio
                  Moderators
                  wrote on last edited by
                  #8

                  Use signals and slots to communicate between threads, then it won't cause you any problems.

                  (Z(:^

                  1 Reply Last reply
                  3
                  • D Offline
                    D Offline
                    DeltaSim
                    wrote on last edited by
                    #9

                    Ok thank you it works.

                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved