Qt Forum

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

    Unsolved QTreeView erroneously fetches all items with fetchMore()

    General and Desktop
    qtreeview canfetchmore fetchmore
    3
    9
    2289
    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.
    • A
      atomblender last edited by atomblender

      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, the view calls fetchMore() automatically 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.

      I've prepared a simplified example. There is a base model 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.

      Model base 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);
      }
      

      I also created a simple app that shows the problem: synchronous model works correctly with all views (QListView, QTableView, QTreeView) but asynchronous model doesn't work correctly with QTreeView.

      Screenshot: https://bugreports.qt.io/secure/attachment/71496/treeviewtest.png

      The project archive: https://bugreports.qt.io/secure/attachment/71497/treeviewtest.zip

      So I wonder if I don't understand something about Model/View in Qt or it's a Qt bug?

      Also, I use QTreeView instead of QTableView with my QAbstractTableModel derived class because I want that mouse hover highlights entire row instead of a single cell which is probably not possible in QTableView without some workarounds.0_1523484146080_treeviewtest.png

      1 Reply Last reply Reply Quote 0
      • Christian Ehrlicher
        Christian Ehrlicher Lifetime Qt Champion last edited by

        This looks like https://bugreports.qt.io/browse/QTBUG-18075 - at least the backtrace looks like the description there

        Qt has to stay free or it will die.

        A 1 Reply Last reply Reply Quote 4
        • A
          atomblender @Christian Ehrlicher last edited by

          @Christian-Ehrlicher: Thanks for reply. I've also tried to find bugs related to fetchMore():
          https://bugreports.qt.io/browse/QTBUG-18075?jql=text ~ "fetchmore"
          Without success, however. I'm thinking now about reporting a bug but I'm worried that it's a bug in my own code.

          V 1 Reply Last reply Reply Quote 0
          • V
            VRonin @atomblender last edited by

            @atomblender said in QTreeView erroneously fetches all items with fetchMore():

            I'm worried that it's a bug in my own code.

            Yes and no. I can see how you want it to work but the problem is you are telling lies to your view in the async way.

            You return true from canFetchMore so the view fetches and lays out the new data but you are delaying when that data is made available so the view thinks it still needs to lay it out and so repeats the process. This ends when canFetchMore returns false so the view gives up. At this point the model processes all the data fetching and signals the view to repaint itself

            "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

            A 1 Reply Last reply Reply Quote 4
            • A
              atomblender @VRonin last edited by atomblender

              @VRonin: Thanks for your reply. What is confusing is that the documentation for canFetchMore(), fetchMore() and Model/View Programming is not clear whether it is mandatory to insert new items synchronously and that QListView and QTableView work correctly with asynchronous item fetching. This inconsistency in behavior leads me to believe that it might be a bug in QTreeView. Another possibility is that there is something special about QTreeView.

              1 Reply Last reply Reply Quote 0
              • V
                VRonin last edited by

                QTreeView, differently from the others need to query individual items to lay out itself (basically it needs to know if an item in the first column has children or not).

                I'm not saying this behaviour is totally intended and ideal, what I'm saying is that your use case is in a grey area of who's to blame and I wouldn't be surprised if your bug report ends up with an "invalid" sticker on it (i'm not involved in Qt development at all so I might be epically wrong)

                "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 Reply Quote 3
                • A
                  atomblender last edited by atomblender

                  I've reported a bug: 67693

                  If it's a real bug then the issue will hopefully be fixed. If it's a QTreeview's limitation or the bug won't be fixed than I will have to find a workaround. At the very least the matter will be clarified.

                  V 1 Reply Last reply Reply Quote 0
                  • V
                    VRonin @atomblender last edited by

                    @atomblender Put the affected version as the latest one or you might get ignored

                    "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

                    A 1 Reply Last reply Reply Quote 1
                    • A
                      atomblender @VRonin last edited by atomblender

                      @VRonin: Ok, updated to 5.10.1

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