Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-67693

QTreeView erroneously fetches all items with fetchMore()

    XMLWordPrintable

Details

    • Bug
    • Resolution: Incomplete
    • P3: Somewhat important
    • None
    • 5.15.2
    • Widgets: Itemviews
    • None

    Description

      Hi, I'm developing a program which on user's request fetches some data from Internet, stores it in a QAbstractTableModel derived model and shows it in QTreeView.

      My model reimplements canFetchMore() and fetchMore() functions so additional data is only downloaded when the user scrolls to the end of the list. Because I don't have the data at hand when it's needed (it must be downloaded first), I can't just add new data in fetchMore(). So instead I just make a request in fetchMore() and when the data arrives it is added to the model.

      And here is the problem: when my model is used by QTreeView, after requested items arrive to the model and beginInsertRows()/endInsertRows() are called, the view calls canFetchMore() and subsequently fetchMore() so another batch of items is fetched automatically and this behavior is repeated until canFetchMore() returns false (so all data items were fetched). This is a different behavior from QListView and QTableView which both correctly call fetchMore() only once and when later the data arrives they stop calling fetchMore() unless the user scrolls to the end of the list.

      To present the problem I've prepared a simple project. There is a ModelBase class and two derived models which reimplement fetchMore(): first model adds items synchronously in fetchMore() and the other one asynchronously with QTimer::singleshot() invoked in fetchMore(). QTreeView works correctly with the synchronous model but not with the asynchronous one.

      Partial ModelBase class:

      class ModelBase : public QAbstractListModel
      {
      public:
      // {...}
          void createMoreItems();
      protected:
          bool moreItemsAvailable; // true if items.size() <  maxItems
      private:
          std::vector<QString> items;
          const int maxItems = 1000; // don't fetch more then this
          const int itemsPerRequest = 50;
      };
      
      bool ModelBase::canFetchMore(const QModelIndex &parent) const
      {
          return moreItemsAvailable;
      }
      
      void ModelBase::createMoreItems()
      {
          if (!moreItemsAvailable)
              return;
      
          QStringList newItems;
          for (int i = 0; i < itemsPerRequest; ++i)
              newItems.push_back(QString("Item ") + QString::number(items.size() + i));
      
          beginInsertRows(QModelIndex(), items.size(), items.size() + newItems.size() - 1);
      
          items.insert(items.end(), newItems.begin(), newItems.end());
          moreItemsAvailable = (items.size() <  maxItems ? true : false);
      
          endInsertRows();
      }

      Synchronous model adds items directly in fetchMore():

      void SynchronousModel::fetchMore(const QModelIndex &parent)
      {
          createMoreItems();
      }

      Asynchronous model adds items asynchronously:

      void AsynchronousModel::fetchMore(const QModelIndex &parent)
      {
          QTimer::singleShot(0, this, &ModelBase::createMoreItems);
      }

      This project shows that synchronous model works correctly with all views (QListView, QTableView, QTreeView) but asynchronous model doesn't work correctly with QTreeView (after new items are inserted and canFetchMore() returns true, fetchMore() is called again), only with QListView and QTableView.

      The documentation for canFetchMore(), fetchMore() and Model/View Programming is not clear whether it is mandatory to insert new items synchronously.

      I don't know if it's a QTreeView's design constraint (handling a tree structure might require additional data) or a bug so I'm reporting this issue as a bug to at least clarify the matter.

      I'm attaching a complete project archive and a screenshot which shows the problem.

       

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            qt.team.quick.subscriptions Qt Quick and Widgets Team
            atomblender atomblender
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes