Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Replace QstandItemModel with QAbstractItemModel
Forum Updated to NodeBB v4.3 + New Features

Replace QstandItemModel with QAbstractItemModel

Scheduled Pinned Locked Moved Solved General and Desktop
16 Posts 5 Posters 1.6k 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.
  • L Offline
    L Offline
    leinad
    wrote on last edited by
    #1

    Hi,

    I was wondering if someone can help me with a problem I'm having using QStandardItemModel and perhaps show me to migrate my code to QAbstractItemModel. I have a tree view which is being populated using QStandardItemModel . The problem is when I try to remove rows; a lot of them it takes a long time. An example is removing 40,000+ rows. This used to work fine with Qt versions < 5.11.2. But now I'm migrated to 5.12 and it is extremely slow. Suggestions from others is to use QAbstractItemModel and remove the rows using that model. Below is a sample program which works fine with earlier version of Qt ( < 5.11.2 ).

    Can someone show me how to map to QAbstractItemModel or make it work just as fast with QStandardItemModel using the current version of Qt? I did a lot of reading but still don't understand how to do it. I'm fairly new to Qt so I need detail help if possible. I just need to know how to add data to the model for QAbstractItemModel equivalent to QStandardItemModel::setItem and how to remove rows equivalent to QStandardItemModel::removeRows.

    Regards,
    Dan


    #include <QtWidgets>

    //QAbstractItemModel Class
    void executeTest()
    {
    int masterRowNumber = 0;
    const int numberOfRows = 50000;
    const int removeRows = 40000;
    const int numCol = 15;

    QTreeView tv;
    QStandardItemModel myModel;
    QElapsedTimer timer;
    timer.start();
    
    qDebug() << "creating first set of data";
    
    //Now that we have our data lets put into the model
    tv.setModel(&myModel);
    tv.setUniformRowHeights(true);  //Speeds up scrolling
    tv.setSortingEnabled(true);  //enable sorting
    
    for (int row = 0; row < numberOfRows; row++)
    {
        //Inserting data into the model
        for (int col = 0; col < numCol; col++)
            myModel.setItem(row, col, new QStandardItem(QString::number(row)));
    
        masterRowNumber++;
    }
    
    qDebug() << "After first Insert into model" << timer.elapsed();
    qDebug() << "Now Deleting Data...";
    
    //sort the data - in the treeView
    tv.sortByColumn(2, Qt::AscendingOrder);  //this causes a long deley in delete
    
    //Now that our model is populated and shown in the treeView - lets delete rows
    // **** It takes forever to delete the first set of rows after the sort.  
    //In 5.12 This is very SLOW!!! but fast in Qt < 5.11.2
    tv.setSortingEnabled(false);
    myModel.removeRows(0, removeRows, QModelIndex());  //remove 40000 rows
    tv.setModel(&myModel);
    tv.setSortingEnabled(true);
    masterRowNumber -= removeRows;
    
    qDebug() << "After first delete of rows now creating new set of data"  << timer.elapsed();
    
    //now lets add more rows again
    for (int row = 0; row < numberOfRows; row++)
    {
        //Inserting data into the model
        for (int col = 0; col < numCol; col++)
           myModel.setItem(masterRowNumber, col, new QStandardItem(QString::number(row)));
    
        masterRowNumber++;
    }
    
    qDebug() << "After second insert into model"  << timer.elapsed();
    qDebug() << "Now Deleting..";
    
    //Again very slow!
    tv.setSortingEnabled(false);
    myModel.removeRows(0, removeRows, QModelIndex());  //remove 40000 rows
    tv.setSortingEnabled(true);
    masterRowNumber -= removeRows;
    
    qDebug() << "After second delete"  << timer.elapsed();
    
    
    qDebug() << "finished";
    

    }

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    executeTest();

    return a.exec();
    

    }

    VRoninV 1 Reply Last reply
    0
    • L leinad

      Hi,

      I was wondering if someone can help me with a problem I'm having using QStandardItemModel and perhaps show me to migrate my code to QAbstractItemModel. I have a tree view which is being populated using QStandardItemModel . The problem is when I try to remove rows; a lot of them it takes a long time. An example is removing 40,000+ rows. This used to work fine with Qt versions < 5.11.2. But now I'm migrated to 5.12 and it is extremely slow. Suggestions from others is to use QAbstractItemModel and remove the rows using that model. Below is a sample program which works fine with earlier version of Qt ( < 5.11.2 ).

      Can someone show me how to map to QAbstractItemModel or make it work just as fast with QStandardItemModel using the current version of Qt? I did a lot of reading but still don't understand how to do it. I'm fairly new to Qt so I need detail help if possible. I just need to know how to add data to the model for QAbstractItemModel equivalent to QStandardItemModel::setItem and how to remove rows equivalent to QStandardItemModel::removeRows.

      Regards,
      Dan


      #include <QtWidgets>

      //QAbstractItemModel Class
      void executeTest()
      {
      int masterRowNumber = 0;
      const int numberOfRows = 50000;
      const int removeRows = 40000;
      const int numCol = 15;

      QTreeView tv;
      QStandardItemModel myModel;
      QElapsedTimer timer;
      timer.start();
      
      qDebug() << "creating first set of data";
      
      //Now that we have our data lets put into the model
      tv.setModel(&myModel);
      tv.setUniformRowHeights(true);  //Speeds up scrolling
      tv.setSortingEnabled(true);  //enable sorting
      
      for (int row = 0; row < numberOfRows; row++)
      {
          //Inserting data into the model
          for (int col = 0; col < numCol; col++)
              myModel.setItem(row, col, new QStandardItem(QString::number(row)));
      
          masterRowNumber++;
      }
      
      qDebug() << "After first Insert into model" << timer.elapsed();
      qDebug() << "Now Deleting Data...";
      
      //sort the data - in the treeView
      tv.sortByColumn(2, Qt::AscendingOrder);  //this causes a long deley in delete
      
      //Now that our model is populated and shown in the treeView - lets delete rows
      // **** It takes forever to delete the first set of rows after the sort.  
      //In 5.12 This is very SLOW!!! but fast in Qt < 5.11.2
      tv.setSortingEnabled(false);
      myModel.removeRows(0, removeRows, QModelIndex());  //remove 40000 rows
      tv.setModel(&myModel);
      tv.setSortingEnabled(true);
      masterRowNumber -= removeRows;
      
      qDebug() << "After first delete of rows now creating new set of data"  << timer.elapsed();
      
      //now lets add more rows again
      for (int row = 0; row < numberOfRows; row++)
      {
          //Inserting data into the model
          for (int col = 0; col < numCol; col++)
             myModel.setItem(masterRowNumber, col, new QStandardItem(QString::number(row)));
      
          masterRowNumber++;
      }
      
      qDebug() << "After second insert into model"  << timer.elapsed();
      qDebug() << "Now Deleting..";
      
      //Again very slow!
      tv.setSortingEnabled(false);
      myModel.removeRows(0, removeRows, QModelIndex());  //remove 40000 rows
      tv.setSortingEnabled(true);
      masterRowNumber -= removeRows;
      
      qDebug() << "After second delete"  << timer.elapsed();
      
      
      qDebug() << "finished";
      

      }

      int main(int argc, char *argv[])
      {
      QApplication a(argc, argv);
      executeTest();

      return a.exec();
      

      }

      VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by
      #2

      @leinad said in Replace QstandItemModel with QAbstractItemModel:

      Suggestions from others is to use QAbstractItemModel and remove the rows using that model.

      I doubt it's going to solve anything. smells like a view problem.

      What is the resize policy you set on the headers of the view?

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      1 Reply Last reply
      1
      • L Offline
        L Offline
        leinad
        wrote on last edited by
        #3

        Is this what you mean?

        ui->topTreeView->setUniformRowHeights(true);

        mrjjM 1 Reply Last reply
        0
        • L leinad

          Is this what you mean?

          ui->topTreeView->setUniformRowHeights(true);

          mrjjM Offline
          mrjjM Offline
          mrjj
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @leinad
          Hi
          I think more like something like
          treeWidget->header()->setStretchLastSection(true);
          or
          treeWidget->header()->setSectionResizeMode(QHeaderView::ResizeToContents);

          Christian EhrlicherC 1 Reply Last reply
          0
          • L Offline
            L Offline
            leinad
            wrote on last edited by
            #5

            @mrjj said in Replace QstandItemModel with QAbstractItemModel:

            treeWidget->header()->setSectionResizeMode(QHeaderView::ResizeToContents);

            Both did not work. It can easily be tested in the sample code provided. The thing is remove rows worked perfectly fine and fast prior to 5.11.2. I don't see how setting the header will speed up removing rows from the model. I'm guessing I really need to subclass using QAbstractItemModel. Any help in doing that would be great.

            1 Reply Last reply
            0
            • mrjjM mrjj

              @leinad
              Hi
              I think more like something like
              treeWidget->header()->setStretchLastSection(true);
              or
              treeWidget->header()->setSectionResizeMode(QHeaderView::ResizeToContents);

              Christian EhrlicherC Offline
              Christian EhrlicherC Offline
              Christian Ehrlicher
              Lifetime Qt Champion
              wrote on last edited by
              #6

              @mrjj It's due a change in QStandardItemModel - see https://bugreports.qt.io/browse/QTBUG-78324 but I've no idea how to fix it without reverting the change. Therefore going to a custom model is (sadly) currently the way to go.

              Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
              Visit the Qt Academy at https://academy.qt.io/catalog

              1 Reply Last reply
              2
              • L Offline
                L Offline
                leinad
                wrote on last edited by
                #7

                This is why I respectfully request how to do this. I'm trying using the following example: https://doc.qt.io/qt-5/qtwidgets-itemviews-simpletreemodel-example.html but running into issues.

                1 Reply Last reply
                0
                • Christian EhrlicherC Offline
                  Christian EhrlicherC Offline
                  Christian Ehrlicher
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  Your example above uses a QTreeView but the data model looks like a table - so what do you need?

                  Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                  Visit the Qt Academy at https://academy.qt.io/catalog

                  1 Reply Last reply
                  0
                  • L Offline
                    L Offline
                    leinad
                    wrote on last edited by
                    #9

                    I need it work with a treeview. You can see that "tv" is initialized as a treeview. Basically the code above using treeview and abstract model. After that I can figure how to replace my larger base code with this simple example. That is all I need.

                    1 Reply Last reply
                    0
                    • Christian EhrlicherC Offline
                      Christian EhrlicherC Offline
                      Christian Ehrlicher
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      @leinad said in Replace QstandItemModel with QAbstractItemModel:

                      You can see that "tv" is initialized as a treeview

                      It does not matter what view you are using but what model you really use - your example code clearly shows us a table structure, not a tree structure - therefore my question...

                      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                      Visit the Qt Academy at https://academy.qt.io/catalog

                      1 Reply Last reply
                      0
                      • L Offline
                        L Offline
                        leinad
                        wrote on last edited by
                        #11

                        Its a table but I treat it like a tree which just a bunch of columns and rows like a spreadsheet. There is nothing fancy like children, grandchildren, etc.

                        1 Reply Last reply
                        0
                        • Christian EhrlicherC Offline
                          Christian EhrlicherC Offline
                          Christian Ehrlicher
                          Lifetime Qt Champion
                          wrote on last edited by
                          #12

                          So you don't need to implement a tree model and can use QAbstractTableModel as base instead which is much easier.

                          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                          Visit the Qt Academy at https://academy.qt.io/catalog

                          1 Reply Last reply
                          0
                          • L Offline
                            L Offline
                            leinad
                            wrote on last edited by
                            #13

                            Well, all my code is already around a treeview so I would prefer to stay that course. I would have to change the GUI plus the code which seems much more invasive. This is not a small project.

                            1 Reply Last reply
                            0
                            • L Offline
                              L Offline
                              leinad
                              wrote on last edited by
                              #14

                              I'm sorry, I misread what you are saying. I can look at using a QAbstractTableModel. Do you think the performance will be a good as it was before all of this?

                              1 Reply Last reply
                              0
                              • L Offline
                                L Offline
                                leinad
                                wrote on last edited by
                                #15

                                I have this code fragment which I'm having issues. I'm using QAbstractTableModel as suggested.

                                topTreeViewModel = new TopTreeViewModel();

                                void TopTreeViewModel::insertRowsIntoModel(int rowNumber, QList<QList<QStandardItem *>> QStandardItemList, TopTreeViewModel *model, QModelIndex parent)
                                {
                                beginInsertRows(QModelIndex(), rowNumber, rowNumber + QStandardItemList[0].size() - 1); //QModelIndex, rowNumber, numberOfRows
                                model->insertRows(rowNumber, QStandardItemList[0].size(), parent);
                                for(int rows = 0; rows < QStandardItemList.size(); rows++)
                                {

                                    for(int col = 0; col < QStandardItemList[rows].size(); col++)
                                    {
                                        QModelIndex index = model->index(rowNumber + rows, col, parent);
                                        model->setData(index, QStandardItemList[rows][col]->text(), Qt::DisplayRole);
                                    }
                                }
                                endInsertRows();
                                emit(dataChanged(parent, parent));
                                

                                }

                                I call it by using the following in another mainWindow:

                                metaDataModel->insertRowsIntoModel(rowNumber, QStandardItemList, metaDataModel, parent);
                                rowNumber += QStandardItemList.size();

                                I get an exception in beginInsertRows(); If I comment it out the data is correct but not displayed in the treeView.

                                The header is declared as follows (there are other methods but this is the one causing issues. Any help?
                                #ifndef TOPTREEVIEWMODEL_H
                                #define TOPTREEVIEWMODEL_H

                                #include <QObject>
                                #include <QAbstractTableModel>
                                #include <QStandardItem>
                                #include <QDebug>
                                

                                class TopTreeViewModel : public QAbstractTableModel
                                {
                                Q_OBJECT

                                public:
                                TopTreeViewModel(QObject *parent=0);
                                ~TopTreeViewModel();

                                public:

                                void insertRowsIntoModel(int rowNumber, QList<QList<QStandardItem *>> QStandardItemList, TopTreeViewModel *model, QModelIndex parent);

                                };

                                #endif // TOPTREEVIEWMODEL_H

                                JonBJ 1 Reply Last reply
                                0
                                • L leinad

                                  I have this code fragment which I'm having issues. I'm using QAbstractTableModel as suggested.

                                  topTreeViewModel = new TopTreeViewModel();

                                  void TopTreeViewModel::insertRowsIntoModel(int rowNumber, QList<QList<QStandardItem *>> QStandardItemList, TopTreeViewModel *model, QModelIndex parent)
                                  {
                                  beginInsertRows(QModelIndex(), rowNumber, rowNumber + QStandardItemList[0].size() - 1); //QModelIndex, rowNumber, numberOfRows
                                  model->insertRows(rowNumber, QStandardItemList[0].size(), parent);
                                  for(int rows = 0; rows < QStandardItemList.size(); rows++)
                                  {

                                      for(int col = 0; col < QStandardItemList[rows].size(); col++)
                                      {
                                          QModelIndex index = model->index(rowNumber + rows, col, parent);
                                          model->setData(index, QStandardItemList[rows][col]->text(), Qt::DisplayRole);
                                      }
                                  }
                                  endInsertRows();
                                  emit(dataChanged(parent, parent));
                                  

                                  }

                                  I call it by using the following in another mainWindow:

                                  metaDataModel->insertRowsIntoModel(rowNumber, QStandardItemList, metaDataModel, parent);
                                  rowNumber += QStandardItemList.size();

                                  I get an exception in beginInsertRows(); If I comment it out the data is correct but not displayed in the treeView.

                                  The header is declared as follows (there are other methods but this is the one causing issues. Any help?
                                  #ifndef TOPTREEVIEWMODEL_H
                                  #define TOPTREEVIEWMODEL_H

                                  #include <QObject>
                                  #include <QAbstractTableModel>
                                  #include <QStandardItem>
                                  #include <QDebug>
                                  

                                  class TopTreeViewModel : public QAbstractTableModel
                                  {
                                  Q_OBJECT

                                  public:
                                  TopTreeViewModel(QObject *parent=0);
                                  ~TopTreeViewModel();

                                  public:

                                  void insertRowsIntoModel(int rowNumber, QList<QList<QStandardItem *>> QStandardItemList, TopTreeViewModel *model, QModelIndex parent);

                                  };

                                  #endif // TOPTREEVIEWMODEL_H

                                  JonBJ Offline
                                  JonBJ Offline
                                  JonB
                                  wrote on last edited by JonB
                                  #16

                                  @leinad
                                  I haven't attempted to follow all your code, but:

                                  beginInsertRows(QModelIndex(), rowNumber, rowNumber + QStandardItemList[0].size() - 1); //QModelIndex, rowNumber, numberOfRows
                                  model->insertRows(rowNumber, QStandardItemList[0].size(), parent);
                                  for(int rows = 0; rows < QStandardItemList.size(); rows++)
                                  

                                  This does not look right, does it? For the "I get an exception in beginInsertRows();", I think you mean in the arguments to calling that function. There must be something fundamentally wrong in counting the required rows via QStandardItemList[0].size() but indexing/looping via rows < QStandardItemList.size(). The first has [0], the second does not. I would guess the latter is correct, and QStandardItemList[0].size() is to do with column count? Or maybe I'm going mad....

                                  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