Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. HorizontalHeaderView & VerticalHeaderView does not disconnect from QQmlTableModel::headerDataChanged in Loader
Forum Updated to NodeBB v4.3 + New Features

HorizontalHeaderView & VerticalHeaderView does not disconnect from QQmlTableModel::headerDataChanged in Loader

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
3 Posts 1 Posters 379 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.
  • V Offline
    V Offline
    Volodymyr Mudryk
    wrote on last edited by
    #1

    Hi

    I have table view loaded dynamically. If it is without HorizontalHeaderView and VerticalHeaderView it works fine.
    But if I use them in my real application it crash after same time. (but can not reproduce the crash in test app)
    Investigation shows that connections from HorizontalHeaderView and VerticalHeaderView still are in model after the unload table view.
    If you press many times the button "Reload" in test app you will see in output the model gets more and more connections.

    Any ideas how to fix it?

    Qt 6.4.0

    main.qml

    import QtQuick
    import QtQuick.Controls
    import Qt.labs.qmlmodels
    
    import Helper
    
    Window {
        id: window
        width: 640
        height: 480
        visible: true
        title: qsTr("Hello World")
    
        Helper {
            id: helper
        }
    
        Button {
            id: btnReload
            text: "Reload"
            anchors.left: loader.right
            onClicked: {
                loader.active = false
                loader.active = true
                helper.dumpObjectInfo(tableModel)
            }
        }
    
        TableModel {
            id: tableModel
            TableModelColumn {
                display: "name"
            }
            TableModelColumn {
                display: "color"
            }
    
            rows: [{
                    "name": "cat",
                    "color": "black"
                }, {
                    "name": "dog",
                    "color": "brown"
                }, {
                    "name": "bird",
                    "color": "white"
                }]
        }
    
        Loader {
            id: loader
            width: 100
            height: 300
            sourceComponent: comp
            active: true
        }
    
        Component {
            id: comp
            Item {
                anchors.fill: paren
    
                HorizontalHeaderView {
                    id: horizontalHeader
                    implicitHeight: 20
                    syncView: tableView
                    anchors.left: tableView.left
    
                    delegate: Rectangle {
                        implicitHeight: 20
                        implicitWidth: 50
                        border.width: 1
    
                        Text {
                            text: "name"
                            anchors.fill: parent
                            horizontalAlignment: Text.AlignHCenter
                            verticalAlignment: Text.AlignVCenter
                            textFormat: Text.PlainText
                        }
                    }
                }
    
                TableView {
                    id: tableView
                    anchors.left: parent.left
                    anchors.right: parent.right
                    anchors.top: horizontalHeader.bottom
                    anchors.bottom: parent.bottom
    
                    columnSpacing: 1
                    rowSpacing: 1
                    clip: true
    
                    model: tableModel
    
                    delegate: Rectangle {
                        implicitWidth: 100
                        implicitHeight: 50
                        border.width: 1
    
                        Text {
                            text: display
                            anchors.centerIn: parent
                        }
                    }
                }
            }
        }
    }
    

    manu.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    
    #include "Helper.h"
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
        const QUrl url(u"qrc:/untitled2/main.qml"_qs);
        QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                         &app, [url](QObject *obj, const QUrl &objUrl) {
            if (!obj && url == objUrl)
                QCoreApplication::exit(-1);
        }, Qt::QueuedConnection);
    
        qmlRegisterType<Helper>("Helper", 1, 0, "Helper");
    
        engine.load(url);
    
        return app.exec();
    }
    

    Helper.h

    #ifndef HELPER_H
    #define HELPER_H
    
    #include <QObject>
    
    class Helper: public QObject
    {
        Q_OBJECT
    public:
        Helper();
    
        Q_INVOKABLE void dumpObjectInfo(QObject* obj);
    };
    
    #endif // HELPER_H
    

    Helper.cpp

    #include "Helper.h"
    
    Helper::Helper()
    {
    
    }
    
    void Helper::dumpObjectInfo(QObject *obj)
    {
        obj->dumpObjectInfo();
    }
    
    
    V 1 Reply Last reply
    0
    • V Volodymyr Mudryk

      Hi

      I have table view loaded dynamically. If it is without HorizontalHeaderView and VerticalHeaderView it works fine.
      But if I use them in my real application it crash after same time. (but can not reproduce the crash in test app)
      Investigation shows that connections from HorizontalHeaderView and VerticalHeaderView still are in model after the unload table view.
      If you press many times the button "Reload" in test app you will see in output the model gets more and more connections.

      Any ideas how to fix it?

      Qt 6.4.0

      main.qml

      import QtQuick
      import QtQuick.Controls
      import Qt.labs.qmlmodels
      
      import Helper
      
      Window {
          id: window
          width: 640
          height: 480
          visible: true
          title: qsTr("Hello World")
      
          Helper {
              id: helper
          }
      
          Button {
              id: btnReload
              text: "Reload"
              anchors.left: loader.right
              onClicked: {
                  loader.active = false
                  loader.active = true
                  helper.dumpObjectInfo(tableModel)
              }
          }
      
          TableModel {
              id: tableModel
              TableModelColumn {
                  display: "name"
              }
              TableModelColumn {
                  display: "color"
              }
      
              rows: [{
                      "name": "cat",
                      "color": "black"
                  }, {
                      "name": "dog",
                      "color": "brown"
                  }, {
                      "name": "bird",
                      "color": "white"
                  }]
          }
      
          Loader {
              id: loader
              width: 100
              height: 300
              sourceComponent: comp
              active: true
          }
      
          Component {
              id: comp
              Item {
                  anchors.fill: paren
      
                  HorizontalHeaderView {
                      id: horizontalHeader
                      implicitHeight: 20
                      syncView: tableView
                      anchors.left: tableView.left
      
                      delegate: Rectangle {
                          implicitHeight: 20
                          implicitWidth: 50
                          border.width: 1
      
                          Text {
                              text: "name"
                              anchors.fill: parent
                              horizontalAlignment: Text.AlignHCenter
                              verticalAlignment: Text.AlignVCenter
                              textFormat: Text.PlainText
                          }
                      }
                  }
      
                  TableView {
                      id: tableView
                      anchors.left: parent.left
                      anchors.right: parent.right
                      anchors.top: horizontalHeader.bottom
                      anchors.bottom: parent.bottom
      
                      columnSpacing: 1
                      rowSpacing: 1
                      clip: true
      
                      model: tableModel
      
                      delegate: Rectangle {
                          implicitWidth: 100
                          implicitHeight: 50
                          border.width: 1
      
                          Text {
                              text: display
                              anchors.centerIn: parent
                          }
                      }
                  }
              }
          }
      }
      

      manu.cpp

      #include <QGuiApplication>
      #include <QQmlApplicationEngine>
      
      #include "Helper.h"
      
      int main(int argc, char *argv[])
      {
          QGuiApplication app(argc, argv);
      
          QQmlApplicationEngine engine;
          const QUrl url(u"qrc:/untitled2/main.qml"_qs);
          QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                           &app, [url](QObject *obj, const QUrl &objUrl) {
              if (!obj && url == objUrl)
                  QCoreApplication::exit(-1);
          }, Qt::QueuedConnection);
      
          qmlRegisterType<Helper>("Helper", 1, 0, "Helper");
      
          engine.load(url);
      
          return app.exec();
      }
      

      Helper.h

      #ifndef HELPER_H
      #define HELPER_H
      
      #include <QObject>
      
      class Helper: public QObject
      {
          Q_OBJECT
      public:
          Helper();
      
          Q_INVOKABLE void dumpObjectInfo(QObject* obj);
      };
      
      #endif // HELPER_H
      

      Helper.cpp

      #include "Helper.h"
      
      Helper::Helper()
      {
      
      }
      
      void Helper::dumpObjectInfo(QObject *obj)
      {
          obj->dumpObjectInfo();
      }
      
      
      V Offline
      V Offline
      Volodymyr Mudryk
      wrote on last edited by Volodymyr Mudryk
      #2

      @Volodymyr-Mudryk

      I think the root cause is in qquickheaderview.cpp
      Connect to &QAbstractItemModel::headerDataChanged as lambda but disconnect only from class instance.

      How to notify Qt developers about it?

      void QHeaderDataProxyModel::connectToModel()
      {
          if (m_model.isNull())
              return;
          connect(m_model, &QAbstractItemModel::headerDataChanged,
              [this](Qt::Orientation orient, int first, int last) {
                  if (orient != orientation())
                      return;
                  if (orient == Qt::Horizontal) {
                      emit dataChanged(createIndex(0, first), createIndex(0, last));
                  } else {
                      emit dataChanged(createIndex(first, 0), createIndex(last, 0));
                  }
              });
      ...
      
      void QHeaderDataProxyModel::disconnectFromModel()
      {
          if (m_model.isNull())
              return;
          m_model->disconnect(this);
      }
      
      1 Reply Last reply
      0
      • V Offline
        V Offline
        Volodymyr Mudryk
        wrote on last edited by
        #3

        I've created bug about it: https://bugreports.qt.io/browse/QTBUG-108610

        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