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. QSortFilterProxy & QIdentityProxyModel & QAbstractItemModel = Crash :- )

QSortFilterProxy & QIdentityProxyModel & QAbstractItemModel = Crash :- )

Scheduled Pinned Locked Moved Solved General and Desktop
qabstractitemmoqsortfilterproxqidentityproxymdrag and dropdrag&drop
26 Posts 5 Posters 4.2k Views
  • 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.
  • V VRonin
    3 Jan 2020, 10:34

    Try spawning a Model Test side by side your model. Most of the time the error is easily caught by the test and it gives you a very good clue on what's going wrong

    D Offline
    D Offline
    Dariusz
    wrote on 25 Jan 2020, 10:50 last edited by
    #9

    @VRonin said in QSortFilterProxy & QIdentityProxyModel & QAbstractItemModel = Crash :- ):

    Try spawning a Model Test side by side your model. Most of the time the error is easily caught by the test and it gives you a very good clue on what's going wrong

    Wow, that's amazing! Thanks so much!

    I've been testing my model for few days now, but I struggle with one error...

    WARNING: FAIL! Compared values are not the same:
       Actual (model->rowCount(parent)) 4
       Expected (c.oldSize + (end - start + 1)) 5
       (qabstractitemmodeltester.cpp:669)
    

    This happens during append function as far sa I can tell. I have 2 of them.

    1st : - for appending vector of items

            mGenericModel->beginInsertRows(index(), mChildren.size(), mChildren.size() + items.size() - 1);
            mChildren.append(items);
            mGenericModel->endInsertRows();
    

    2nd : - for appending 1 item.

            int loc = mChildren.size();
            mGenericModel->beginInsertRows(index(), loc, loc);
            mChildren.append(nodePtr);
            mGenericModel->endInsertRows();
    

    The model->rowCount(parent) runs this:

    {
        icGenericTreeItem *parentNode = getItemFromIndex(parent);
        if (!parentNode)return 0;
        return parentNode->getChildCount();
    }
    

    Does any of the code above look wrong?

    1 Reply Last reply
    0
    • D Offline
      D Offline
      Dariusz
      wrote on 25 Jan 2020, 10:59 last edited by Dariusz
      #10

      Another error that I'm getting reports off is :

      WARNING: QObject::connect: Cannot queue arguments of type 'QAbstractItemModel::LayoutChangeHint'
      (Make sure 'QAbstractItemModel::LayoutChangeHint' is registered using qRegisterMetaType().)
      

      No idea how to bite this one at all...

      68c84439-7b15-41c2-b35c-fca919d6c9e9-image.png

      I sweat I'm not sending some signals/info to my proxy models. But I have no idea which/where. The TestModesl does not report anything in this case.


      Here is my code for drag/drop action to handle indexes/layouts...

       Q_EMIT layoutAboutToBeChanged();
      
          QModelIndexList indexBefore;
          QModelIndexList indexAfter;
          std::reverse(newData.begin(), newData.end());
      
          /// Get old indexes
          for (int x = 0; x < newData.size(); ++x) {
              indexBefore.append(newData[x]->index());
          }
      
          /// Action below will emit beginRemoveRow for each item 1 by 1 and then beginInsertRows for each item 1 by 1. 1st remove all 
              rows then insert all rows.
          if (row == -1) {
              i->appendChildren(newData);
          } else {
              i->insertChildren(newData, row);
          }
          /// get new indexes
          for (int x = 0; x < newData.size(); ++x) {
              indexAfter.append(newData[x]->index());
          }
      
          changePersistentIndexList(indexBefore, indexAfter);
          Q_EMIT layoutChanged();
      

      I mean the question that I have now... when I'm adding 20 items from random selection order. Can I 1st remove them all 1 by 1 and then add them in all in 1 call?

      So assuming vector<treeItem*> items;
              for (auto &item:items) {
                  item->setParent(this); // this calls removeRows(item->parent.index(),item->row(),item->row()); and endRemoveRows(); + item->parent.mChildren().removeItem(item->row());
                  item->setModel(mGenericModel);
              }
      and then:
              mGenericModel->beginInsertRows(index(), mChildren.size(), mChildren.size() + items.size() - 1);
              mChildren.append(items);
              mGenericModel->endInsertRows();
      

      Or I cant call removeRows in this order and I have to removeRow then insert then remove then insert and so on ?
      TIA

      K 1 Reply Last reply 25 Jan 2020, 16:13
      0
      • D Dariusz
        25 Jan 2020, 10:59

        Another error that I'm getting reports off is :

        WARNING: QObject::connect: Cannot queue arguments of type 'QAbstractItemModel::LayoutChangeHint'
        (Make sure 'QAbstractItemModel::LayoutChangeHint' is registered using qRegisterMetaType().)
        

        No idea how to bite this one at all...

        68c84439-7b15-41c2-b35c-fca919d6c9e9-image.png

        I sweat I'm not sending some signals/info to my proxy models. But I have no idea which/where. The TestModesl does not report anything in this case.


        Here is my code for drag/drop action to handle indexes/layouts...

         Q_EMIT layoutAboutToBeChanged();
        
            QModelIndexList indexBefore;
            QModelIndexList indexAfter;
            std::reverse(newData.begin(), newData.end());
        
            /// Get old indexes
            for (int x = 0; x < newData.size(); ++x) {
                indexBefore.append(newData[x]->index());
            }
        
            /// Action below will emit beginRemoveRow for each item 1 by 1 and then beginInsertRows for each item 1 by 1. 1st remove all 
                rows then insert all rows.
            if (row == -1) {
                i->appendChildren(newData);
            } else {
                i->insertChildren(newData, row);
            }
            /// get new indexes
            for (int x = 0; x < newData.size(); ++x) {
                indexAfter.append(newData[x]->index());
            }
        
            changePersistentIndexList(indexBefore, indexAfter);
            Q_EMIT layoutChanged();
        

        I mean the question that I have now... when I'm adding 20 items from random selection order. Can I 1st remove them all 1 by 1 and then add them in all in 1 call?

        So assuming vector<treeItem*> items;
                for (auto &item:items) {
                    item->setParent(this); // this calls removeRows(item->parent.index(),item->row(),item->row()); and endRemoveRows(); + item->parent.mChildren().removeItem(item->row());
                    item->setModel(mGenericModel);
                }
        and then:
                mGenericModel->beginInsertRows(index(), mChildren.size(), mChildren.size() + items.size() - 1);
                mChildren.append(items);
                mGenericModel->endInsertRows();
        

        Or I cant call removeRows in this order and I have to removeRow then insert then remove then insert and so on ?
        TIA

        K Offline
        K Offline
        kshegunov
        Moderators
        wrote on 25 Jan 2020, 16:13 last edited by
        #11

        @Dariusz said in QSortFilterProxy & QIdentityProxyModel & QAbstractItemModel = Crash :- ):

        Another error that I'm getting reports off is :
        WARNING: QObject::connect: Cannot queue arguments of type 'QAbstractItemModel::LayoutChangeHint'
        (Make sure 'QAbstractItemModel::LayoutChangeHint' is registered using qRegisterMetaType().)

        Please tell me you are not using threads ...

        Read and abide by the Qt Code of Conduct

        D 1 Reply Last reply 25 Jan 2020, 16:39
        0
        • K kshegunov
          25 Jan 2020, 16:13

          @Dariusz said in QSortFilterProxy & QIdentityProxyModel & QAbstractItemModel = Crash :- ):

          Another error that I'm getting reports off is :
          WARNING: QObject::connect: Cannot queue arguments of type 'QAbstractItemModel::LayoutChangeHint'
          (Make sure 'QAbstractItemModel::LayoutChangeHint' is registered using qRegisterMetaType().)

          Please tell me you are not using threads ...

          D Offline
          D Offline
          Dariusz
          wrote on 25 Jan 2020, 16:39 last edited by
          #12

          @kshegunov I've checked code, mostly nope except for selectionModel()->select(items); on my treeView.
          Update() is called on QMetaInvole() via QueuedConnection.

          Could the selection model cause it ? :O

          J K C 3 Replies Last reply 25 Jan 2020, 16:49
          0
          • D Dariusz
            25 Jan 2020, 16:39

            @kshegunov I've checked code, mostly nope except for selectionModel()->select(items); on my treeView.
            Update() is called on QMetaInvole() via QueuedConnection.

            Could the selection model cause it ? :O

            J Offline
            J Offline
            JKSH
            Moderators
            wrote on 25 Jan 2020, 16:49 last edited by
            #13

            @Dariusz said in QSortFilterProxy & QIdentityProxyModel & QAbstractItemModel = Crash :- ):

            mostly nope except for...

            It needs to be 100% nope. Models and views are not thread-safe. They can crash if you run read/write their data from other threads.

            It is possible to create thread-safe models, but you need to explicitly write your model code in a way that is thread safe.

            Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

            1 Reply Last reply
            2
            • D Dariusz
              25 Jan 2020, 16:39

              @kshegunov I've checked code, mostly nope except for selectionModel()->select(items); on my treeView.
              Update() is called on QMetaInvole() via QueuedConnection.

              Could the selection model cause it ? :O

              K Offline
              K Offline
              kshegunov
              Moderators
              wrote on 25 Jan 2020, 16:53 last edited by
              #14

              What @JKSH said - no threading in the views & models.

              Read and abide by the Qt Code of Conduct

              1 Reply Last reply
              0
              • D Offline
                D Offline
                Dariusz
                wrote on 25 Jan 2020, 16:54 last edited by
                #15

                So all of the issues I'm getting above could be due to running selection function on thread? :O Gotta test it now ! Brb.

                K 1 Reply Last reply 25 Jan 2020, 16:56
                0
                • D Dariusz
                  25 Jan 2020, 16:54

                  So all of the issues I'm getting above could be due to running selection function on thread? :O Gotta test it now ! Brb.

                  K Offline
                  K Offline
                  kshegunov
                  Moderators
                  wrote on 25 Jan 2020, 16:56 last edited by kshegunov
                  #16

                  @Dariusz said in QSortFilterProxy & QIdentityProxyModel & QAbstractItemModel = Crash :- ):

                  So all of the issues I'm getting above could be due to running selection function on thread?

                  And this is surprising? I've had a program run over a year before it hit a race condition, and I'd like to think I know what I'm doing.

                  Read and abide by the Qt Code of Conduct

                  1 Reply Last reply
                  0
                  • D Dariusz
                    25 Jan 2020, 16:39

                    @kshegunov I've checked code, mostly nope except for selectionModel()->select(items); on my treeView.
                    Update() is called on QMetaInvole() via QueuedConnection.

                    Could the selection model cause it ? :O

                    C Online
                    C Online
                    Christian Ehrlicher
                    Lifetime Qt Champion
                    wrote on 25 Jan 2020, 17:54 last edited by
                    #17

                    @Dariusz said in QSortFilterProxy & QIdentityProxyModel & QAbstractItemModel = Crash :- ):

                    Could the selection model cause it

                    It does, not could...

                    Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                    Visit the Qt Academy at https://academy.qt.io/catalog

                    1 Reply Last reply
                    0
                    • D Offline
                      D Offline
                      Dariusz
                      wrote on 25 Jan 2020, 18:34 last edited by Dariusz
                      #18

                      Hey

                      Ok so I disabled my threaded selection function but sadly I'm still getting crashes after large drag, dragging few items does not cause issue, but items with children/etc seems to cause crash more often. Its very random :- ((

                      2d00a7ad-102d-43cc-9a7c-75bd9c09a60a-image.png
                      a0e731bb-6ea4-40f6-a1ba-4cd4568d3e7d-image.png
                      f2256f79-5661-4b89-848f-aa162904c9c9-image.png

                      1 Reply Last reply
                      0
                      • C Online
                        C Online
                        Christian Ehrlicher
                        Lifetime Qt Champion
                        wrote on 25 Jan 2020, 18:58 last edited by
                        #19

                        This still looks like a threading issue since _q_sourceRowsInserted() is the slot which is connected to the signal rowsInserted() from the source model. When both classes would be in the same thread then this function would have been called directly and not through an event like in your case here.

                        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                        Visit the Qt Academy at https://academy.qt.io/catalog

                        D 1 Reply Last reply 25 Jan 2020, 20:57
                        0
                        • C Christian Ehrlicher
                          25 Jan 2020, 18:58

                          This still looks like a threading issue since _q_sourceRowsInserted() is the slot which is connected to the signal rowsInserted() from the source model. When both classes would be in the same thread then this function would have been called directly and not through an event like in your case here.

                          D Offline
                          D Offline
                          Dariusz
                          wrote on 25 Jan 2020, 20:57 last edited by
                          #20

                          @Christian-Ehrlicher :O !

                          I have now
                          QAbstractItemModel = my model
                          QIdentityProxyModel = my custom identity - no changes here just place holder
                          QSortFilterProxyModel = this one is tweaked.

                          When I setModels on each of them, do I have to make any connections between them signals/slots of any of it?
                          I made one for selection/drag notifaction to re-select dropped items, but that is via QueuedConnection thus should not make any issue ?

                          I did more testing, seems like now any drag/drop is broken for me. Jezus... what a weekend.

                          1054252a-3739-42c0-8eed-5fb23625510d-image.png

                          I'm dropping QT from 5.14.0 to 5.13.1, perhaps its library bug as I'm running out of ideas whats wrong now :- (((

                          1 Reply Last reply
                          0
                          • C Online
                            C Online
                            Christian Ehrlicher
                            Lifetime Qt Champion
                            wrote on 25 Jan 2020, 21:06 last edited by
                            #21

                            Minimize your code until it does no longer occour so we can take a look at your model. Otherwise we can't help here anymore.

                            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                            Visit the Qt Academy at https://academy.qt.io/catalog

                            D 1 Reply Last reply 25 Jan 2020, 21:20
                            0
                            • C Christian Ehrlicher
                              25 Jan 2020, 21:06

                              Minimize your code until it does no longer occour so we can take a look at your model. Otherwise we can't help here anymore.

                              D Offline
                              D Offline
                              Dariusz
                              wrote on 25 Jan 2020, 21:20 last edited by
                              #22

                              @Christian-Ehrlicher I wish I could but the code base is over 120k+ lines of code and its not something I can "strip away n test" in standalone module. I'm stipping all I can but so far its just a nightmare.

                              As far as I can tell, the drag happens "ok" but I think I fail to properly notify the identity & then sort models...

                              In qt docs there is the layoutChanged() function I need to handle

                              emit layoutAboutToBeChanged
                              Remember the QModelIndex that will change
                              Update your internal data
                              Call changePersistentIndex()
                              emit layoutChanged
                              

                              which I implemented like this :

                                      Q_EMIT layoutAboutToBeChanged();
                              
                                      QModelIndexList indexBefore;
                                      QModelIndexList indexAfter;
                                      std::reverse(newData.begin(), newData.end());
                              
                                      /// Get old indexes
                                      for (int x = 0; x < newData.size(); ++x) {
                                          indexBefore.append(newData[x]->index());
                                      }
                              
                                      if (row == -1) {
                                          i->appendChildren(newData);
                                      } else {
                                          i->insertChildren(newData, row);
                                      }
                                      /// get new indexes
                                      for (int x = 0; x < newData.size(); ++x) {
                                          indexAfter.append(newData[x]->index());
                                      }
                              
                                      mim->setIcTreeNodes(newData);
                                      mim->setDragSucess();
                              
                                      changePersistentIndexList(indexBefore, indexAfter);
                                      Q_EMIT layoutChanged();
                              

                              But I have no idea if that is correct since I have never seen example like this before :- (

                              Any hints?

                              1 Reply Last reply
                              0
                              • D Offline
                                D Offline
                                Dariusz
                                wrote on 25 Jan 2020, 21:48 last edited by Dariusz
                                #23

                                Another error I'm getting that I can't understand is this one >

                                ######
                                			FATAL: ASSERT: "last < rowCount(parent)" in file itemmodels\qabstractitemmodel.cpp, line 2785
                                 (itemmodels\qabstractitemmodel.cpp:2785, (null))
                                ######
                                
                                
                                ######
                                			FATAL: ASSERT: "!this->isEmpty()" in file c:\users\qt\work\qt\qtbase\include\qtcore\../../src/corelib/tools/qstack.h, line 62
                                 (c:\users\qt\work\qt\qtbase\include\qtcore\../../src/corelib/tools/qstack.h:62, (null))
                                ######
                                

                                I went over entire drag/drop operation line by line checking indexes/ removeRow/insertRow routine and everything appear to be "valid" and yet I get this at the end ;[
                                This happens when I move last item from group in to another group, say item is index row 8
                                the function would be
                                mGenericModel->beginRemoveRows(index(), 8, 8); ? or its 8 and 8+1 ?
                                Else that assert is incorrect in library > Q_ASSERT(last < rowCount(parent));
                                Since if I'm moving last item, then last will be == rowCount(parent) which is still valid, and yet this will cause error :/ Or am I just talking total nonsense now...

                                Ok went line by line, error happens latter. Size of children is 9, last item index is 8, everything clears up properly. The crash happens latter in Qt ;[

                                It looks like its the damn persistentIndexes/proxy models not getting notified properly.

                                1 Reply Last reply
                                0
                                • D Offline
                                  D Offline
                                  Dariusz
                                  wrote on 27 Jan 2020, 09:41 last edited by
                                  #24

                                  After getting full debug out of modelTest class I noticed an inconsistent output of row changes...
                                  Did some digging and the issue ended up being...

                                  AbstractModel & Identity lived in threadB
                                  ProxySort lived in threadA.

                                  And connection between them ended up being queuedconnection via qt auto connection system. Which meant that... the sort was getting notification incorrectly...

                                  So lesson to learn.. "watch ur threads and what objects gets made where...".

                                  Problem solved, for now :- )

                                  TIA!

                                  J 1 Reply Last reply 27 Jan 2020, 10:38
                                  0
                                  • D Dariusz
                                    27 Jan 2020, 09:41

                                    After getting full debug out of modelTest class I noticed an inconsistent output of row changes...
                                    Did some digging and the issue ended up being...

                                    AbstractModel & Identity lived in threadB
                                    ProxySort lived in threadA.

                                    And connection between them ended up being queuedconnection via qt auto connection system. Which meant that... the sort was getting notification incorrectly...

                                    So lesson to learn.. "watch ur threads and what objects gets made where...".

                                    Problem solved, for now :- )

                                    TIA!

                                    J Offline
                                    J Offline
                                    JKSH
                                    Moderators
                                    wrote on 27 Jan 2020, 10:38 last edited by
                                    #25

                                    Glad to hear that you're not encountering any more crashes. There's 1 last thing you should make sure of:

                                    @Dariusz said in QSortFilterProxy & QIdentityProxyModel & QAbstractItemModel = Crash :- ):

                                    AbstractModel & Identity lived in threadB
                                    ProxySort lived in threadA.

                                    • All 3 models must live in the GUI thread.
                                    • All views must live in the GUI thread.

                                    The GUI thread is the thread that creates QApplication.

                                    Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                                    D 1 Reply Last reply 27 Jan 2020, 11:55
                                    2
                                    • J JKSH
                                      27 Jan 2020, 10:38

                                      Glad to hear that you're not encountering any more crashes. There's 1 last thing you should make sure of:

                                      @Dariusz said in QSortFilterProxy & QIdentityProxyModel & QAbstractItemModel = Crash :- ):

                                      AbstractModel & Identity lived in threadB
                                      ProxySort lived in threadA.

                                      • All 3 models must live in the GUI thread.
                                      • All views must live in the GUI thread.

                                      The GUI thread is the thread that creates QApplication.

                                      D Offline
                                      D Offline
                                      Dariusz
                                      wrote on 27 Jan 2020, 11:55 last edited by Dariusz
                                      #26

                                      @JKSH Yep I'm having a full run through the app now to ensure everything happens in GUI thread - that is widget/affects widget.

                                      1 Reply Last reply
                                      1

                                      18/26

                                      25 Jan 2020, 18:34

                                      • Login

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