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. What to do if I can't make a call to `beginInsertRows()` before data is changed?
Forum Updated to NodeBB v4.3 + New Features

What to do if I can't make a call to `beginInsertRows()` before data is changed?

Scheduled Pinned Locked Moved Solved General and Desktop
6 Posts 3 Posters 190 Views 2 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.
  • P Offline
    P Offline
    peter.thompson
    wrote 22 days ago last edited by peter.thompson
    #1

    I am implementing QAbstractTableModel with a pointer to some shared data. This data might be changed by the QAbstractTableModel that I am currently writing, but it might also be changed by other parts of the application. How do I handle when records are inserted into the data by something other than the QAbstractTableModel? If the model does the insertion, I can control it and make sure it first calls beginInsertRows(), then inserts the data, and finally calls endInsertRows() (which appears to be the proper method). However, if something else inserts an item, all I will get is a signal after the insertion. So it is impossible to call beginInsertRows() before the change has occurred.

    Qt's documentation seems to indicate that this method must be called before the change occurs. And as far as I can tell, there is no alternative. From the docs for QAbstractItemModel::beginInsertRows:

    Begins a row insertion operation.

    When reimplementing insertRows() in a subclass, you must call this function before inserting data into the model's underlying data store.

    As a last resort, I could try to apply some changes to the class that holds the data on the back end, so that it would emit a signal before a change. However, this is a complicated class that is used throughout the code base, so making this change could be risky and would likely add a lot of development time.

    I have this same question about beginRemoveRows(), beginMoveRows(), and beginResetModel(). It would be fantastic if there were a general solution for responding to any of these operations after the fact.

    A 1 Reply Last reply 22 days ago
    0
    • K Offline
      K Offline
      KH-219Design
      wrote 22 days ago last edited by KH-219Design
      #5

      @peter.thompson You may be able to leverage the following fact into a workaround for your situation.

      I can state from experience that calling these one after the other ("on the same line", as it were) will trigger the signal you probably want/need to have emitted from the (I believe it is modelUpdated, but don't quote me 😉)

      beginResetModel(); endResetModel();
      

      (of course they don't literally need to be on one line. I'm just emphasizing that you can call them back-to-back, without having changes to the data happen in between, and the result will be that the model "updates" at this time, as far as other watcher objects are concerned)

      beginResetModel(); 
      endResetModel();
      

      ... is also fine.

      I have done this in several applications, and at the time I also looked inside the Qt source code to convince myself that it indeed does do what I intend. My use case was not the case that you describe. Rather, I simply had a "complex", many-nested-if-statement logic for selecting which rows were updated in any given case, and I didn't want to add more complexity trying to meticulously piece together what arguments to pass to dataChanged, so I found I could just do this "hack" at the appropriate point, to signal to the relevant QML to repaint "the whole model" (the visual UI representation thereof, more accurately).

      www.219design.com
      Software | Electrical | Mechanical | Product Design

      P 1 Reply Last reply 18 days ago
      0
      • P peter.thompson
        22 days ago

        I am implementing QAbstractTableModel with a pointer to some shared data. This data might be changed by the QAbstractTableModel that I am currently writing, but it might also be changed by other parts of the application. How do I handle when records are inserted into the data by something other than the QAbstractTableModel? If the model does the insertion, I can control it and make sure it first calls beginInsertRows(), then inserts the data, and finally calls endInsertRows() (which appears to be the proper method). However, if something else inserts an item, all I will get is a signal after the insertion. So it is impossible to call beginInsertRows() before the change has occurred.

        Qt's documentation seems to indicate that this method must be called before the change occurs. And as far as I can tell, there is no alternative. From the docs for QAbstractItemModel::beginInsertRows:

        Begins a row insertion operation.

        When reimplementing insertRows() in a subclass, you must call this function before inserting data into the model's underlying data store.

        As a last resort, I could try to apply some changes to the class that holds the data on the back end, so that it would emit a signal before a change. However, this is a complicated class that is used throughout the code base, so making this change could be risky and would likely add a lot of development time.

        I have this same question about beginRemoveRows(), beginMoveRows(), and beginResetModel(). It would be fantastic if there were a general solution for responding to any of these operations after the fact.

        A Online
        A Online
        Axel Spoerl
        Moderators
        wrote 22 days ago last edited by
        #2

        @peter.thompson said in What to do if I can't make a call to `beginInsertRows()` before data is changed?:

        apply some changes to the class that holds the data

        Here's the architectural flaw. The QAbstractTableModel is supposed to be the sole data holder. It is supposed to be modified with the setData() override or individually implemented data setter. But it is not supposed to be modified outside the model.

        Software Engineer
        The Qt Company, Oslo

        P 1 Reply Last reply 22 days ago
        0
        • A Axel Spoerl
          22 days ago

          @peter.thompson said in What to do if I can't make a call to `beginInsertRows()` before data is changed?:

          apply some changes to the class that holds the data

          Here's the architectural flaw. The QAbstractTableModel is supposed to be the sole data holder. It is supposed to be modified with the setData() override or individually implemented data setter. But it is not supposed to be modified outside the model.

          P Offline
          P Offline
          peter.thompson
          wrote 22 days ago last edited by peter.thompson
          #3

          @Axel-Spoerl Thanks for your response. Is there any way to make QAbstractTableModel work with shared data, where it can't be the sole data holder?

          I ask because the architecture of our data isn't something I am able to change. (This is for a large, established codebase.) I am looking into adding a QAbstractTableModel as an interface to our existing data, to make it work with Qt's views. But if that's not the intended use of QAbstractTableModel, and if there's no way to make that work, then I might look into a different solution, one that doesn't use Qt's model/view framework.

          1 Reply Last reply
          0
          • A Online
            A Online
            Axel Spoerl
            Moderators
            wrote 22 days ago last edited by
            #4

            This is a very general discussion. If you want to present data in a UI, the UI needs to be informed about data changes, in order to reflect them correctly. The Qt implementation of this concept is model/view. Data changes of any kind have to be handled as describe [here](link url) to make it work. Other frameworks may provide other implementations. That won't remove the need to notify the UI about every data change.

            As long as the "class holding the data" can ensure, that every change is announced to the model as described above, the model/view implementation will work. IMHO handling this after the fact is just more complicated to implement and more error prone. Again, this is independent from the framework used for the UI.

            Maybe you want to explain in more detail, what your data holding class looks like, where the data comes from and how it is modified.

            Software Engineer
            The Qt Company, Oslo

            1 Reply Last reply
            0
            • K Offline
              K Offline
              KH-219Design
              wrote 22 days ago last edited by KH-219Design
              #5

              @peter.thompson You may be able to leverage the following fact into a workaround for your situation.

              I can state from experience that calling these one after the other ("on the same line", as it were) will trigger the signal you probably want/need to have emitted from the (I believe it is modelUpdated, but don't quote me 😉)

              beginResetModel(); endResetModel();
              

              (of course they don't literally need to be on one line. I'm just emphasizing that you can call them back-to-back, without having changes to the data happen in between, and the result will be that the model "updates" at this time, as far as other watcher objects are concerned)

              beginResetModel(); 
              endResetModel();
              

              ... is also fine.

              I have done this in several applications, and at the time I also looked inside the Qt source code to convince myself that it indeed does do what I intend. My use case was not the case that you describe. Rather, I simply had a "complex", many-nested-if-statement logic for selecting which rows were updated in any given case, and I didn't want to add more complexity trying to meticulously piece together what arguments to pass to dataChanged, so I found I could just do this "hack" at the appropriate point, to signal to the relevant QML to repaint "the whole model" (the visual UI representation thereof, more accurately).

              www.219design.com
              Software | Electrical | Mechanical | Product Design

              P 1 Reply Last reply 18 days ago
              0
              • K KH-219Design
                22 days ago

                @peter.thompson You may be able to leverage the following fact into a workaround for your situation.

                I can state from experience that calling these one after the other ("on the same line", as it were) will trigger the signal you probably want/need to have emitted from the (I believe it is modelUpdated, but don't quote me 😉)

                beginResetModel(); endResetModel();
                

                (of course they don't literally need to be on one line. I'm just emphasizing that you can call them back-to-back, without having changes to the data happen in between, and the result will be that the model "updates" at this time, as far as other watcher objects are concerned)

                beginResetModel(); 
                endResetModel();
                

                ... is also fine.

                I have done this in several applications, and at the time I also looked inside the Qt source code to convince myself that it indeed does do what I intend. My use case was not the case that you describe. Rather, I simply had a "complex", many-nested-if-statement logic for selecting which rows were updated in any given case, and I didn't want to add more complexity trying to meticulously piece together what arguments to pass to dataChanged, so I found I could just do this "hack" at the appropriate point, to signal to the relevant QML to repaint "the whole model" (the visual UI representation thereof, more accurately).

                P Offline
                P Offline
                peter.thompson
                wrote 18 days ago last edited by
                #6

                @KH-219Design Thanks for your response. I've tried this and it appears to work everywhere that I need it to, so I am planning to move forward with your solution.

                I should note, there does appear to be one limitation with this solution: calling beginResetModel() and endResetModel() not only updates the model/view but also deselects all items. I would guess that this is because resetting the model also resets the selection model. This should be fine in my use case, but just wanted to note it for anyone else who might read this.

                1 Reply Last reply
                1
                • P peter.thompson has marked this topic as solved 18 days ago

                6/6

                20 May 2025, 00:43

                • Login

                • Login or register to search.
                6 out of 6
                • First post
                  6/6
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved