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. BeginResetModel() not working
Qt 6.11 is out! See what's new in the release blog

BeginResetModel() not working

Scheduled Pinned Locked Moved General and Desktop
31 Posts 4 Posters 20.2k 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.
  • deisikD Offline
    deisikD Offline
    deisik
    wrote on last edited by
    #1

    As per documentation, "you must call this function before resetting any internal data structures in your model or proxy model" and regarding its counterpart, endResetModel(), "you must call this function after resetting any internal data structure in your model or proxy model". Rational reasoning tells me that by beginResetModel() you declare your data being no longer valid (read unavailable) and by endResetModel() being valid again while changing it somewhere in between so that any views getting data from the model should shrink from quering data which is not yet ready. Everything seems consistent and coherent in this simple logic, right?

    But experience does not follow these considerations

    In my model I am using a QProgressDialog (qt 4.8.0) while inside beginResetModel/endResetModel block and the view attached to this model does try to query data from it showing garbage from partially rebuilt data (if not crashing). Presently, instead of changing an existing dataset I have to build a new one from scratch and then reassign half a dozen of pointers to get rid of this misconception. In my opinion this is neither the best nor the right thing to do - these data structures are greedy for memory and cpu, to put it mildly (mind, I ain't using a progress bar just for the fun of it)

    So my question, am I missing something with what beginResetModel/endResetModel functions are used for (and the meaning of the code they are supposed to enclose) or should I report a bug in case I am right in my assumptions?

    1 Reply Last reply
    0
    • ? Offline
      ? Offline
      A Former User
      wrote on last edited by
      #2

      From my experience this works without problems. I use it in my models and never ran into trouble. Without seeing any code we cannot comment any further.

      1 Reply Last reply
      0
      • deisikD Offline
        deisikD Offline
        deisik
        wrote on last edited by
        #3

        I've made a bug report "here":https://bugreports.qt-project.org/browse/QTBUG-24096

        1 Reply Last reply
        0
        • ? Offline
          ? Offline
          A Former User
          wrote on last edited by
          #4

          I could reproduce that error with your test case. It's really strange and annoying. Thanks for opening the bug report, I've voted for it.

          1 Reply Last reply
          0
          • deisikD Offline
            deisikD Offline
            deisik
            wrote on last edited by
            #5

            It feels like no one really cares out there. In the meantime I've managed a simple workaround by caching all items currently in the viewport and feeding them to the view while tacitly rebuilding the whole model in the background

            1 Reply Last reply
            0
            • deisikD Offline
              deisikD Offline
              deisik
              wrote on last edited by
              #6

              At last someone deigned an answer in the bug tracker. They say it is not a bug, that beginResetModel and endResetModel can't be split by an event loop running. If they mean that the beginResetModel/endResetModel block should't be bothered from outside then the whole concept makes no sense, for its purpose as far as I get it is exactly to guarantee that the code within may not be interrupted for quering data, which beginResetModel/endResetModel surely fail to do

              1 Reply Last reply
              0
              • A Offline
                A Offline
                andre
                wrote on last edited by
                #7

                I think that Stephen is right in his comment, though I am not 100% sure. I'd (or you'd) have to dig in the code of QAbstractItemModel to see what this begin/end pair actually does. My guestimate is that it will block signals from the model to the view, so you are free to mess with internal data structures without triggering any premature updates to the view. However, it will not inform the view by itself. That means that if you return to the eventloop, things like a paintevent in the view may still result in data queries.

                1 Reply Last reply
                0
                • deisikD Offline
                  deisikD Offline
                  deisik
                  wrote on last edited by
                  #8

                  [quote author="Andre" date="1348644977"]My guestimate is that it will block signals from the model to the view, so you are free to mess with internal data structures without triggering any premature updates to the view[/quote]

                  There are no signals from the model which are not explicitly specified in the code of the model. What sense does it make to emit signals to the view besides these two in the data rebuild routine?
                  [quote author="Andre" date="1348644977"]However, it will not inform the view by itself. That means that if you return to the eventloop, things like a paintevent in the view may still result in data queries[/quote]

                  This contradicts to what Stephen wrote. If event loops are explicitly prohibited (by definition, i.e. they shouldn't be used as he says, not because they can't be used) within beginResetModel/endResetModel then there is no sense in beginResetModel/endResetModel as such because these methods do nothing to impose this prohibition

                  1 Reply Last reply
                  0
                  • D Offline
                    D Offline
                    dangelog
                    wrote on last edited by
                    #9

                    I think you're misusing beginResetModel/endResetModel.

                    • beginResetModel/endResetModel will simply cause the emission of the model's modelAboutToBeReset / modelReset signals, update bookeeping information (persistent indexes), etc.
                    • views are allowed to ask for data() at any time, therefore returning to the event loop with the model in a "inconsistent" state is wrong

                    In your testcase you're simply adding rows/columns with a progress, and therefore you should actually be using beginInsertRows / beginInsertColumns; or, complete the model reset in each iteration, before returning to the event loop.

                    Software Engineer
                    KDAB (UK) Ltd., a KDAB Group company

                    1 Reply Last reply
                    0
                    • A Offline
                      A Offline
                      andre
                      wrote on last edited by
                      #10

                      [quote author="deisik" date="1348647304"][quote author="Andre" date="1348644977"]My guestimate is that it will block signals from the model to the view, so you are free to mess with internal data structures without triggering any premature updates to the view[/quote]

                      There are no signals from the model which are not explicitly specified in the code of the model. What sense does it make to specify signals in the data rebuild routine?[/quote]
                      I'm not sure I understand exactly what you mean here, but like I said: if you really want to know what it does: the source is there for you to inspect. Like I said: I was only guessing.
                      [quote]
                      [quote author="Andre" date="1348644977"]However, it will not inform the view by itself. That means that if you return to the eventloop, things like a paintevent in the view may still result in data queries[/quote]

                      This contradicts to what Stephen wrote. If event loops are explicitly prohibited (by definition as he says, not because they can't be used) within beginResetModel/endResetModel then there is no sense in beginResetModel/endResetModel as such because these methods do nothing to impose this prohibition[/quote]
                      [/quote]
                      No, I don't think it contradicts, but if it does: trust Stephen on this, not me.

                      You should keep in mind that any signal that you trigger results in a direct method call, unless the connection is of queued type. That normally only is the case for signal-slot connections between threads. So no, you do not need an eventloop for signal-slot connections to work. Anything you do during your reset may trigger signals that I suspect will be blocked by the beginResetModel. However, note that there is a modelAboutToBeReset() signal, so that will be emitted for sure.

                      1 Reply Last reply
                      0
                      • deisikD Offline
                        deisikD Offline
                        deisik
                        wrote on last edited by
                        #11

                        [quote author="peppe" date="1348647631"]

                        • beginResetModel/endResetModel will simply cause the emission of the model's modelAboutToBeReset / modelReset signals, update bookeeping information (persistent indexes), etc.
                        • views are allowed to ask for data() at any time, therefore returning to the event loop with the model in a "inconsistent" state is wrong[/quote]

                        Your first proposition contradics the second one. Views being allowed to ask for data at any time means that model should always be in a consistent state. And what about resetting model in this case?

                        1 Reply Last reply
                        0
                        • deisikD Offline
                          deisikD Offline
                          deisik
                          wrote on last edited by
                          #12

                          [quote author="Andre" date="1348647770"]Anything you do during your reset may trigger signals that I suspect will be blocked by the beginResetModel. However, note that there is a modelAboutToBeReset() signal, so that will be emitted for sure.[/quote]

                          No, they don't get blocked as you can see in the test case

                          1 Reply Last reply
                          0
                          • A Offline
                            A Offline
                            andre
                            wrote on last edited by
                            #13

                            [quote author="deisik" date="1348648089"][quote author="peppe" date="1348647631"]

                            • beginResetModel/endResetModel will simply cause the emission of the model's modelAboutToBeReset / modelReset signals, update bookeeping information (persistent indexes), etc.
                            • views are allowed to ask for data() at any time, therefore returning to the event loop with the model in a "inconsistent" state is wrong[/quote]

                            Your first proposition contradics the second one. Views being allowed to ask for data at any time means that model should always be in a consistent state. And what about resetting model in this case?

                            [/quote]
                            No, it is not a contradiction. It means that models always need to be in a consistent state at the moment that they:

                            • return to the eventloop, or
                            • emit signals (that also yields control and may trigger a view asking for data, directly or indirectly)

                            So: don't do the above during your reset. As long as you don't, the view's can't request data, as the current point in your code is in your model reset procedure, not in a view querying your model. Unless you are using multiple threads, which is not supported between a model and a view.

                            Edit:

                            [quote author="deisik" date="1348648438"][quote author="Andre" date="1348647770"]Anything you do during your reset may trigger signals that I suspect will be blocked by the beginResetModel. However, note that there is a modelAboutToBeReset() signal, so that will be emitted for sure.[/quote]

                            No, they don't get blocked as you can see in the test case
                            [/quote]
                            No, you are right. If you look at the source code, all it does (in 4.8.1) is:
                            @

                            void QAbstractItemModel::beginResetModel()
                            {
                            emit modelAboutToBeReset();
                            }
                            @

                            So, no signal blocking. My guestimate was wrong.

                            1 Reply Last reply
                            0
                            • deisikD Offline
                              deisikD Offline
                              deisik
                              wrote on last edited by
                              #14

                              [quote author="Andre" date="1348648503"]No, it is not a contradiction. It means that models always need to be in a consistent state at the moment that they:

                              • return to the eventloop, or
                              • emit signals (that also yields control and may trigger a view asking for data, directly or indirectly)[/quote]

                              This basically means that beginResetModel/endResetModel are meaningless/useless because they don't block return to the eventloop, which occurs if you (me) try to run a progress bar for data reset process. They just do nothing, if you don't return to eventloop, views in no case by themselves will query data (unless explicitly called to do so) from the model and if you do, beginResetModel/endResetModel just won't block

                              You seem to miss my whole point

                              1 Reply Last reply
                              0
                              • A Offline
                                A Offline
                                andre
                                wrote on last edited by
                                #15

                                How do you know they are meaningless? They just don't do what you expected them to do. How do you know that the view may not have an optimization so that at the moment it receives the modelAboutToBeReset signal, is stops listening or does other clever stuff such as clearing a cache or whatever magic needs to be done? I don't. And I certainly don't know that of any custom view living out there in the wild. What is done with the signal in the default Qt views, you can find out by inspecting the source code of those views yourself.

                                Anyway: where is it documented that the beginResetModel blocks a return to the eventloop? How should that even work? Like I said: I imagined it would block further signals (and that would have been possible to do), but it does not. But returning to the eventloop is something that is very hard to prevent.

                                If I miss your whole point, then perhaps you should try to explain it again, but this time without complaints that your assumptions of how Qt model view works don't match with reality. Then, perhaps, we can help you search for a solution or a workaround for your specific scenario. We all know that Qt model view is not perfect and that some use cases are hard to implement with it.

                                1 Reply Last reply
                                0
                                • deisikD Offline
                                  deisikD Offline
                                  deisik
                                  wrote on last edited by
                                  #16

                                  [quote author="Andre" date="1348649547"]How do you know they are meaningless? They just don't do what you expected them to do. [/quote]

                                  Because if you don’t get returned to eventloop views simply can't query data from the model (with or without beginResetModel/endResetModel) by themselves (unless directly asked to do so, indeed). But if you do (despite beginResetModel) they will, which means they are still listening. Rather simple logic, right?

                                  [quote author="Andre" date="1348649547"]Anyway: where is it documented that the beginResetModel blocks a return to the eventloop? How should that even work? Like I said: I imagined it would block further signals (and that would have been possible to do), but it does not. But returning to the eventloop is something that is very hard to prevent[/quote]

                                  It's written in the docs that beginResetModel/endResetModel are used for safe resetting of the model internal data structures, which these methods fail to do. That's all

                                  [quote author="Andre" date="1348649547"]If I miss your whole point, then perhaps you should try to explain it again, but this time without complaints that your assumptions of how Qt model view works don't match with reality[/quote]

                                  These are really not my assumptions. It's not me who started talking about event loops

                                  [quote author="Andre" date="1348649547"]Then, perhaps, we can help you search for a solution or a workaround for your specific scenario. We all know that Qt model view is not perfect and that some use cases are hard to implement with it[/quote]

                                  I have already found a workaround (see above)

                                  1 Reply Last reply
                                  0
                                  • D Offline
                                    D Offline
                                    dangelog
                                    wrote on last edited by
                                    #17

                                    [quote author="deisik" date="1348648089"][quote author="peppe" date="1348647631"]

                                    • beginResetModel/endResetModel will simply cause the emission of the model's modelAboutToBeReset / modelReset signals, update bookeeping information (persistent indexes), etc.
                                    • views are allowed to ask for data() at any time, therefore returning to the event loop with the model in a "inconsistent" state is wrong[/quote]

                                    Your first proposition contradics the second one. Views being allowed to ask for data at any time means that model should always be in a consistent state. And what about resetting model in this case?
                                    [/quote]

                                    I think you're missing an obvious assumption, my fault: from the point of view of your code, Qt is a single-threaded and event-driven. (You can start other threads but that's out the question here, we're in the GUI thread.)

                                    Therefore, the view's code that fetches data cannot be running at the same time you're updating the model. The views might fetch in response to the signals you emit when you call begin*/end* methods, but this makes no sense to me (and in any case, WHEN you're calling those methods, the model IS ALREADY in a consistent state. Either it's BEFORE any modification happened, or it's AFTER all modifications have been made).

                                    Software Engineer
                                    KDAB (UK) Ltd., a KDAB Group company

                                    1 Reply Last reply
                                    0
                                    • deisikD Offline
                                      deisikD Offline
                                      deisik
                                      wrote on last edited by
                                      #18

                                      [quote author="peppe" date="1348647631"]In your testcase you're simply adding rows/columns with a progress, and therefore you should actually be using beginInsertRows / beginInsertColumns; or, complete the model reset in each iteration, before returning to the event loop.[/quote]

                                      Yes, just to show that the program will crash. In the actual model the data is changed completely, rows/columns can be added, removed or their number can remain the same, but all data is changed in all rows/columns

                                      1 Reply Last reply
                                      0
                                      • deisikD Offline
                                        deisikD Offline
                                        deisik
                                        wrote on last edited by
                                        #19

                                        [quote author="peppe" date="1348651164"]Therefore, the view's code that fetches data cannot be running at the same time you're updating the model. The views might fetch in response to the signals you emit when you call begin*/end* methods, but this makes no sense to me (and in any case, WHEN you're calling those methods, the model IS ALREADY in a consistent state. Either it's BEFORE any modification happened, or it's AFTER all modifications have been made).[/quote]

                                        That's what I am talking about. The model is inconsistent WITHIN begin/end methods, so no view may query data. And as it turns out the methods don't guarantee this (even if there're no signals WITHIN this block or any other which is explicitly being called)

                                        1 Reply Last reply
                                        0
                                        • A Offline
                                          A Offline
                                          andre
                                          wrote on last edited by
                                          #20

                                          [quote author="deisik" date="1348651720"]That's what I am talking about. The model is inconsistent WITHIN begin/end methods, so no view may query data. And as it turns out the methods don't guarantee this

                                          [/quote]

                                          And it seems that you were (are still?) assuming that beginResetModel() would (should?) somehow enforce that, no matter what you did before calling endResetModel(). That assumption turns out to be wrong.

                                          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