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. Understanding QAbstractListModel in python/QML program and C++ equivalent
Forum Updated to NodeBB v4.3 + New Features

Understanding QAbstractListModel in python/QML program and C++ equivalent

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

    Hi everyone !

    I have to change a QML human machine interface from python to C++. But I'm new to python AND qml so I'm struggling as the things are getting tough.

    I'll ask my questions before showing the code :

    there's a python class derived from QQAbstractListModel that looks like containing some QtQuick Items. (code below) It's PresetModel. First, I kind of understand the setPresetBase method but... that way to put everything in a table like it's nothing... how can I convert it into C++ ? I guess parameters is a QList ? So I could store my items as QVariant in a QList ? If so, then what ?

    How can I share such a thing with QML ? I see that they just put it in setContextProperty. I tried to do a simple one and do the same, but I couldn't get the data(index) from my QAbstractListModel, or call a method called apply...

    i see that they defined apply as a pyqt slot. What is the equivalent in C++ ? I tried to define it as a public slot : but it changed nothing...
    I'm lost.
    Could you explain me how to create and use a QAbstractListModel such as this on but in C++ ?

    Thanks in advance. Here is the code (not everything, just what I think being useful)

    class PresetModel( QtCore.QAbstractListModel ):
        NameRole = QtCore.Qt.UserRole + 1
    
        _roles = {
            NameRole: b"name",
            }
    
        def __init__( self, view, parent=None ):
            super().__init__( parent )
            self._preset_list = []
            self._preset_base = None
            self.view = view
            self._name_id = 0
    
        def rowCount( self, parent=QtCore.QModelIndex() ):
            return len( self._preset_list )
    
        def data( self, index, role=QtCore.Qt.DisplayRole ):
            try:
                preset_item = self._preset_list[index.row()]
            except IndexError:
                return QVariant()
            if role == self.NameRole:
                return preset_item.name
            return QVariant()
    
        def roleNames( self ):
            return self._roles
    
        def setPresetBase( self ):
            object = self.view.rootObject()
            items = object.childItems()
            parameters = []
            for i in items:
                if type(i) == QtQuick.QQuickItem and i.objectName() != "" and i.objectName() != "EditPanel" and i.objectName() != "EditGrid":
                    parameters.append( [ i.objectName(), i.x(), i.y(), i.z(), i.width(), i.height(), i.isVisible() ] )
            self._preset_base = Preset( "base", parameters )
    
        @QtCore.pyqtSlot( int )
        def removePreset( self, index ):
            if len( self._preset_list ) > 0:
                preset = self._preset_list[ index ]
                self.beginRemoveRows( QtCore.QModelIndex(), index, index )
                self._preset_list.remove( preset )
                self.endRemoveRows()
                self.savePresetsToFile()
    
        @QtCore.pyqtSlot( int )
        def applyPreset( self, index ):
            if index != -1 and len( self._preset_list ) > index:
                preset = self._preset_list[index]
            else:
                preset = self._preset_base
            for i in preset.config:
                item = self.view.rootObject().findChild( QtQuick.QQuickItem, i[0] )
                if item != None:
                    item.setProperty( "x", i[1] )
                    item.setProperty( "y", i[2] )
                    item.setProperty( "z", i[3] )
                    item.setProperty( "width", i[4] )
                    item.setProperty( "height", i[5] )
                    item.setProperty( "visible", i[6] )
    

    The class is instanciated like this

    self.preset_model = preset_model.PresetModel( view )
            self.view.rootContext().setContextProperty( 'presetModel', self.preset_model )
    
        @QtCore.pyqtSlot( QtCore.QVariant )
        def onStatusViewChanged( self, status ):
            if status == QtQuick.QQuickView.Ready:
                self.preset_model.setPresetBase()
                self.preset_model.loadPresetsFromFile()
    
    Pablo J. RoginaP KillerSmathK 2 Replies Last reply
    0
    • H Hodenbrecher

      Hi everyone !

      I have to change a QML human machine interface from python to C++. But I'm new to python AND qml so I'm struggling as the things are getting tough.

      I'll ask my questions before showing the code :

      there's a python class derived from QQAbstractListModel that looks like containing some QtQuick Items. (code below) It's PresetModel. First, I kind of understand the setPresetBase method but... that way to put everything in a table like it's nothing... how can I convert it into C++ ? I guess parameters is a QList ? So I could store my items as QVariant in a QList ? If so, then what ?

      How can I share such a thing with QML ? I see that they just put it in setContextProperty. I tried to do a simple one and do the same, but I couldn't get the data(index) from my QAbstractListModel, or call a method called apply...

      i see that they defined apply as a pyqt slot. What is the equivalent in C++ ? I tried to define it as a public slot : but it changed nothing...
      I'm lost.
      Could you explain me how to create and use a QAbstractListModel such as this on but in C++ ?

      Thanks in advance. Here is the code (not everything, just what I think being useful)

      class PresetModel( QtCore.QAbstractListModel ):
          NameRole = QtCore.Qt.UserRole + 1
      
          _roles = {
              NameRole: b"name",
              }
      
          def __init__( self, view, parent=None ):
              super().__init__( parent )
              self._preset_list = []
              self._preset_base = None
              self.view = view
              self._name_id = 0
      
          def rowCount( self, parent=QtCore.QModelIndex() ):
              return len( self._preset_list )
      
          def data( self, index, role=QtCore.Qt.DisplayRole ):
              try:
                  preset_item = self._preset_list[index.row()]
              except IndexError:
                  return QVariant()
              if role == self.NameRole:
                  return preset_item.name
              return QVariant()
      
          def roleNames( self ):
              return self._roles
      
          def setPresetBase( self ):
              object = self.view.rootObject()
              items = object.childItems()
              parameters = []
              for i in items:
                  if type(i) == QtQuick.QQuickItem and i.objectName() != "" and i.objectName() != "EditPanel" and i.objectName() != "EditGrid":
                      parameters.append( [ i.objectName(), i.x(), i.y(), i.z(), i.width(), i.height(), i.isVisible() ] )
              self._preset_base = Preset( "base", parameters )
      
          @QtCore.pyqtSlot( int )
          def removePreset( self, index ):
              if len( self._preset_list ) > 0:
                  preset = self._preset_list[ index ]
                  self.beginRemoveRows( QtCore.QModelIndex(), index, index )
                  self._preset_list.remove( preset )
                  self.endRemoveRows()
                  self.savePresetsToFile()
      
          @QtCore.pyqtSlot( int )
          def applyPreset( self, index ):
              if index != -1 and len( self._preset_list ) > index:
                  preset = self._preset_list[index]
              else:
                  preset = self._preset_base
              for i in preset.config:
                  item = self.view.rootObject().findChild( QtQuick.QQuickItem, i[0] )
                  if item != None:
                      item.setProperty( "x", i[1] )
                      item.setProperty( "y", i[2] )
                      item.setProperty( "z", i[3] )
                      item.setProperty( "width", i[4] )
                      item.setProperty( "height", i[5] )
                      item.setProperty( "visible", i[6] )
      

      The class is instanciated like this

      self.preset_model = preset_model.PresetModel( view )
              self.view.rootContext().setContextProperty( 'presetModel', self.preset_model )
      
          @QtCore.pyqtSlot( QtCore.QVariant )
          def onStatusViewChanged( self, status ):
              if status == QtQuick.QQuickView.Ready:
                  self.preset_model.setPresetBase()
                  self.preset_model.loadPresetsFromFile()
      
      Pablo J. RoginaP Offline
      Pablo J. RoginaP Offline
      Pablo J. Rogina
      wrote on last edited by
      #2

      @Hodenbrecher said in Understanding QAbstractListModel in python/QML program and C++ equivalent:

      they defined apply as a pyqt slot. What is the equivalent in C++ ? I tried to define it as a public slot : but it changed nothing...

      Not that I'm proficient with Python (yet...) but please remember that a slot (in C++, QML, Python, whatever) is meant to be called/activated by a signal being emitted...
      That said, you may need to check the whole Python code for "connect" entries like these:

      buttonX.clicked.connect(buttonX_clicked())
      

      or

      QObject.connect(buttonY, SIGNAL("clicked()"), buttonY_clicked)
      

      Upvote the answer(s) that helped you solve the issue
      Use "Topic Tools" button to mark your post as Solved
      Add screenshots via postimage.org
      Don't ask support requests via chat/PM. Please use the forum so others can benefit from the solution in the future

      1 Reply Last reply
      1
      • H Hodenbrecher

        Hi everyone !

        I have to change a QML human machine interface from python to C++. But I'm new to python AND qml so I'm struggling as the things are getting tough.

        I'll ask my questions before showing the code :

        there's a python class derived from QQAbstractListModel that looks like containing some QtQuick Items. (code below) It's PresetModel. First, I kind of understand the setPresetBase method but... that way to put everything in a table like it's nothing... how can I convert it into C++ ? I guess parameters is a QList ? So I could store my items as QVariant in a QList ? If so, then what ?

        How can I share such a thing with QML ? I see that they just put it in setContextProperty. I tried to do a simple one and do the same, but I couldn't get the data(index) from my QAbstractListModel, or call a method called apply...

        i see that they defined apply as a pyqt slot. What is the equivalent in C++ ? I tried to define it as a public slot : but it changed nothing...
        I'm lost.
        Could you explain me how to create and use a QAbstractListModel such as this on but in C++ ?

        Thanks in advance. Here is the code (not everything, just what I think being useful)

        class PresetModel( QtCore.QAbstractListModel ):
            NameRole = QtCore.Qt.UserRole + 1
        
            _roles = {
                NameRole: b"name",
                }
        
            def __init__( self, view, parent=None ):
                super().__init__( parent )
                self._preset_list = []
                self._preset_base = None
                self.view = view
                self._name_id = 0
        
            def rowCount( self, parent=QtCore.QModelIndex() ):
                return len( self._preset_list )
        
            def data( self, index, role=QtCore.Qt.DisplayRole ):
                try:
                    preset_item = self._preset_list[index.row()]
                except IndexError:
                    return QVariant()
                if role == self.NameRole:
                    return preset_item.name
                return QVariant()
        
            def roleNames( self ):
                return self._roles
        
            def setPresetBase( self ):
                object = self.view.rootObject()
                items = object.childItems()
                parameters = []
                for i in items:
                    if type(i) == QtQuick.QQuickItem and i.objectName() != "" and i.objectName() != "EditPanel" and i.objectName() != "EditGrid":
                        parameters.append( [ i.objectName(), i.x(), i.y(), i.z(), i.width(), i.height(), i.isVisible() ] )
                self._preset_base = Preset( "base", parameters )
        
            @QtCore.pyqtSlot( int )
            def removePreset( self, index ):
                if len( self._preset_list ) > 0:
                    preset = self._preset_list[ index ]
                    self.beginRemoveRows( QtCore.QModelIndex(), index, index )
                    self._preset_list.remove( preset )
                    self.endRemoveRows()
                    self.savePresetsToFile()
        
            @QtCore.pyqtSlot( int )
            def applyPreset( self, index ):
                if index != -1 and len( self._preset_list ) > index:
                    preset = self._preset_list[index]
                else:
                    preset = self._preset_base
                for i in preset.config:
                    item = self.view.rootObject().findChild( QtQuick.QQuickItem, i[0] )
                    if item != None:
                        item.setProperty( "x", i[1] )
                        item.setProperty( "y", i[2] )
                        item.setProperty( "z", i[3] )
                        item.setProperty( "width", i[4] )
                        item.setProperty( "height", i[5] )
                        item.setProperty( "visible", i[6] )
        

        The class is instanciated like this

        self.preset_model = preset_model.PresetModel( view )
                self.view.rootContext().setContextProperty( 'presetModel', self.preset_model )
        
            @QtCore.pyqtSlot( QtCore.QVariant )
            def onStatusViewChanged( self, status ):
                if status == QtQuick.QQuickView.Ready:
                    self.preset_model.setPresetBase()
                    self.preset_model.loadPresetsFromFile()
        
        KillerSmathK Offline
        KillerSmathK Offline
        KillerSmath
        wrote on last edited by KillerSmath
        #3

        @Hodenbrecher

        . that way to put everything in a table like it's nothing... how can I convert it into C++ ? I guess parameters is a QList ? So I could store my items as QVariant in a QList ? If so, then what ?

        You could create a custom data type to store all variables of QQuickItem, then define a list of this custom data type

        // definition
        typedef struct ObjectDataType{
            QString objectName;
            qreal x, y, z, width, height;
            bool visible;
        } ObjectDataType;
        
        // usage
        QList<ObjectDataType> parameters;
        parameters.append({objName, xValue, yValue, zValue, wValue, hValue, vBoolean});
        

        How can I share such a thing with QML ? I see that they just put it in setContextProperty. I tried to do a simple one and do the same, but I couldn't get the data(index) from my QAbstractListModel, or call a method called apply...

        Are you passing the correct parameters ? Take a look at data function signature.

        QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const

        Can you share a snippet of your code to understand how you are trying to access the data from QML ?


        i see that they defined apply as a pyqt slot. What is the equivalent in C++ ? I tried to define it as a public slot : but it changed nothing...

        Have you defined Q_OBJECT macro on your class definition ? It is necessary to allow the Signal and Slot feature on c++

        https://doc.qt.io/qt-5/qobject.html#Q_OBJECT

        @Computer Science Student - Brazil
        Web Developer and Researcher
        “Sometimes it’s the people no one imagines anything of who do the things that no one can imagine.” - Alan Turing

        H 1 Reply Last reply
        1
        • KillerSmathK KillerSmath

          @Hodenbrecher

          . that way to put everything in a table like it's nothing... how can I convert it into C++ ? I guess parameters is a QList ? So I could store my items as QVariant in a QList ? If so, then what ?

          You could create a custom data type to store all variables of QQuickItem, then define a list of this custom data type

          // definition
          typedef struct ObjectDataType{
              QString objectName;
              qreal x, y, z, width, height;
              bool visible;
          } ObjectDataType;
          
          // usage
          QList<ObjectDataType> parameters;
          parameters.append({objName, xValue, yValue, zValue, wValue, hValue, vBoolean});
          

          How can I share such a thing with QML ? I see that they just put it in setContextProperty. I tried to do a simple one and do the same, but I couldn't get the data(index) from my QAbstractListModel, or call a method called apply...

          Are you passing the correct parameters ? Take a look at data function signature.

          QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const

          Can you share a snippet of your code to understand how you are trying to access the data from QML ?


          i see that they defined apply as a pyqt slot. What is the equivalent in C++ ? I tried to define it as a public slot : but it changed nothing...

          Have you defined Q_OBJECT macro on your class definition ? It is necessary to allow the Signal and Slot feature on c++

          https://doc.qt.io/qt-5/qobject.html#Q_OBJECT

          H Offline
          H Offline
          Hodenbrecher
          wrote on last edited by Hodenbrecher
          #4

          @KillerSmath Thanks for your answer

          The struct is a good idea. What I started to do is a QVector<QVariant>. So I could use it like this:

          //CTOR of the dataModel I will store in the QList
          Preset(QString& air_name, QVector<QVariant>& air_config);
          
          //definition of the QList in PresetModel
          QList<Preset> m_preset_list
          

          what do you think about ? Is the struct more efficient or convenient ?


          i'm using the right definitio, copied it fro the doc.
          Here the use of the class. It's used to personalize the interface by moving the items into the main window.

          GridView {
              id: container
              width: 300; height: 200
              clip: true
          //    [...]
              onCurrentIndexChanged: presetModel.applyPreset( currentIndex )
          //    [...]
              model: presetModel
              delegate: delegatePreset
              highlight: highlight
              remove: Transition {
                  ParallelAnimation {
                      NumberAnimation { property: "scale"; to: 0; duration: 500 }
                      NumberAnimation { properties: "x,y"; to: 100; duration: 500 }
                  }
              }
              currentIndex: -1
          }
          

          I have to say that I don't understand it yet... I just know that I have to create PresetModel. Else I can't launch the QML application.
          What is the model, delegate... I don't know if I need to understand it to write the C++

          So I think that I have to use

          PresetModel* johnnyBoy = new PresetModel(myView);
          QQmlContext::setContextProperty("presetModel", johnnyBoy);
          

          but heard about passing it as a QVariant containing the QList... Maybe I missunderstood


          Yes, everything that needs to be defined as a Q_OBJECT is.
          What I am not sure of is if I have to define apply as a

          public slot: 
          

          or as a

          Q_INVOKABLE
          

          ?


          Subsidiary question
          what is this doing and how to write it in C++ ? I kind of understand the role of the role but this is too much for me and the doc is not very helpful

          class PresetModel( QtCore.QAbstractListModel ):
              NameRole = QtCore.Qt.UserRole + 1      #+1 ??? The docs says it's value is 0x011
          
              _roles = {                             #so I guess its an int...
                  NameRole: b"name",                 #b"name" ????
                  }
          #[...]
              def data( self, index, role=QtCore.Qt.DisplayRole ):
                    try:
                        preset_item = self._preset_list[index.row()]#ok
                    except IndexError:
                        return QVariant()
                    if role == self.NameRole:#not ok
                        return preset_item.name     #Probably used to find the QQuickItem linked later
                    return QVariant()
          

          Maybe I should create a new topic specific to this ?

          Thanks a lot !



          [edit] here is my code for data

          QVariant PresetModel::data(const QModelIndex & air_index, int ai_role) const
          {
          	if (air_index.row() < 0 || air_index.row() >= m_preset_list.size())
          		return QVariant();
          	const Preset& wr_preset_item = m_preset_list[air_index.row()];//definition : QList<Preset> m_preset_list;
          	if (ai_role == m_nameRole)
          		return wr_preset_item.getName();//in CTOR : m_nameRole = Qt::UserRole + 1;
          	return QVariant();
          }
          
          JonBJ KillerSmathK 2 Replies Last reply
          0
          • H Hodenbrecher

            @KillerSmath Thanks for your answer

            The struct is a good idea. What I started to do is a QVector<QVariant>. So I could use it like this:

            //CTOR of the dataModel I will store in the QList
            Preset(QString& air_name, QVector<QVariant>& air_config);
            
            //definition of the QList in PresetModel
            QList<Preset> m_preset_list
            

            what do you think about ? Is the struct more efficient or convenient ?


            i'm using the right definitio, copied it fro the doc.
            Here the use of the class. It's used to personalize the interface by moving the items into the main window.

            GridView {
                id: container
                width: 300; height: 200
                clip: true
            //    [...]
                onCurrentIndexChanged: presetModel.applyPreset( currentIndex )
            //    [...]
                model: presetModel
                delegate: delegatePreset
                highlight: highlight
                remove: Transition {
                    ParallelAnimation {
                        NumberAnimation { property: "scale"; to: 0; duration: 500 }
                        NumberAnimation { properties: "x,y"; to: 100; duration: 500 }
                    }
                }
                currentIndex: -1
            }
            

            I have to say that I don't understand it yet... I just know that I have to create PresetModel. Else I can't launch the QML application.
            What is the model, delegate... I don't know if I need to understand it to write the C++

            So I think that I have to use

            PresetModel* johnnyBoy = new PresetModel(myView);
            QQmlContext::setContextProperty("presetModel", johnnyBoy);
            

            but heard about passing it as a QVariant containing the QList... Maybe I missunderstood


            Yes, everything that needs to be defined as a Q_OBJECT is.
            What I am not sure of is if I have to define apply as a

            public slot: 
            

            or as a

            Q_INVOKABLE
            

            ?


            Subsidiary question
            what is this doing and how to write it in C++ ? I kind of understand the role of the role but this is too much for me and the doc is not very helpful

            class PresetModel( QtCore.QAbstractListModel ):
                NameRole = QtCore.Qt.UserRole + 1      #+1 ??? The docs says it's value is 0x011
            
                _roles = {                             #so I guess its an int...
                    NameRole: b"name",                 #b"name" ????
                    }
            #[...]
                def data( self, index, role=QtCore.Qt.DisplayRole ):
                      try:
                          preset_item = self._preset_list[index.row()]#ok
                      except IndexError:
                          return QVariant()
                      if role == self.NameRole:#not ok
                          return preset_item.name     #Probably used to find the QQuickItem linked later
                      return QVariant()
            

            Maybe I should create a new topic specific to this ?

            Thanks a lot !



            [edit] here is my code for data

            QVariant PresetModel::data(const QModelIndex & air_index, int ai_role) const
            {
            	if (air_index.row() < 0 || air_index.row() >= m_preset_list.size())
            		return QVariant();
            	const Preset& wr_preset_item = m_preset_list[air_index.row()];//definition : QList<Preset> m_preset_list;
            	if (ai_role == m_nameRole)
            		return wr_preset_item.getName();//in CTOR : m_nameRole = Qt::UserRole + 1;
            	return QVariant();
            }
            
            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #5

            @Hodenbrecher
            Your Python to C++ translation looks broadly correct. However, a couple of comments, if you want to understand/improve:

            • NameRole = QtCore.Qt.UserRole + 1: the + 1 just ensures it's unique. I can't recall, but somewhere in the docs something talks about starting your own from QtCore.Qt.UserRole + 1 instead of from QtCore.Qt.UserRole. The value will actually be 0x0101 rather than what you wrote. An int should be fine (Qt::ItemDataRole is actually an enum, but I don't think you can extend its values in C++.)

            • b"name": Python "b string". Byte literal, producing bytes type rather than str type. Whatever that NameRole is used for is it perhaps supposed to be a perhaps a ByteArray rather than a QString? Alternatively, if your original is Python 2 not 3 it might have something to do with Python char type vs Qt QString/C++ char [], I don't know, but I imagine you'll soon know if it's wrong.

            • //in CTOR : m_nameRole = Qt::UserRole + 1;: Note that in Python, anything inside a class but not inside a def --- your NameRole & _roles --- are not instance variables. They are class variables. Your choice of name m_nameRole and setting it in constructor are therefore not great. Your NameRole should therefore be something like a const int defined in the class declaration, and similarly with _roles = ... (can't do that in my C# but I think you can in C++), rather than anything in constructor.

            H 1 Reply Last reply
            1
            • JonBJ JonB

              @Hodenbrecher
              Your Python to C++ translation looks broadly correct. However, a couple of comments, if you want to understand/improve:

              • NameRole = QtCore.Qt.UserRole + 1: the + 1 just ensures it's unique. I can't recall, but somewhere in the docs something talks about starting your own from QtCore.Qt.UserRole + 1 instead of from QtCore.Qt.UserRole. The value will actually be 0x0101 rather than what you wrote. An int should be fine (Qt::ItemDataRole is actually an enum, but I don't think you can extend its values in C++.)

              • b"name": Python "b string". Byte literal, producing bytes type rather than str type. Whatever that NameRole is used for is it perhaps supposed to be a perhaps a ByteArray rather than a QString? Alternatively, if your original is Python 2 not 3 it might have something to do with Python char type vs Qt QString/C++ char [], I don't know, but I imagine you'll soon know if it's wrong.

              • //in CTOR : m_nameRole = Qt::UserRole + 1;: Note that in Python, anything inside a class but not inside a def --- your NameRole & _roles --- are not instance variables. They are class variables. Your choice of name m_nameRole and setting it in constructor are therefore not great. Your NameRole should therefore be something like a const int defined in the class declaration, and similarly with _roles = ... (can't do that in my C# but I think you can in C++), rather than anything in constructor.

              H Offline
              H Offline
              Hodenbrecher
              wrote on last edited by
              #6

              @JonB Thank you very much, that was helpful.

              Note that in Python, anything inside a class but not inside a def --- your NameRole & _roles --- are not instance variables. They are class variables.

              I'm not sure to understand. Do you mean that NameRole and _roles should be static variables in my C++ ?


              Whatever that NameRole is used for is it perhaps supposed to be a perhaps a ByteArray

              That's logical. We set the name as a byte array and use the numerical values of the ASCII char to use it's value.
              But I still don't understand this :

              _roles = {
                      NameRole: b"name",
                      }
              

              if _roles is a byte array maybe the synthax to set it's value is using the { } but then... nameRole : b"name"... So all the PresetModel instances (probably only one thought) will have their _role set to the value corresponding to "name" ? That's weird, i think I don't get it

              Thank you very much for your help


              another subsidiary question

              @QtCore.pyqtSlot()
                  def onPresetChanged( self ):
                      row = 0
                      for r in self._preset_list:
                          if r == self.sender:
                              row = self._preset_list.index( r )#index is part of a QAbstractListItem. But i think _preset_list is a QList or a QVector. and r a Preset object
                              break
                      self.dataChanged.emit( self.index(row, 0), self.index(row, 0), [self.NameRole] )
              

              in the for loop the code assigns to row ( an int probably) a _preset_list.index(r) which means that _preset_list is derived from QAbstractItemModel ? and then there's r in the parameters. r is an element from _preset_list, right ? A Preset object.

              JonBJ 1 Reply Last reply
              0
              • H Hodenbrecher

                @JonB Thank you very much, that was helpful.

                Note that in Python, anything inside a class but not inside a def --- your NameRole & _roles --- are not instance variables. They are class variables.

                I'm not sure to understand. Do you mean that NameRole and _roles should be static variables in my C++ ?


                Whatever that NameRole is used for is it perhaps supposed to be a perhaps a ByteArray

                That's logical. We set the name as a byte array and use the numerical values of the ASCII char to use it's value.
                But I still don't understand this :

                _roles = {
                        NameRole: b"name",
                        }
                

                if _roles is a byte array maybe the synthax to set it's value is using the { } but then... nameRole : b"name"... So all the PresetModel instances (probably only one thought) will have their _role set to the value corresponding to "name" ? That's weird, i think I don't get it

                Thank you very much for your help


                another subsidiary question

                @QtCore.pyqtSlot()
                    def onPresetChanged( self ):
                        row = 0
                        for r in self._preset_list:
                            if r == self.sender:
                                row = self._preset_list.index( r )#index is part of a QAbstractListItem. But i think _preset_list is a QList or a QVector. and r a Preset object
                                break
                        self.dataChanged.emit( self.index(row, 0), self.index(row, 0), [self.NameRole] )
                

                in the for loop the code assigns to row ( an int probably) a _preset_list.index(r) which means that _preset_list is derived from QAbstractItemModel ? and then there's r in the parameters. r is an element from _preset_list, right ? A Preset object.

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

                @Hodenbrecher said in Understanding QAbstractListModel in python/QML program and C++ equivalent:

                I'm not sure to understand. Do you mean that NameRole and _roles should be static variables in my C++ ?

                Yes. static, or better still const since you don't want to alter them after they are set. My C++ is a bit ropey, but you can have something like:

                class PresetModel
                {
                    static const int s_nameRole = Qt::UserRole + 1;
                }
                

                The important thing is that this value is available outside/independent of any instance (via PresetModel::s_nameRole), and other code might require that.

                if _roles is a byte array

                It isn't. roles is (like) a C++ struct, hence the { ... }. It is the NameRole member which is the byte array. You can do something more nowadays in C++ with these, but in C this would be something like:

                struct {
                    byteArray NameRole;
                } _roles = {
                    "name"
                };
                

                Again because it's at the class level you'll want something like static struct ...: it's to be shared by all instances. This is adding some kind of "name role" to this class, in addition to the in-built Qt::ItemDataRole ones. I don't think all on its own the _roles is used/does anything: I am expecting you to find it referenced somewhere in code (via PresetModel._roles) to "declare" a new role. Doubtless it will have something to do with https://doc.qt.io/qt-5/qabstractitemmodel-obsolete.html#setRoleNames (now defunct) & https://doc.qt.io/qt-5/qabstractitemmodel.html#roleNames, q.v..

                1 Reply Last reply
                1
                • H Hodenbrecher

                  @KillerSmath Thanks for your answer

                  The struct is a good idea. What I started to do is a QVector<QVariant>. So I could use it like this:

                  //CTOR of the dataModel I will store in the QList
                  Preset(QString& air_name, QVector<QVariant>& air_config);
                  
                  //definition of the QList in PresetModel
                  QList<Preset> m_preset_list
                  

                  what do you think about ? Is the struct more efficient or convenient ?


                  i'm using the right definitio, copied it fro the doc.
                  Here the use of the class. It's used to personalize the interface by moving the items into the main window.

                  GridView {
                      id: container
                      width: 300; height: 200
                      clip: true
                  //    [...]
                      onCurrentIndexChanged: presetModel.applyPreset( currentIndex )
                  //    [...]
                      model: presetModel
                      delegate: delegatePreset
                      highlight: highlight
                      remove: Transition {
                          ParallelAnimation {
                              NumberAnimation { property: "scale"; to: 0; duration: 500 }
                              NumberAnimation { properties: "x,y"; to: 100; duration: 500 }
                          }
                      }
                      currentIndex: -1
                  }
                  

                  I have to say that I don't understand it yet... I just know that I have to create PresetModel. Else I can't launch the QML application.
                  What is the model, delegate... I don't know if I need to understand it to write the C++

                  So I think that I have to use

                  PresetModel* johnnyBoy = new PresetModel(myView);
                  QQmlContext::setContextProperty("presetModel", johnnyBoy);
                  

                  but heard about passing it as a QVariant containing the QList... Maybe I missunderstood


                  Yes, everything that needs to be defined as a Q_OBJECT is.
                  What I am not sure of is if I have to define apply as a

                  public slot: 
                  

                  or as a

                  Q_INVOKABLE
                  

                  ?


                  Subsidiary question
                  what is this doing and how to write it in C++ ? I kind of understand the role of the role but this is too much for me and the doc is not very helpful

                  class PresetModel( QtCore.QAbstractListModel ):
                      NameRole = QtCore.Qt.UserRole + 1      #+1 ??? The docs says it's value is 0x011
                  
                      _roles = {                             #so I guess its an int...
                          NameRole: b"name",                 #b"name" ????
                          }
                  #[...]
                      def data( self, index, role=QtCore.Qt.DisplayRole ):
                            try:
                                preset_item = self._preset_list[index.row()]#ok
                            except IndexError:
                                return QVariant()
                            if role == self.NameRole:#not ok
                                return preset_item.name     #Probably used to find the QQuickItem linked later
                            return QVariant()
                  

                  Maybe I should create a new topic specific to this ?

                  Thanks a lot !



                  [edit] here is my code for data

                  QVariant PresetModel::data(const QModelIndex & air_index, int ai_role) const
                  {
                  	if (air_index.row() < 0 || air_index.row() >= m_preset_list.size())
                  		return QVariant();
                  	const Preset& wr_preset_item = m_preset_list[air_index.row()];//definition : QList<Preset> m_preset_list;
                  	if (ai_role == m_nameRole)
                  		return wr_preset_item.getName();//in CTOR : m_nameRole = Qt::UserRole + 1;
                  	return QVariant();
                  }
                  
                  KillerSmathK Offline
                  KillerSmathK Offline
                  KillerSmath
                  wrote on last edited by
                  #8

                  @Hodenbrecher

                  What I am not sure of is if I have to define apply as a
                  public slot:
                  or as a
                  Q_INVOKABLE

                  Slot and Invokable macros are used to different situation.

                  • Slot is used to allow a function to receive signals.
                  • Q_INVOKABLE allow the qml to directly call a function

                  Have you seen the QAbstractItemModel Qt Example ? It will improve your understanding of how to forward a custom c++ model to QML.

                  https://doc.qt.io/qt-5/qtquick-models-abstractitemmodel-example.html

                  @Computer Science Student - Brazil
                  Web Developer and Researcher
                  “Sometimes it’s the people no one imagines anything of who do the things that no one can imagine.” - Alan Turing

                  1 Reply Last reply
                  3

                  • Login

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