Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-91649

"Writing to "entity" broke the binding to the underlying model" warning when removing item from model

    XMLWordPrintable

Details

    • ec79af7396 (qt/qtdeclarative/dev) ec79af7396 (qt/tqtc-qtdeclarative/dev)

    Description

      I have a model named InventoryModel. One of its roles is a QObject-derived class named ComponentEntity. I use this role as a required property in the delegate:

          ListView {
              id: listView
              anchors.fill: parent
              model: InventoryModel {}
              delegate: ItemDelegate {
                  width: listView.width
                  text: itemName
      
                  required property int index
                  required property string itemName
                  required property ComponentEntity entity
      
                  Component.onDestruction: print("destroying delegate for " + itemName)
              }
          }
      

      When removing an item from the model, I get a warning:

      removing 1 of "Item 9" from index 9 (entire stack)
      ending remove of 1 of "Item 9" (entire stack)
      Destroying ComponentEntity(0x55ff3b74c7e0, name = "Item 9")
      qrc:/main.qml: Writing to "entity" broke the binding to the underlying model
      qml: destroying delegate for Item 9
      

      Stack trace leading up to the error:

      1  PropertyUpdater::breakBinding                                                                                qqmldelegatemodel.cpp          953  0x7fffe928667a 
      2  PropertyUpdater::qt_static_metacall                                                                          moc_qqmldelegatemodel_p_p.cpp  513  0x7fffe92b81ea 
      3  PropertyUpdater::qt_metacall                                                                                 moc_qqmldelegatemodel_p_p.cpp  550  0x7fffe92b82f0 
      4  QMetaObject::metacall                                                                                        qmetaobject.cpp                317  0x7ffff6a909e1 
      5  doActivate<false>                                                                                            qobject.cpp                    3912 0x7ffff6adde80 
      6  QMetaObject::activate                                                                                        qobject.cpp                    3959 0x7ffff6ad6e23 
      7  QQmlVMEMetaObject::activate                                                                                  qqmlvmemetaobject.cpp          1312 0x7ffff724127e 
      8  QQmlVMEVariantQObjectPtr::objectDestroyed                                                                    qqmlvmemetaobject.cpp          190  0x7ffff7242c8d 
      9  QQmlData::destroyed                                                                                          qqmlengine.cpp                 1951 0x7ffff724b5cd 
      10 QQmlData::destroyed                                                                                          qqmlengine.cpp                 747  0x7ffff72486a9 
      11 QObject::~QObject                                                                                            qobject.cpp                    1001 0x7ffff6acf1fd 
      12 ComponentEntity::~ComponentEntity                                                                            main.cpp                       15   0x55555555a40b 
      13 ComponentEntity::~ComponentEntity                                                                            main.cpp                       17   0x55555555a43e 
      14 QtSharedPointer::CustomDeleter<ComponentEntity, QtSharedPointer::NormalDeleter>::execute                     qsharedpointer_impl.h          187  0x55555555e01d 
      15 QtSharedPointer::ExternalRefCountWithCustomDeleter<ComponentEntity, QtSharedPointer::NormalDeleter>::deleter qsharedpointer_impl.h          205  0x55555555d59e 
      16 QtSharedPointer::ExternalRefCountData::destroy                                                               qsharedpointer_impl.h          149  0x55555555a029 
      17 QSharedPointer<ComponentEntity>::deref                                                                       qsharedpointer_impl.h          458  0x55555555d6ce 
      18 QSharedPointer<ComponentEntity>::deref                                                                       qsharedpointer_impl.h          453  0x55555555c1ea 
      19 QSharedPointer<ComponentEntity>::~QSharedPointer                                                             qsharedpointer_impl.h          310  0x55555555b1a4 
      20 InventoryModel::removeLast                                                                                   main.cpp                       56   0x55555555a8ec 
      21 InventoryModel::qt_static_metacall                                                                           main.moc                       141  0x555555559138 
      22 InventoryModel::qt_metacall                                                                                  main.moc                       178  0x55555555923e 
      23 QMetaObject::metacall                                                                                        qmetaobject.cpp                317  0x7ffff6a909e1 
      24 QQmlObjectOrGadget::metacall                                                                                 qqmlobjectorgadget.cpp         51   0x7ffff72bc6fc 
      25 CallMethod                                                                                                   qv4qobjectwrapper.cpp          1319 0x7ffff70f9d6b 
      26 CallPrecise                                                                                                  qv4qobjectwrapper.cpp          1573 0x7ffff70fa854 
      27 QV4::QObjectMethod::callInternal                                                                             qv4qobjectwrapper.cpp          2131 0x7ffff70fd2ba 
      28 QV4::QObjectMethod::virtualCall                                                                              qv4qobjectwrapper.cpp          2068 0x7ffff70fcd2c 
      29 QV4::FunctionObject::call                                                                                    qv4functionobject_p.h          202  0x7ffff702f97f 
      30 QV4::Moth::VME::interpret                                                                                    qv4vme_moth.cpp                757  0x7ffff712c601 
      31 QV4::Moth::VME::exec                                                                                         qv4vme_moth.cpp                466  0x7ffff712825f 
      32 QV4::Function::call                                                                                          qv4function.cpp                69   0x7ffff7098dd6 
      33 QQmlJavaScriptExpression::evaluate                                                                           qqmljavascriptexpression.cpp   212  0x7ffff72e1356 
      34 QQmlBoundSignalExpression::evaluate                                                                          qqmlboundsignal.cpp            224  0x7ffff72779b3 
      35 QQmlBoundSignal_callback                                                                                     qqmlboundsignal.cpp            361  0x7ffff7278037 
      36 QQmlNotifier::emitNotify                                                                                     qqmlnotifier.cpp               104  0x7ffff72bbb4e 
      37 QQmlData::signalEmitted                                                                                      qqmlengine.cpp                 834  0x7ffff7248b79 
      38 doActivate<false>                                                                                            qobject.cpp                    3778 0x7ffff6add83c 
      39 QMetaObject::activate                                                                                        qobject.cpp                    3946 0x7ffff6ad6dad 
      40 QQuickAbstractButton::clicked                                                                                moc_qquickabstractbutton_p.cpp 630  0x7fffe881bd5d 
      41 QQuickAbstractButtonPrivate::trigger                                                                         qquickabstractbutton.cpp       342  0x7fffe8754bce 
      42 QQuickAbstractButtonPrivate::handleRelease                                                                   qquickabstractbutton.cpp       182  0x7fffe875425c 
      43 QQuickControl::mouseReleaseEvent                                                                             qquickcontrol.cpp              2151 0x7fffe8787e90 
      44 QQuickItem::event                                                                                            qquickitem.cpp                 8208 0x7fffe96168ad 
      45 QQuickAbstractButton::event                                                                                  qquickabstractbutton.cpp       1035 0x7fffe8756c29 
      46 QCoreApplicationPrivate::notify_helper                                                                       qcoreapplication.cpp           1225 0x7ffff6a865d6 
      47 doNotify                                                                                                     qcoreapplication.cpp           1154 0x7ffff6a861a3 
      48 QCoreApplication::notify                                                                                     qcoreapplication.cpp           1140 0x7ffff6a86102 
      49 QGuiApplication::notify                                                                                      qguiapplication.cpp            1935 0x7ffff778d5bd 
      50 QCoreApplication::notifyInternal2                                                                            qcoreapplication.cpp           1064 0x7ffff6a86017 
      51 QCoreApplication::sendEvent                                                                                  qcoreapplication.cpp           1462 0x7ffff6a86ab4 
      52 QQuickWindowPrivate::deliverMouseEvent                                                                       qquickwindow.cpp               2020 0x7fffe964026b 
      53 QQuickWindowPrivate::deliverPointerEvent                                                                     qquickwindow.cpp               2612 0x7fffe964387f 
      54 QQuickWindowPrivate::handleMouseEvent                                                                        qquickwindow.cpp               2427 0x7fffe9642ef9 
      55 QQuickWindow::mouseReleaseEvent                                                                              qquickwindow.cpp               2407 0x7fffe9642bf3 
      56 QWindow::event                                                                                               qwindow.cpp                    2341 0x7ffff77a46c2 
      57 QQuickWindow::event                                                                                          qquickwindow.cpp               1902 0x7fffe963f848 
      58 QCoreApplicationPrivate::notify_helper                                                                       qcoreapplication.cpp           1225 0x7ffff6a865d6 
      59 doNotify                                                                                                     qcoreapplication.cpp           1154 0x7ffff6a861a3 
      60 QCoreApplication::notify                                                                                     qcoreapplication.cpp           1140 0x7ffff6a86102 
      61 QGuiApplication::notify                                                                                      qguiapplication.cpp            1935 0x7ffff778d5bd 
      62 QCoreApplication::notifyInternal2                                                                            qcoreapplication.cpp           1064 0x7ffff6a86017 
      63 QCoreApplication::sendSpontaneousEvent                                                                       qcoreapplication.cpp           1474 0x7ffff6a86af2 
      64 QGuiApplicationPrivate::processMouseEvent                                                                    qguiapplication.cpp            2282 0x7ffff778e81f 
      65 QGuiApplicationPrivate::processWindowSystemEvent                                                             qguiapplication.cpp            2002 0x7ffff778d9bc 
      66 QWindowSystemInterface::sendWindowSystemEvents                                                               qwindowsysteminterface.cpp     1169 0x7ffff776a2b7 
      67 xcbSourceDispatch                                                                                            qxcbeventdispatcher.cpp        105  0x7ffff2df94a8 
      68 g_main_context_dispatch                                                                                                                          0x7ffff56abf9d 
      69 ??                                                                                                                                               0x7ffff56ac220 
      70 g_main_context_iteration                                                                                                                         0x7ffff56ac2c3 
      71 QEventDispatcherGlib::processEvents                                                                          qeventdispatcher_glib.cpp      423  0x7ffff6b24d19 
      72 QXcbGlibEventDispatcher::processEvents                                                                       qxcbeventdispatcher.cpp        143  0x7ffff2df96ee 
      73 QEventLoop::processEvents                                                                                    qeventloop.cpp                 139  0x7ffff6a824b5 
      74 QEventLoop::exec                                                                                             qeventloop.cpp                 232  0x7ffff6a8281b 
      75 QCoreApplication::exec                                                                                       qcoreapplication.cpp           1375 0x7ffff6a868e6 
      76 QGuiApplication::exec                                                                                        qguiapplication.cpp            1867 0x7ffff778d3ce 
      77 main                                                                                                         main.cpp                       140  0x555555558f3e                                                                                                                                              
      

      Then, when exiting:

      qml: destroying delegate for Item 8
      qml: destroying delegate for Item 7
      qml: destroying delegate for Item 6
      qml: destroying delegate for Item 5
      qml: destroying delegate for Item 4
      qml: destroying delegate for Item 3
      qml: destroying delegate for Item 2
      qml: destroying delegate for Item 1
      qml: destroying delegate for Item 0
      Destroying ComponentEntity(0x55ff3b7f39d0, name = "Item 0")
      qrc:/main.qml: Writing to "entity" broke the binding to the underlying model
      Destroying ComponentEntity(0x55ff3b8e5360, name = "Item 1")
      qrc:/main.qml: Writing to "entity" broke the binding to the underlying model
      Destroying ComponentEntity(0x55ff3b875b20, name = "Item 2")
      qrc:/main.qml: Writing to "entity" broke the binding to the underlying model
      Destroying ComponentEntity(0x55ff3b875d50, name = "Item 3")
      qrc:/main.qml: Writing to "entity" broke the binding to the underlying model
      Destroying ComponentEntity(0x55ff3b875f00, name = "Item 4")
      qrc:/main.qml: Writing to "entity" broke the binding to the underlying model
      Destroying ComponentEntity(0x55ff3b770cf0, name = "Item 5")
      qrc:/main.qml: Writing to "entity" broke the binding to the underlying model
      Destroying ComponentEntity(0x55ff3b770ea0, name = "Item 6")
      qrc:/main.qml: Writing to "entity" broke the binding to the underlying model
      Destroying ComponentEntity(0x55ff3b771050, name = "Item 7")
      qrc:/main.qml: Writing to "entity" broke the binding to the underlying model
      Destroying ComponentEntity(0x55ff3b771200, name = "Item 8")
      qrc:/main.qml: Writing to "entity" broke the binding to the underlying model
      

      I can see that this happens because the ComponentEntity object is destroyed before the delegate. However, as the model is informed of the removal in advance, I don't believe I should be getting this warning. The view should take care of destruction of the delegate and freeze the bindings. However, I know that others disagree with me about this. If the solution is to again say that this is up to the user to deal with, then it should be clearly documented that objects used as required properties must outlive the delegate, with an example demonstrating how to do this.

      In my case, when the item is removed from InventoryModel, it should be deleted (assuming there are no other references to it, hence why I use QSharedPointer), which is why I don't think it should be necessary to work around Qt here. A hacky workaround for the attached example (note that a 0 ms timer is not sufficient):

          Q_INVOKABLE void removeLast() {
              const int count = rowCount();
              if (count == 0)
                  return;
      
              auto sharedEntityPtr = mContents.at(count - 1);
              const QString objectName = sharedEntityPtr->objectName();
              onPreItemRemoved(objectName, 1, true, count - 1);
              mContents.takeLast();
              QTimer::singleShot(100, [=]() mutable {
                  qDebug() << ">>>";
                  sharedEntityPtr.reset();
                  qDebug() << "<<<";
              });
              onPostItemRemoved(objectName, 1, true, count - 1);
          }
      

      Attachments

        1. qtbug91649.zip
          3 kB
          Mitch Curtis

        Issue Links

          For Gerrit Dashboard: QTBUG-91649
          # Subject Branch Project Status CR V

          Activity

            People

              ulherman Ulf Hermann
              mitch_curtis Mitch Curtis
              Votes:
              2 Vote for this issue
              Watchers:
              8 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes