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. Delete of QObject in QList

Delete of QObject in QList

Scheduled Pinned Locked Moved Solved General and Desktop
4 Posts 3 Posters 387 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.
  • K Offline
    K Offline
    Krulle
    wrote on last edited by
    #1

    Hi guys,
    I'm a bit stuck at the moment and don't understand why my Qobject derived class is being deleted.

    Here's the problem:
    I am using a generic ListModel from here: https://github.com/sgbo/QGenericListModel
    This model is inherited from the "RecipeModel". It uses the "RecipeItem" as type. The RecipeItem only contains Q_PROPERTY for use in QML.

    class RecipeModel : public GenericListModel<RecipeItem>
    {
        Q_OBJECT
    
    public:
        explicit RecipeModel(QObject *parent = nullptr);
        ~RecipeModel() override;
    
        Q_INVOKABLE RecipeItem *at(int i);
        Q_INVOKABLE RecipeItem *at(const QString &name);
    
    signals:
    
    };
    
    #include "recipemodel.h"
    
    RecipeModel::RecipeModel(QObject *parent) : GenericListModel(parent)
    {
    
    }
    
    RecipeModel::~RecipeModel()
    {
        qDebug() << Q_FUNC_INFO;
    }
    
    RecipeItem *RecipeModel::at(int i)
    {
        qDebug() << m_itemList.at(i);
        if(m_itemList.isEmpty())
            return nullptr;
        return GenericListModel::at(i);
    }
    
    RecipeItem *RecipeModel::at(const QString &name)
    {
        return GenericListModel::at(name, "name");
    }
    

    The RecipeModel is initialised in the class "Core" and is kept over the runtime of the programm.

    #ifndef CORE_H
    #define CORE_H
    
    #include <QObject>
    #include <QtQml>
    
    #include "corebase.h"
    
    class RecipeItem;
    class IRecipeItemDao;
    class RecipeDaoDatabase;
    
    class Core : public CoreBase
    {
        Q_OBJECT
    
        RecipeItem * m_currentItem;
        QSharedPointer<IRecipeItemDao> m_recipeItemDao;
    
    public:
        explicit Core(QObject *parent = nullptr);
        ~Core() override;
    
        Q_INVOKABLE RecipeItem * currentItem() const;
        void setCurrentItem(RecipeItem *item);
        Q_INVOKABLE void setCurrentItem(int modelIndex);
    
        QSharedPointer<IRecipeItemDao> recipeItemDao() const;
    };
    
    #endif // CORE_H
    

    So, now the crux:
    If I get the "Item" from the model (with the function GenericListModel::at(int)), then the RecipeItem is deleted.
    The next time I fetch it with "GenericListModel::at", the device crashes.
    Can someone explain to me why?
    Access from QML e.g:

    import QtQuick 2.4
    import QtQuick.Window 2.3
    import QtQuick.VirtualKeyboard 2.4
    import Qt.labs.settings 1.1
    import QtQml 2.12
    
    import "../Content"
    
    import UserModule 1.0
    import Backend 1.0
    
    Item {
        id: appContainer
        width: Screen.width < Screen.height ? Screen.height : Screen.width
        height: Screen.width < Screen.height ? Screen.width : Screen.height
        rotation: Screen.width < Screen.height ? 90 : 0
    
        property int listId: listId
    
        ReceipeCreateNewFormular {
            id: receipeCreateNew
    
    //        RecipeModelController {
    //            id: recipeModelController
    //            core: CoreApp
    //        }
    
            Component.onCompleted: {
                var item = CoreApp.recipeModel.at(listId)                <<<---------------------
                console.log(CoreApp.recipeModel.at(listId))
    
    //            recipeName.inputText = item.name
    //            datetimeinput.inputText = item.date.toLocaleDateString(Qt.locale("de_DE"), Locale.ShortFormat)
    //            mashWater.inputText = item.mashWater
    //            spargeWater.inputText = item.spargeWater
    //            gravity.inputText = item.origGravity
    //            castWort.inputText = item.castWort
    //            beerSort.inputText = item.beerSort
    //            cookTime.inputText = item.cookTime
    //            author.inputText = item.author
    //            shortDescription.areatext = item.shortDescription
    
    //            listHop.model = listItem.hopModel
    //            listMash.model = listItem.mashModel
            }
    
            butTakeDataOver.onClicked: {
    //            console.log("butTakeDataOver " + receipeCreateNew.recipeName.inputText);
    //            recipeModelController.updateItem(listItem,
    //                                             receipeCreateNew.recipeName.inputText,
    //                                             Date(receipeCreateNew.datetimeinput.inputText),
    //                                             receipeCreateNew.beerSort.inputText,
    //                                             receipeCreateNew.author.inputText,
    //                                             receipeCreateNew.castWort.inputText,
    //                                             receipeCreateNew.gravity.inputText,
    //                                             receipeCreateNew.shortDescription.areatext,
    //                                             receipeCreateNew.mashWater.inputText,
    //                                             receipeCreateNew.spargeWater.inputText,
    //                                             receipeCreateNew.cookTime.inputText)
    //            mainStackView.pop()
            }
    
            butAddMashStep.icon.source: MainConstants.getIconFile("content", "ic_add_circle_outline")
            butAddHopStep.icon.source: MainConstants.getIconFile("content", "ic_add_circle_outline")
    
        }
    
        InputPanel {
            id: inputPanel
            y: appContainer.height
            z: 99
            anchors.left: parent.left
            anchors.right: parent.right
    
            states: State {
                name: "visible"
                when: inputPanel.active
                PropertyChanges {
                    target: inputPanel
                    y: appContainer.height - inputPanel.height
                }
                PropertyChanges {
                    target: receipeCreateNew
                    contentHeight: appContainer.height + inputPanel.height
                }
            }
    
            AutoScroller {}
        }
    
    }
    

    Thanks for your help :)

    J.HilkJ 1 Reply Last reply
    0
    • Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #2

      @Krulle said in Delete of QObject in QList:

      The next time I fetch it with "GenericListModel::at", the device crashes.

      Use a debugger, see where it crashes. It for sure crashes when the list is empty in RecipeModel::at(int i)

      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
      1
      • K Krulle

        Hi guys,
        I'm a bit stuck at the moment and don't understand why my Qobject derived class is being deleted.

        Here's the problem:
        I am using a generic ListModel from here: https://github.com/sgbo/QGenericListModel
        This model is inherited from the "RecipeModel". It uses the "RecipeItem" as type. The RecipeItem only contains Q_PROPERTY for use in QML.

        class RecipeModel : public GenericListModel<RecipeItem>
        {
            Q_OBJECT
        
        public:
            explicit RecipeModel(QObject *parent = nullptr);
            ~RecipeModel() override;
        
            Q_INVOKABLE RecipeItem *at(int i);
            Q_INVOKABLE RecipeItem *at(const QString &name);
        
        signals:
        
        };
        
        #include "recipemodel.h"
        
        RecipeModel::RecipeModel(QObject *parent) : GenericListModel(parent)
        {
        
        }
        
        RecipeModel::~RecipeModel()
        {
            qDebug() << Q_FUNC_INFO;
        }
        
        RecipeItem *RecipeModel::at(int i)
        {
            qDebug() << m_itemList.at(i);
            if(m_itemList.isEmpty())
                return nullptr;
            return GenericListModel::at(i);
        }
        
        RecipeItem *RecipeModel::at(const QString &name)
        {
            return GenericListModel::at(name, "name");
        }
        

        The RecipeModel is initialised in the class "Core" and is kept over the runtime of the programm.

        #ifndef CORE_H
        #define CORE_H
        
        #include <QObject>
        #include <QtQml>
        
        #include "corebase.h"
        
        class RecipeItem;
        class IRecipeItemDao;
        class RecipeDaoDatabase;
        
        class Core : public CoreBase
        {
            Q_OBJECT
        
            RecipeItem * m_currentItem;
            QSharedPointer<IRecipeItemDao> m_recipeItemDao;
        
        public:
            explicit Core(QObject *parent = nullptr);
            ~Core() override;
        
            Q_INVOKABLE RecipeItem * currentItem() const;
            void setCurrentItem(RecipeItem *item);
            Q_INVOKABLE void setCurrentItem(int modelIndex);
        
            QSharedPointer<IRecipeItemDao> recipeItemDao() const;
        };
        
        #endif // CORE_H
        

        So, now the crux:
        If I get the "Item" from the model (with the function GenericListModel::at(int)), then the RecipeItem is deleted.
        The next time I fetch it with "GenericListModel::at", the device crashes.
        Can someone explain to me why?
        Access from QML e.g:

        import QtQuick 2.4
        import QtQuick.Window 2.3
        import QtQuick.VirtualKeyboard 2.4
        import Qt.labs.settings 1.1
        import QtQml 2.12
        
        import "../Content"
        
        import UserModule 1.0
        import Backend 1.0
        
        Item {
            id: appContainer
            width: Screen.width < Screen.height ? Screen.height : Screen.width
            height: Screen.width < Screen.height ? Screen.width : Screen.height
            rotation: Screen.width < Screen.height ? 90 : 0
        
            property int listId: listId
        
            ReceipeCreateNewFormular {
                id: receipeCreateNew
        
        //        RecipeModelController {
        //            id: recipeModelController
        //            core: CoreApp
        //        }
        
                Component.onCompleted: {
                    var item = CoreApp.recipeModel.at(listId)                <<<---------------------
                    console.log(CoreApp.recipeModel.at(listId))
        
        //            recipeName.inputText = item.name
        //            datetimeinput.inputText = item.date.toLocaleDateString(Qt.locale("de_DE"), Locale.ShortFormat)
        //            mashWater.inputText = item.mashWater
        //            spargeWater.inputText = item.spargeWater
        //            gravity.inputText = item.origGravity
        //            castWort.inputText = item.castWort
        //            beerSort.inputText = item.beerSort
        //            cookTime.inputText = item.cookTime
        //            author.inputText = item.author
        //            shortDescription.areatext = item.shortDescription
        
        //            listHop.model = listItem.hopModel
        //            listMash.model = listItem.mashModel
                }
        
                butTakeDataOver.onClicked: {
        //            console.log("butTakeDataOver " + receipeCreateNew.recipeName.inputText);
        //            recipeModelController.updateItem(listItem,
        //                                             receipeCreateNew.recipeName.inputText,
        //                                             Date(receipeCreateNew.datetimeinput.inputText),
        //                                             receipeCreateNew.beerSort.inputText,
        //                                             receipeCreateNew.author.inputText,
        //                                             receipeCreateNew.castWort.inputText,
        //                                             receipeCreateNew.gravity.inputText,
        //                                             receipeCreateNew.shortDescription.areatext,
        //                                             receipeCreateNew.mashWater.inputText,
        //                                             receipeCreateNew.spargeWater.inputText,
        //                                             receipeCreateNew.cookTime.inputText)
        //            mainStackView.pop()
                }
        
                butAddMashStep.icon.source: MainConstants.getIconFile("content", "ic_add_circle_outline")
                butAddHopStep.icon.source: MainConstants.getIconFile("content", "ic_add_circle_outline")
        
            }
        
            InputPanel {
                id: inputPanel
                y: appContainer.height
                z: 99
                anchors.left: parent.left
                anchors.right: parent.right
        
                states: State {
                    name: "visible"
                    when: inputPanel.active
                    PropertyChanges {
                        target: inputPanel
                        y: appContainer.height - inputPanel.height
                    }
                    PropertyChanges {
                        target: receipeCreateNew
                        contentHeight: appContainer.height + inputPanel.height
                    }
                }
        
                AutoScroller {}
            }
        
        }
        

        Thanks for your help :)

        J.HilkJ Offline
        J.HilkJ Offline
        J.Hilk
        Moderators
        wrote on last edited by
        #3

        @Krulle I see a Q_INVOKABLE for the at() function. This is for QML right?

        I bet that your RecipeModel or your RecipeItem's have no valid QObject parent. Thus the QMLengine takes ownership of those items and the GC mercilessly deletes them when your QML part doesn't use them any more.

        Couple of options you have

        • give them proper c++ parents
        • use https://doc.qt.io/qt-5/qqmlengine.html#setObjectOwnership to explicitly set the ownership to c++
        • make your non modifying getter functions, const functions <- this one is good practice anyway but I'm unsure if it will prevent the ownership steal, depends on the implementation I guess.

        Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


        Q: What's that?
        A: It's blue light.
        Q: What does it do?
        A: It turns blue.

        K 1 Reply Last reply
        3
        • J.HilkJ J.Hilk

          @Krulle I see a Q_INVOKABLE for the at() function. This is for QML right?

          I bet that your RecipeModel or your RecipeItem's have no valid QObject parent. Thus the QMLengine takes ownership of those items and the GC mercilessly deletes them when your QML part doesn't use them any more.

          Couple of options you have

          • give them proper c++ parents
          • use https://doc.qt.io/qt-5/qqmlengine.html#setObjectOwnership to explicitly set the ownership to c++
          • make your non modifying getter functions, const functions <- this one is good practice anyway but I'm unsure if it will prevent the ownership steal, depends on the implementation I guess.
          K Offline
          K Offline
          Krulle
          wrote on last edited by
          #4

          @J-Hilk said in Delete of QObject in QList:

          @Krulle I see a Q_INVOKABLE for the at() function. This is for QML right?

          I bet that your RecipeModel or your RecipeItem's have no valid QObject parent. Thus the QMLengine takes ownership of those items and the GC mercilessly deletes them when your QML part doesn't use them any more.

          Couple of options you have

          • give them proper c++ parents
          • use https://doc.qt.io/qt-5/qqmlengine.html#setObjectOwnership to explicitly set the ownership to c++
          • make your non modifying getter functions, const functions <- this one is good practice anyway but I'm unsure if it will prevent the ownership steal, depends on the implementation I guess.

          Thank you very much. You are right.
          The parent object was a nullptr. After I passed a valid parent object to the RecipeItem, it was no longer deleted.

          1 Reply Last reply
          1

          • Login

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