Qt Forum

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

    Forum Updated on Feb 6th

    Solved QAbstractTableModel.data() called on full data, outside displayed ones

    General and Desktop
    5
    15
    384
    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.
    • woar
      woar last edited by

      Hi Qt Community,

      I'm having trouble with my application calling the data access function (QAbstractTableModel.data(index, role)) multiple times on indexes that are out of display range.
      My data is quite large (thousands of lines), and calling each and every cell multiple times (different roles) is not tractable.

      My questions are :

      • why is the data(index,role) called when the QTableView is not showed at all ? Sometimes multiple times !
      • why is it called on all indexes while only 30 lines are displayed when I finally display the QTableView ?
      • is this to be expected with QAbstractTableModel+QTableView, or is it due to poor coding on my part (which I hope) ? Then where should I look ?

      More details on my app and the problem as I see it :

      • I have two tabs,
        one with configuration : loading data from multiple files, updating the data content. No view is showed.
        one with the QTableView : 30 rows are displayed
      • When I launch my app :
        the system loads data (calling begin/endResetModel) multiple times
        the configuration tab is displayed (no view of the model)
        During call to MainWindow.show(), I can see that my whole data is called with DisplayRole on all rows, and this 2 times ! (I am still not displaying any view)
      • Then I switch to the "view" tab, containing the QTableView, for the first time
        I can see that my whole data is called with DisplayRole on all rows, and this four times !
        And right after, I can se that the 30 first rows are called with displayRole (which is expected)
        Using the tableview slider calls data() on the corresponding new rows to be displayed (also as expected)
      • Then, each time I switch to config and back to display, the data() is called on all rows, twice !
      • Each time I add a line (calling begin/endinsertRow), the whole data is read with data(displayRole)...

      Looking for advices !
      Thanks

      PS: I'm using Pyside2 (Qt for Python v5.13), but I guess the behavior is supposed to be similar to C++, and comments in C++ are welcome, I'll convert it to python.

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

        Please provide a minimal, compilable example so we can see what may go wrong.

        Qt has to stay free or it will die.

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

          Thanks @Christian-Ehrlicher , I was cleaning my code block by block to be able to show a lighter version here, and I started to be pretty sure the "problem" was comming from Qt as I had deleted almost every complicated thing from my code.

          Then I found these lines :

                  self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
                  self.table_view.verticalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
                  self.table_view.horizontalHeader().setStretchLastSection(True)
          

          They are the ones responsible, which acutally makes sense, Qt has to read all the data to find the max size of elements.

          Results of my trials: number of full data access by state :

                                Open App / Show TableView for the 1st time / show-hide TableView again / Resize window
          H Resize2Contents   :    1                   2                       1                           Crazy
          V Resize2Contents   :    0                   3                       1                           Crazy
          H+V Resize2Contents :    2                   4                       2                           Crazy
          H+V + HStretchLast  :    2                   6                       2                           Crazy
          HStretchLast only   :    0                   0                       0                             0
          

          In the end this was totally unrelated to my model, *ResetModel, ... but to display options...

          I hope this will save time to people in the future, who will think twice before using these functions that seem harmless !

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

            A good example on why a simple reproducer is a good starting point.
            See also QHeaderView::setResizeContentsPrecision - it may help you if you need to use this resize mode.

            /edit: and please mark the topic as solved, thx.

            Qt has to stay free or it will die.

            woar 1 Reply Last reply Reply Quote 2
            • woar
              woar @Christian Ehrlicher last edited by

              @Christian-Ehrlicher Thanks again, exactly what I needed.
              Still some strange behavior though :

                      self.table_view.horizontalHeader().setResizeContentsPrecision(0)
                      self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
              

              Works fine if I force the view tab to be selected at startup. Else (maybe because it doesnt know how many rows will be displayed), it runs through the entire data.

              On the other hand, the verticalHeader equivalent lines still process the whole data. Any idea why ?
              For now I will set it to Fixed.

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

                'Special value 0 means that it will look at only the visible area.'

                Qt has to stay free or it will die.

                1 Reply Last reply Reply Quote 1
                • B
                  brookbot last edited by

                  Someone should add a note to the documentation for those functions - its pathetically sparse and there should be ample warning.

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

                    Hi,

                    @Christian-Ehrlicher cited the content of the documentation of the function.

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    1 Reply Last reply Reply Quote 0
                    • S
                      StarterKit last edited by StarterKit

                      Pardon for posting in this old thread, but I found it during digging inside the same problem.
                      First, I thought that I found the solution here - setResizeContentsPrecision(0). But next, I tried to do

                      self.view.verticalHeader().setResizeContentsPrecision(0)
                      self.view.verticalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
                      

                      and it fetches all rows... Should setResizeContentsPrecision work for vertical header also?
                      If not - is there any way to have rows of different height in QTableView without reading whole table data?

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

                        @StarterKit said in QAbstractTableModel.data() called on full data, outside displayed ones:

                        If not - is there any way to have rows of different height in QTableView without reading whole table data?

                        No because then the size of the scrollbar can not be determined.

                        Qt has to stay free or it will die.

                        S 1 Reply Last reply Reply Quote 0
                        • S
                          StarterKit @Christian Ehrlicher last edited by

                          @Christian-Ehrlicher , yes, I see your point. But this is valid if we calculate scroll bar position based on row geometry. As alternative - we may calculate scroll bar size/position based on row count - it will give neglegible error for tables with tens of rows (and almost 0 error for large tables with hunderds -thousands rows...). I think it might be a useful feature of QTableVew/QHeaderView...

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

                            Feel free to provide a patch for it :)

                            Qt has to stay free or it will die.

                            S 1 Reply Last reply Reply Quote 0
                            • S
                              StarterKit @Christian Ehrlicher last edited by

                              @Christian-Ehrlicher said in QAbstractTableModel.data() called on full data, outside displayed ones:

                              Feel free to provide a patch for it :)

                              Ok, will read a bit about how to build Qt from source and make changes. Have never done it before.

                              SGaist 1 Reply Last reply Reply Quote 0
                              • SGaist
                                SGaist Lifetime Qt Champion @StarterKit last edited by

                                @StarterKit Since you would like to create a patch (that's cool, thanks), don't try to build the whole of Qt since your patch is located in qtbase, you can just build that module and go hacking.

                                Interested in AI ? www.idiap.ch
                                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                S 1 Reply Last reply Reply Quote 0
                                • S
                                  StarterKit @SGaist last edited by StarterKit

                                  @SGaist thanks for the advice. I'll try to do it in spare time.

                                  Right now I decided to play with QTableView::setRowHeight(). It appears to do the job quite well, but code structure looks ugly.
                                  But looking how fast it does the job I really start thinking that it is a bug that setResizeContentsPrecision(0) doesn't work for vertical header.

                                  I.e. as a first test I called setRowHeight() from data() method of the model. This method is called many times for different roles and columns. And even in these non-optimal conditions it works well as it is called for visible rows only. And there are no problems with scrollbar at all - it works as it should. I assume with setResizeContentsPrecision(0) it may do the same or similar action but with only one call to data() for SizeHintRole.

                                  I reported QTBUG-100818 first of all for documentation, but mentioned there my doubts.

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