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. QML and C++ model not shown
Forum Updated to NodeBB v4.3 + New Features

QML and C++ model not shown

Scheduled Pinned Locked Moved Solved QML and Qt Quick
8 Posts 4 Posters 548 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.
  • M Offline
    M Offline
    Mick_1
    wrote on last edited by
    #1

    Hello,

    I'm trying to learn how to create a C++ model with QAbstractListModel to display it in a QML view but I have nothing displayed despite my attempts.

    I followed the video on this Qt site: C++ Model

    The only part where I don't follow the explanations is the modification of main to add my model class, because I preferred to use a BackEnd class to modify my model according to an XML file (later).

    So I've got a "CustomData" class with a custom item list managed from a QAbstractListModel class whose header looks like this:

    #include <QAbstractListModel>
    
    Q_MOC_INCLUDE("CustomData.h")
    
    class CustomData;
    
    class DataModel : public QAbstractListModel
    {
        Q_OBJECT
    
    public:
        explicit DataModel(QObject *parent = nullptr);
        ~DataModel();
    
    
        Q_PROPERTY(CustomData *dataList READ dataList WRITE setDataList NOTIFY dataListChanged)
    
        enum
        {
            NameRole  = Qt::UserRole,
            ValueRole = Qt::UserRole+1,
            TypeRole  = Qt::UserRole+2
        };
    
        // Basic functionality:
        int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    
        QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    
        // Editable:
        bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
    
        Qt::ItemFlags flags(const QModelIndex &index) const override;
    
        virtual QHash<int, QByteArray> roleNames() const override;
    
        CustomData *dataList() const;
        void setDataList(CustomData *dataList);
    
    
    signals:
        void dataListChanged();
    
    
    private:
        QHash<int, QByteArray> m_roleNames;
        CustomData *m_dataList;
    
    };
    

    Here is the header of my BackEnd class:

    /* BackEnd Class */
    class BackEnd : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(CustomData *dataList READ dataList WRITE setDataList NOTIFY dataListChanged)
    
        QML_ELEMENT
    
    
    public:
        /* Constructor */
        explicit BackEnd(QObject *parent = nullptr);
        /* Destructor */
        ~BackEnd();
    
    
        /* Public Methods */
        CustomData *dataList() const;
        void setDataList(CustomData *newDataList);
    
    
    signals:
        void dataListChanged();
    
    
    private:
        /* Private Methods */
    
    
        /* Private Attributes */
        CustomData     *m_dataList;
    
    };
    

    That's all I do in my BackEnd:

    BackEnd::BackEnd(QObject *parent)
        : QObject{parent}
    {
        m_dataList = new CustomData();
        m_dataList->appendItem();
        m_dataList->appendItem();
    }
    
    CustomData *BackEnd::dataList() const
    {
        return m_dataList;
    }
    
    void BackEnd::setDataList(CustomData *newDataModel)
    {
        m_dataList = newDataModel;
        emit dataListChanged();
    }
    

    My main:

    qmlRegisterType<BackEnd>("BackEnd", 1, 0, "BackEnd");
    
    qmlRegisterType<DataModel>("DataModel", 1, 0, "DataModel");
    

    And finally, my QML view :

    ListView {
            id: listView
            ...
    
            model: DataModel {
                 id: datamodel
                 dataList: backend.dataList
    
            }
    

    I know that maybe I'm not showing enough code, but since there are 3 classes, I thought that the problem would already be in what I'm showing.

    I think it's more how I call my model in BackEnd and my QML view because the rest is like in the video or the explanations in the Qt 6 QML book.

    Thank you if you can give me your point of view.

    GrecKoG 1 Reply Last reply
    0
    • M Mick_1

      @GrecKo Yes, I tried to replace my model with a ListModel and ListElement and I can see my delegates and data.

      But with my custom model, it return 0 as count for now :/

      Would you like more code ? I can publish my whole code here (or somewhere else more convenient ?)

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #4

      @Mick_1 said in QML and C++ model not shown:

      But with my custom model, it return 0 as count for now :/

      So show your implementation of overridden rowCount()!?

      1 Reply Last reply
      1
      • M Mick_1

        Hello,

        I'm trying to learn how to create a C++ model with QAbstractListModel to display it in a QML view but I have nothing displayed despite my attempts.

        I followed the video on this Qt site: C++ Model

        The only part where I don't follow the explanations is the modification of main to add my model class, because I preferred to use a BackEnd class to modify my model according to an XML file (later).

        So I've got a "CustomData" class with a custom item list managed from a QAbstractListModel class whose header looks like this:

        #include <QAbstractListModel>
        
        Q_MOC_INCLUDE("CustomData.h")
        
        class CustomData;
        
        class DataModel : public QAbstractListModel
        {
            Q_OBJECT
        
        public:
            explicit DataModel(QObject *parent = nullptr);
            ~DataModel();
        
        
            Q_PROPERTY(CustomData *dataList READ dataList WRITE setDataList NOTIFY dataListChanged)
        
            enum
            {
                NameRole  = Qt::UserRole,
                ValueRole = Qt::UserRole+1,
                TypeRole  = Qt::UserRole+2
            };
        
            // Basic functionality:
            int rowCount(const QModelIndex &parent = QModelIndex()) const override;
        
            QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
        
            // Editable:
            bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
        
            Qt::ItemFlags flags(const QModelIndex &index) const override;
        
            virtual QHash<int, QByteArray> roleNames() const override;
        
            CustomData *dataList() const;
            void setDataList(CustomData *dataList);
        
        
        signals:
            void dataListChanged();
        
        
        private:
            QHash<int, QByteArray> m_roleNames;
            CustomData *m_dataList;
        
        };
        

        Here is the header of my BackEnd class:

        /* BackEnd Class */
        class BackEnd : public QObject
        {
            Q_OBJECT
            Q_PROPERTY(CustomData *dataList READ dataList WRITE setDataList NOTIFY dataListChanged)
        
            QML_ELEMENT
        
        
        public:
            /* Constructor */
            explicit BackEnd(QObject *parent = nullptr);
            /* Destructor */
            ~BackEnd();
        
        
            /* Public Methods */
            CustomData *dataList() const;
            void setDataList(CustomData *newDataList);
        
        
        signals:
            void dataListChanged();
        
        
        private:
            /* Private Methods */
        
        
            /* Private Attributes */
            CustomData     *m_dataList;
        
        };
        

        That's all I do in my BackEnd:

        BackEnd::BackEnd(QObject *parent)
            : QObject{parent}
        {
            m_dataList = new CustomData();
            m_dataList->appendItem();
            m_dataList->appendItem();
        }
        
        CustomData *BackEnd::dataList() const
        {
            return m_dataList;
        }
        
        void BackEnd::setDataList(CustomData *newDataModel)
        {
            m_dataList = newDataModel;
            emit dataListChanged();
        }
        

        My main:

        qmlRegisterType<BackEnd>("BackEnd", 1, 0, "BackEnd");
        
        qmlRegisterType<DataModel>("DataModel", 1, 0, "DataModel");
        

        And finally, my QML view :

        ListView {
                id: listView
                ...
        
                model: DataModel {
                     id: datamodel
                     dataList: backend.dataList
        
                }
        

        I know that maybe I'm not showing enough code, but since there are 3 classes, I thought that the problem would already be in what I'm showing.

        I think it's more how I call my model in BackEnd and my QML view because the rest is like in the video or the explanations in the Qt 6 QML book.

        Thank you if you can give me your point of view.

        GrecKoG Offline
        GrecKoG Offline
        GrecKo
        Qt Champions 2018
        wrote on last edited by
        #2

        @Mick_1 Did you give a size to your ListView? what does its count property returns?

        1 Reply Last reply
        1
        • M Offline
          M Offline
          Mick_1
          wrote on last edited by Mick_1
          #3

          @GrecKo Yes, I tried to replace my model with a ListModel and ListElement and I can see my delegates and data.

          But with my custom model, it return 0 as count for now :/

          Would you like more code ? I can publish my whole code here (or somewhere else more convenient ?)

          JonBJ 1 Reply Last reply
          0
          • M Mick_1

            @GrecKo Yes, I tried to replace my model with a ListModel and ListElement and I can see my delegates and data.

            But with my custom model, it return 0 as count for now :/

            Would you like more code ? I can publish my whole code here (or somewhere else more convenient ?)

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by
            #4

            @Mick_1 said in QML and C++ model not shown:

            But with my custom model, it return 0 as count for now :/

            So show your implementation of overridden rowCount()!?

            1 Reply Last reply
            1
            • M Offline
              M Offline
              Mick_1
              wrote on last edited by
              #5

              Oh damn, it was that...

              Example of a copy/paste tutorial without investigating the why...

              My rowCount looked like this:

              int DataModel::rowCount(const QModelIndex &parent) const
              {
                  if (!parent.isValid() || !m_dataList)
                      return 0;
              
                  return m_dataList->items().size();
              }
              

              This parameter and associated code is present by default, so I'm not sure what the point is and whether I should keep its implementation.

              Removing the parent test in the condition fixed my problem. Thanks a lot !!!

              JonBJ 1 Reply Last reply
              0
              • M Mick_1 has marked this topic as solved on
              • M Mick_1

                Oh damn, it was that...

                Example of a copy/paste tutorial without investigating the why...

                My rowCount looked like this:

                int DataModel::rowCount(const QModelIndex &parent) const
                {
                    if (!parent.isValid() || !m_dataList)
                        return 0;
                
                    return m_dataList->items().size();
                }
                

                This parameter and associated code is present by default, so I'm not sure what the point is and whether I should keep its implementation.

                Removing the parent test in the condition fixed my problem. Thanks a lot !!!

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by JonB
                #6

                @Mick_1
                This code's

                 if (!parent.isValid())
                        return 0;
                

                looks like it was taken from a tree model, not a flat list like you want/have? And hence is the wrong way round for you. When you have a tree model all nodes (other than the root) have a parent which is valid, and rowCount() must return the count of child items. For a flat model it is always passed an invalid parent, your !parent.isValid() will always be true and hence you will always return 0.

                For a flat model I would just have

                    Q_ASSERT(!parent.isValid());    // `parent` should never be passed in valid, else there is a logic error for a flat list
                    if (!m_dataList)
                        return 0;
                
                    return m_dataList->items().size();
                
                jeremy_kJ 1 Reply Last reply
                0
                • M Offline
                  M Offline
                  Mick_1
                  wrote on last edited by
                  #7

                  Ok, thank you @JonB for this explanation, I understood :)

                  Thanks @GrecKo and @JonB for your help ! I'm happy to finally play with C++ models ^^

                  1 Reply Last reply
                  0
                  • JonBJ JonB

                    @Mick_1
                    This code's

                     if (!parent.isValid())
                            return 0;
                    

                    looks like it was taken from a tree model, not a flat list like you want/have? And hence is the wrong way round for you. When you have a tree model all nodes (other than the root) have a parent which is valid, and rowCount() must return the count of child items. For a flat model it is always passed an invalid parent, your !parent.isValid() will always be true and hence you will always return 0.

                    For a flat model I would just have

                        Q_ASSERT(!parent.isValid());    // `parent` should never be passed in valid, else there is a logic error for a flat list
                        if (!m_dataList)
                            return 0;
                    
                        return m_dataList->items().size();
                    
                    jeremy_kJ Offline
                    jeremy_kJ Offline
                    jeremy_k
                    wrote on last edited by
                    #8

                    @JonB said in QML and C++ model not shown:

                    @Mick_1
                    This code's

                     if (!parent.isValid())
                            return 0;
                    

                    looks like it was taken from a tree model, not a flat list like you want/have?

                    This is also unworkable for a tree model, if the intention is to make the top level items of the tree viewable.

                    Asking a question about code? http://eel.is/iso-c++/testcase/

                    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