Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How does MQL TreeView release its resource?



  • Hi:

    I setup a subclass of QAbstractItemModel according to this link:
    https://doc.qt.io/qt-5/qtwidgets-itemviews-simpletreemodel-example.html

    In my model class, I return a QVariant object from QAbstractItemModel's data() function. The value of the QVariant object is a pointer of an CTreeTypeString object and it has Q_PROPERTY. I create it by calling newTreeTypeString().

    // return the QVariant data
    QVariant CTreeModelDevice::newTreeTypeString(const QString &text)
    {
        CTreeTypeString *t = new CTreeTypeString(this);
        t->setText(text);
        QVariant v;
        v.setValue(t);
        return v;
    }
    
    // the class of treeview item
    class CTreeTypeString : public QObject
    {
        Q_OBJECT
    
        Q_PROPERTY(QString text READ getText WRITE setText NOTIFY textChanged)
    
        QString getText();
        void setText(QString text);
    
    signals:
        void textChanged();
    }
    
    qml:
        TreeView {
            model: CTreeModelDevice
            TableViewColumn {
                delegate: Text {
                               text: " " + styleData.value.text
                            }
            }
       }
    

    Upon a certain event, I refresh the treeview by:

    beginResetModel();
    setupModelData();
    endResetModel();
    

    setupModelData() calls newTreeTypeString() again to create new CTreeTypeString objects.

    All these work fine.

    Now it comes to the question: when and how CTreeTypeString objects are deleted?

    I notice that they are not deleted when I call beginResetModel() and endResetModel(). Instead, they are deleted when the main window is closed. Does this mean that QML framework holds the objects even they are not shown in the tree and only delete them when the treeview is destroyed.
    I also tried beginRemoveRows/endRemoveRows then beginInsertRows/endInsertRows. Same observation.

    Is this by design?
    Is there an "official" way in which I can explicitly delete the "unuseful" objects. I get QML errors if I delete them in setupModelData().

    Thanks
    Kevin


  • Moderators

    @kevinguo said in How does MQL TreeView release its resource?:

    Now it comes to the question: when and how CTreeTypeString objects are deleted?
    I notice that they are not deleted when I call beginResetModel() and endResetModel(). Instead, they are deleted when the main window is closed. Does this mean that QML framework holds the objects even they are not shown in the tree and only delete them when the treeview is destroyed.
    I also tried beginRemoveRows/endRemoveRows then beginInsertRows/endInsertRows. Same observation.
    Is this by design?

    Yes. This is unrelated to QML. It does not hold on to your data there.

    CTreeTypeString *t = new CTreeTypeString(this);

    This C++ code is your culprit. You create a QObject and parent it to this (your model). So in order to delete it, you need to either:

    • delete the model
    • or delete the CTreeTypeString object(s) manually

    Is there an "official" way in which I can explicitly delete the "unuseful" objects. I get QML errors if I delete them in setupModelData().

    I think you should delete them after you finish your model reset. Best - call deleteLater() and Qt will handle it when event loop is ready.

    "official" way

    Just return a string... there is no need to use QObject here at all ;-)



  • @sierdzio

    Thanks for your response.

    It works if I manually delete the data after beginResetModel()/endResetModel() block.

    However, if I only refresh a certain branch by calling beginRemoveRows()/endRemoveRows() and beginInsertRows()/endInsertRows(), then delete the data after endInsertRows(), it causes this warning/error:
    xxx.qml:43 TypeError: Value is null and could not be converted to an object

    line 43 is in the delegate and like this:
    text: "" + styleData.value.itemText

    deleteLater() doesn't work for me too because I call this in event loop so the object will be deleted immediately in the same event.

    I have a workaround: store the data and delete it at the next refresh event.

    Thanks
    Kevin


  • Moderators

    @kevinguo said in How does MQL TreeView release its resource?:

    I have a workaround: store the data and delete it at the next refresh event.

    Or you can use a QSharedPointer so it will happen automatically.

    Another possibility - use Q_GADGET and store your objects on stack, not as pointers.



  • @sierdzio said in How does MQL TreeView release its resource?:

    I have a workaround: store the data and delete it at the next refresh event.

    In order to have more control, my final choice is to delete it manually instead of using auto pointer.
    But anyways, thanks for your suggestion.
    Kevin