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. get single item and it's property of QAbstractListModel in QML

get single item and it's property of QAbstractListModel in QML

Scheduled Pinned Locked Moved Unsolved General and Desktop
23 Posts 5 Posters 16.3k 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.
  • S Slash200

    Hello,

    I have a c++ class derived from QAbstractListModel which I use as my Datamodel for QML.
    It has hundrets of objects in it which I want to access directly in QML.
    Using the whole model e.g. in a list ist working.

    ListView {
            width: 100; height: 800
     
            model: dataSourceModelObject
            delegate: Text { text: name + "   " + value}
            }
    
    Component {
            id: mydelegate
            Text { text: model.name + model.value }
            }
    

    But I want to access a property of a single object in this model.
    How can this be done?

    regards

    raven-worxR Offline
    raven-worxR Offline
    raven-worx
    Moderators
    wrote on last edited by raven-worx
    #3

    @Slash200
    you can write a custom method such as:

    Q_INVOKABLE QVariantMap MyModel::get(int index) const
    {
        QVariantMap data;
        const QModelIndex idx = this->index(i,0);
        if( !index.isValid() )
            return data;
        const QHash<int,QByteArray> rn = this->roleNames();
        QHashIterator<int,QByteArray> it(rn);
        while (it.hasNext())
            data[it.value()] = index.data(it.key());
        return data;
    }
    

    This method returns a JS object containing all the data for the given row, using the role names you would also use in the delegate to access the data.

    Usage in QML:

    dataSourceModelObject.get(row).name
    

    --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
    If you have a question please use the forum so others can benefit from the solution in the future

    S 1 Reply Last reply
    2
    • raven-worxR raven-worx

      @Slash200
      you can write a custom method such as:

      Q_INVOKABLE QVariantMap MyModel::get(int index) const
      {
          QVariantMap data;
          const QModelIndex idx = this->index(i,0);
          if( !index.isValid() )
              return data;
          const QHash<int,QByteArray> rn = this->roleNames();
          QHashIterator<int,QByteArray> it(rn);
          while (it.hasNext())
              data[it.value()] = index.data(it.key());
          return data;
      }
      

      This method returns a JS object containing all the data for the given row, using the role names you would also use in the delegate to access the data.

      Usage in QML:

      dataSourceModelObject.get(row).name
      
      S Offline
      S Offline
      Slash200
      wrote on last edited by Slash200
      #4

      @raven-worx Thank you for you reply! This is what I'm looking for, but I have a problem with implementing this function.
      I tried this:

      QVariantMap datasourcemodel::get(int row) const
      {
          QHash<int, QByteArray> names = roleNames();
          QHashIterator<int, QByteArray> i(names);
          QVariantMap res;
          QModelIndex idx = index(row, 0);
          while(i.hasNext()) {
              i.next();
              QVariant data = idx.data(i.key());
              res[i.value()] = data;
      
          }
          qDebug() << res;
      return res;
      }
      

      Then I tried to show a value in QML but it shows only the values on start. Its not updating

      Text {
             id: text2
             x: 600
             y: 137
             width: 100
             height: 31
      
             text: dataSourceModelObject.get(cbx_sources.currentIndex).value
             font.pixelSize: 12
         }
      
      1 Reply Last reply
      1
      • dheerendraD Offline
        dheerendraD Offline
        dheerendra
        Qt Champions 2022
        wrote on last edited by
        #5

        When you send the QVariantMap, you are sending the key, value pairs. You are not sending the original object which changes. If you want to handle the changes in QML, expose the entire object itself e.g

        TestObject* MyModel::get(int index) {
        // get the object using index
        // return the object
        }

        Please note that TestObject need to know to QML using qmlRegisterMetaType<>()..

        Dheerendra
        @Community Service
        Certified Qt Specialist
        http://www.pthinks.com

        S 1 Reply Last reply
        0
        • dheerendraD dheerendra

          When you send the QVariantMap, you are sending the key, value pairs. You are not sending the original object which changes. If you want to handle the changes in QML, expose the entire object itself e.g

          TestObject* MyModel::get(int index) {
          // get the object using index
          // return the object
          }

          Please note that TestObject need to know to QML using qmlRegisterMetaType<>()..

          S Offline
          S Offline
          Slash200
          wrote on last edited by
          #6

          @dheerendra
          Thank you so much dheerendra.
          I'm still have to learn so much about programming.
          Can you be so nice and show me how I can return the object itself from the get function in the model?

          regards
          Bastian

          1 Reply Last reply
          0
          • dheerendraD Offline
            dheerendraD Offline
            dheerendra
            Qt Champions 2022
            wrote on last edited by
            #7

            Did u write a get method the way I described ? Can u tell me what type object your model contains ?

            Dheerendra
            @Community Service
            Certified Qt Specialist
            http://www.pthinks.com

            S 1 Reply Last reply
            0
            • dheerendraD dheerendra

              Did u write a get method the way I described ? Can u tell me what type object your model contains ?

              S Offline
              S Offline
              Slash200
              wrote on last edited by
              #8

              @dheerendra I tried to implent the get function, but i dont understand how to return a reference of the object.
              This is the object inside the model:

              Header:

              #ifndef DATASOURCEOBJECT_H
              #define DATASOURCEOBJECT_H
              
              #include <QObject>
              
              
              
              class DataSourceObject
              {
              
              
              public:
              
                  //Constructors and destructors
                  DataSourceObject(const int &id, const QString &name, const QString &displayname, const double &value);
              
              
              
                  int id() const;
              
                  void setid(const int &id);
              
                  QString name() const;
              
                  void setname(const QString &name);
              
                  QString displayname() const;
              
                  void setdisplayname(const QString &displayname);
              
                  double value() const;
              
                  void setvalue(const double &value);
              
              
              private:
              
                  int m_id;
                  QString m_name;
                  QString m_displayname;
                  double m_value;
              
              };
              
              
              
              
              #endif // DATASOURCEOBJECT_H
              

              cpp:

              #include "datasourceobject.h"
              
              
              DataSourceObject::DataSourceObject(const int &id, const QString &name, const QString &displayname, const double &value)
                  : m_id(id), m_name(name), m_displayname(displayname), m_value(value)
              {
              
              }
              
              
              int DataSourceObject::id() const
              {
                  return m_id;
              }
              
              void DataSourceObject::setid(const int &id)
              {
                  if (id != m_id) {
                      m_id = id;
                      //emit idChanged();
                  }
              }
              
              
              QString DataSourceObject::name() const
              {
                  return m_name;
              }
              
              void DataSourceObject::setname(const QString &name)
              {
                  if (name != m_name) {
                      m_name = name;
                      //emit nameChanged();
                  }
              }
              
              
              QString DataSourceObject::displayname() const
              {
                  return m_displayname;
              }
              
              void DataSourceObject::setdisplayname(const QString &displayname)
              {
                  if (displayname != m_displayname) {
                      m_displayname = displayname;
                      //emit displaynameChanged();
                  }
              }
              
              
              double DataSourceObject::value() const
              {
                  return m_value;
              }
              
              void DataSourceObject::setvalue(const double &value)
              {
                  //if(value != m_value) {
                      m_value = value;
                      //emit valueChanged();
                      //}
              }
              
              1 Reply Last reply
              0
              • dheerendraD Offline
                dheerendraD Offline
                dheerendra
                Qt Champions 2022
                wrote on last edited by
                #9

                How are storing the data objects in model ? Is it list or some other containers ? Also ur data object shud inherit from qobject

                Dheerendra
                @Community Service
                Certified Qt Specialist
                http://www.pthinks.com

                S 1 Reply Last reply
                0
                • dheerendraD dheerendra

                  How are storing the data objects in model ? Is it list or some other containers ? Also ur data object shud inherit from qobject

                  S Offline
                  S Offline
                  Slash200
                  wrote on last edited by
                  #10

                  @dheerendra I read a JSON file an then i store the data in the model:

                  void Connect::initDataSources(){
                  
                  
                      QString jsonFileValue; //value of jasonfile, extracted as QString
                  
                      //Some file opening logics here, including existence and reading test
                      QFile datasourcesjson(QStringLiteral("datasources.json"));
                  
                      //open document in read mode
                      datasourcesjson.open((QIODevice::ReadOnly));
                  
                  
                      //read whole data from json file in a Qstring
                      if(!datasourcesjson.isReadable()){
                          qWarning("datasources.json not readable.\n\n\n");
                          return;
                      }
                      else
                      {
                          jsonFileValue = datasourcesjson.readAll();
                          datasourcesjson.close();
                  
                          QJsonDocument m_DataSourceDocument = QJsonDocument::fromJson(jsonFileValue.toUtf8());
                  
                          QJsonObject m_DataSourceObject = m_DataSourceDocument.object();
                  
                          m_DataSourceArray = m_DataSourceObject.value(QString("datasources")).toArray();
                  
                          //create for each Datasource a Instance of DataSourceObject
                  
                          for (const auto obj : m_DataSourceArray){
                  
                              m_DataSourceModel.addDataSourceObject(DataSourceObject(obj.toObject().value("id").toInt(),
                                                                                     obj.toObject().value("name").toString(),
                                                                                     obj.toObject().value("displayname").toString(),
                                                                                     0));
                  
                          }
                  
                          return;
                  
                      }
                  
                  }
                  
                  1 Reply Last reply
                  0
                  • dheerendraD Offline
                    dheerendraD Offline
                    dheerendra
                    Qt Champions 2022
                    wrote on last edited by
                    #11

                    DataSourceObject shud inherit from qobject. Also when you call adddatasource how object is stored inside the model ? Are u using qlist?

                    Dheerendra
                    @Community Service
                    Certified Qt Specialist
                    http://www.pthinks.com

                    S 1 Reply Last reply
                    0
                    • dheerendraD dheerendra

                      DataSourceObject shud inherit from qobject. Also when you call adddatasource how object is stored inside the model ? Are u using qlist?

                      S Offline
                      S Offline
                      Slash200
                      wrote on last edited by
                      #12

                      @dheerendra i tried to get it to work with Qobject but it didnt worked. Also the Example from Qt (called abstractidemmodel bundelt with qt creator) didnt inhert from qobject.

                      void datasourcemodel::addDataSourceObject(const DataSourceObject &DataSourceObject){
                          beginInsertRows(QModelIndex(), rowCount(), rowCount());
                          m_DataSourceObjects << DataSourceObject;
                          endInsertRows();
                      }
                      
                      1 Reply Last reply
                      0
                      • S Slash200

                        Hello,

                        I have a c++ class derived from QAbstractListModel which I use as my Datamodel for QML.
                        It has hundrets of objects in it which I want to access directly in QML.
                        Using the whole model e.g. in a list ist working.

                        ListView {
                                width: 100; height: 800
                         
                                model: dataSourceModelObject
                                delegate: Text { text: name + "   " + value}
                                }
                        
                        Component {
                                id: mydelegate
                                Text { text: model.name + model.value }
                                }
                        

                        But I want to access a property of a single object in this model.
                        How can this be done?

                        regards

                        VRoninV Offline
                        VRoninV Offline
                        VRonin
                        wrote on last edited by
                        #13

                        You don't need special methods to get stuff, see https://wiki.qt.io/How_to_Use_a_Custom_Class_in_C%2B%2B_Model_and_QML_View

                        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                        ~Napoleon Bonaparte

                        On a crusade to banish setIndexWidget() from the holy land of Qt

                        1 Reply Last reply
                        1
                        • dheerendraD Offline
                          dheerendraD Offline
                          dheerendra
                          Qt Champions 2022
                          wrote on last edited by
                          #14

                          m_DataSourceObjects

                          What is the datatype of above variable ? Can you show me the declaration ?

                          Dheerendra
                          @Community Service
                          Certified Qt Specialist
                          http://www.pthinks.com

                          1 Reply Last reply
                          0
                          • S Offline
                            S Offline
                            Slash200
                            wrote on last edited by
                            #15

                            shouldn't be single items accessible with the data() function.

                            using the model in a listview works perfectly. But wenn access the value from a item directly in QML with this:

                            Text {
                                    id: text2
                                    x: 600
                                    y: 137
                                    width: 100
                                    height: 31
                            
                                    text: dataSourceModel.data(88,259)
                                    font.pixelSize: 12
                                }
                            

                            Where 88 is the desired index and 259 the valueRole

                            qml returns: Unable to assign [undefined] to QString

                            this is my data function in my derived qabstractlistmodel class:

                            QVariant datasourcemodel::data(const QModelIndex & index, int role) const{
                                if(index.row() < 0 || index.row() >= m_DataSourceObjects.count())
                                    return  QVariant();
                            
                                const DataSourceObject &dataSourceObject = m_DataSourceObjects[index.row()];
                                if (role == idRole)
                                    return dataSourceObject.id();
                                else if (role == nameRole)
                                    return dataSourceObject.name();
                                else if (role == displaynameRole)
                                    return dataSourceObject.displayname();
                                else if (role == valueRole)
                                    return dataSourceObject.value();
                                //else if (role == allRole)
                                //    return get(index.row());
                                return QVariant();
                            }
                            
                            VRoninV 1 Reply Last reply
                            0
                            • S Slash200

                              shouldn't be single items accessible with the data() function.

                              using the model in a listview works perfectly. But wenn access the value from a item directly in QML with this:

                              Text {
                                      id: text2
                                      x: 600
                                      y: 137
                                      width: 100
                                      height: 31
                              
                                      text: dataSourceModel.data(88,259)
                                      font.pixelSize: 12
                                  }
                              

                              Where 88 is the desired index and 259 the valueRole

                              qml returns: Unable to assign [undefined] to QString

                              this is my data function in my derived qabstractlistmodel class:

                              QVariant datasourcemodel::data(const QModelIndex & index, int role) const{
                                  if(index.row() < 0 || index.row() >= m_DataSourceObjects.count())
                                      return  QVariant();
                              
                                  const DataSourceObject &dataSourceObject = m_DataSourceObjects[index.row()];
                                  if (role == idRole)
                                      return dataSourceObject.id();
                                  else if (role == nameRole)
                                      return dataSourceObject.name();
                                  else if (role == displaynameRole)
                                      return dataSourceObject.displayname();
                                  else if (role == valueRole)
                                      return dataSourceObject.value();
                                  //else if (role == allRole)
                                  //    return get(index.row());
                                  return QVariant();
                              }
                              
                              VRoninV Offline
                              VRoninV Offline
                              VRonin
                              wrote on last edited by
                              #16

                              @Slash200 said in get single item and it's property of QAbstractListModel in QML:

                              shouldn't be single items accessible with the data() function

                              Not in the delegate, please read the wiki I posted.

                              "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                              ~Napoleon Bonaparte

                              On a crusade to banish setIndexWidget() from the holy land of Qt

                              1 Reply Last reply
                              0
                              • dheerendraD Offline
                                dheerendraD Offline
                                dheerendra
                                Qt Champions 2022
                                wrote on last edited by
                                #17
                                1. You have model

                                2. This model contains the list of DataSource Object.

                                3. You got the values using QVariantList

                                4. Now you asked the question saying that value does not change when value is changed in the backend.

                                5. If you are working with View & Model, any change in model will reflect in view provided your model has appropriate signal.

                                6. What you wanted is access single value in model data & display it. Display is not ListView etc.

                                7. Whenever you change the value in Backend, it should change in UI also.

                                e.g

                                Text { 
                                     text : dataModel.dataSourceObj.value
                                }
                                

                                This is how you wanted access it. If any change in the value should also change. data() method will be called through view. What data() method returns is only a value. Whenever any value changes, how it will reflect in your text UI ? So data(..) method will not of use.

                                You are trying to use model like object which gives the value.
                                So I suggested you to have method like following.

                                Assuming that you store the object in the QList

                                TestObject* MyModel::get(int index) {
                                DataSourceObj *obj = list.at(index)
                                return obj
                                }
                                

                                I kept on asking show me how you store the DataSourceObj in model. Apart from this answer I get something else. Hence I was not able to give you get function details. Now I assumed you are storing as QList<> I have shown you the method signature.
                                I have requested you to inherit from QObject also. The reason is that property binding has to work with signal/slots. There is a way to do without QObject and use Q_GADGET. However this does not work for signal/slots.

                                Hope things are clarified. Again I'm asking show me how do you store DataSource objects in Model. Which datastructure are you using to store DataSource Objects ?. If your problem is not the way I explained, then you are looking for something else & I did not understand your problem.

                                Dheerendra
                                @Community Service
                                Certified Qt Specialist
                                http://www.pthinks.com

                                S 1 Reply Last reply
                                0
                                • dheerendraD dheerendra
                                  1. You have model

                                  2. This model contains the list of DataSource Object.

                                  3. You got the values using QVariantList

                                  4. Now you asked the question saying that value does not change when value is changed in the backend.

                                  5. If you are working with View & Model, any change in model will reflect in view provided your model has appropriate signal.

                                  6. What you wanted is access single value in model data & display it. Display is not ListView etc.

                                  7. Whenever you change the value in Backend, it should change in UI also.

                                  e.g

                                  Text { 
                                       text : dataModel.dataSourceObj.value
                                  }
                                  

                                  This is how you wanted access it. If any change in the value should also change. data() method will be called through view. What data() method returns is only a value. Whenever any value changes, how it will reflect in your text UI ? So data(..) method will not of use.

                                  You are trying to use model like object which gives the value.
                                  So I suggested you to have method like following.

                                  Assuming that you store the object in the QList

                                  TestObject* MyModel::get(int index) {
                                  DataSourceObj *obj = list.at(index)
                                  return obj
                                  }
                                  

                                  I kept on asking show me how you store the DataSourceObj in model. Apart from this answer I get something else. Hence I was not able to give you get function details. Now I assumed you are storing as QList<> I have shown you the method signature.
                                  I have requested you to inherit from QObject also. The reason is that property binding has to work with signal/slots. There is a way to do without QObject and use Q_GADGET. However this does not work for signal/slots.

                                  Hope things are clarified. Again I'm asking show me how do you store DataSource objects in Model. Which datastructure are you using to store DataSource Objects ?. If your problem is not the way I explained, then you are looking for something else & I did not understand your problem.

                                  S Offline
                                  S Offline
                                  Slash200
                                  wrote on last edited by
                                  #18

                                  @dheerendra

                                  Apologies for the communication problems.
                                  To simplify the whole thing I uploaded the project to github.

                                  Repo click me

                                  There you see also the main.qml where i try the get the value of a object depending on the selected item with the combobox

                                  1 Reply Last reply
                                  0
                                  • VRoninV Offline
                                    VRoninV Offline
                                    VRonin
                                    wrote on last edited by
                                    #19

                                    is your problem here?

                                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                                    ~Napoleon Bonaparte

                                    On a crusade to banish setIndexWidget() from the holy land of Qt

                                    S 1 Reply Last reply
                                    0
                                    • VRoninV VRonin

                                      is your problem here?

                                      S Offline
                                      S Offline
                                      Slash200
                                      wrote on last edited by
                                      #20

                                      @VRonin

                                      no in the main.qml

                                      Text {
                                          id: text2
                                          x: 600
                                          y: 137
                                          width: 100
                                          height: 31
                                      
                                          //text: dataSourceModel.get(cbx_sources.currentIndex).value
                                      
                                          text: dataSourceModel.data(cbx_sources.currentIndex,259)
                                      
                                          font.pixelSize: 12
                                      }
                                      

                                      i want to give the text2 the value of the selected item from combobox cbx_sources.

                                      1 Reply Last reply
                                      0
                                      • dheerendraD Offline
                                        dheerendraD Offline
                                        dheerendra
                                        Qt Champions 2022
                                        wrote on last edited by
                                        #21

                                        @Slash200 I have shared simple example at GIT

                                        Please look at the example carefully. Hope this helps.

                                        Dheerendra
                                        @Community Service
                                        Certified Qt Specialist
                                        http://www.pthinks.com

                                        S 1 Reply Last reply
                                        0
                                        • dheerendraD dheerendra

                                          @Slash200 I have shared simple example at GIT

                                          Please look at the example carefully. Hope this helps.

                                          S Offline
                                          S Offline
                                          Slash200
                                          wrote on last edited by Slash200
                                          #22

                                          @dheerendra Thank you so much.
                                          I adapted it to your suggestion.
                                          Now I can access single data in the GUI.
                                          Its working, but after hundrets of updates of the value of a object, it's returning NULL for no reason and the programm crashes.
                                          when qmlRegisterType<DataSourceObject>(); is commented out, it's no more crashing
                                          qrc:/main.qml:71: TypeError: Cannot read property 'value' of null

                                          i debugged the object when it changes it value in printed its type and adress to the console:

                                          It changes it's type?
                                          Debug output:

                                          My adress is:  DataSourceObject(0x201635b0)
                                          My adress is:  DataSourceObject(0x201635b0)
                                          My adress is:  DataSourceObject(0x201635b0)
                                          My adress is:  DataSourceObject(0x201635b0)
                                          My adress is:  DataSourceObject(0x201635b0)
                                          My adress is:  DataSourceObject(0x201635b0)
                                          My adress is:  QObject(0x201635b0)
                                          My adress is:  QObject(0x201635b0)
                                          My adress is:  QObject(0x201635b0)
                                          My adress is:  QObject(0x201635b0)
                                          My adress is:  QObject(0x201635b0)
                                          

                                          The version is in the repo https://github.com/BastianGschrey/topic-97612

                                          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