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. Model-View C++ to QML update issue

Model-View C++ to QML update issue

Scheduled Pinned Locked Moved General and Desktop
model-viewlistviewmodelupdate
8 Posts 2 Posters 4.5k 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.
  • G Offline
    G Offline
    gardiol
    wrote on 22 Apr 2015, 06:46 last edited by
    #1

    I have a listview on QML:

      ListView {
            anchors.fill: parent
            model: mymodel
            delegate: ListDelegate  {
            }
        }
    

    And my delegate (it's into a saperate file called ListGelegate.qml):

    Item {
        width: parent.width
        height: button1.height
        Text {
            id: name
            text: title
            anchors.left: parent.left
            anchors.top: parent.top
            anchors.bottom: parent.bottom
            verticalAlignment: Text.AlignVCenter
            horizontalAlignment: Text.AlignLeft
        }
        Button {
            id: button1
            anchors.right: parent.right
            text: "open"
            onClicked:{
                 do my stuff here
            }
        }
    }
    

    My model is implemented in C++, and looks like:

    class MyClass
    {
        private:
            QList<QObject*> list_of_objects;
        public:
            QList<QObject*>& getModel() const
            {
                return  list_of_objects;
            }
            <other class related stuff here>
    }
    

    Then i register the model for the QML:

        myClass = new MyClass();
        engine.rootContext()->setContextProperty( "mymodel", QVariant::fromValue( myClass.getModel() ) );
    

    I can properly see in the view any item which has been already loaded in the model BEFORE i call the setContectProperty. Anything i add or remove AFTER that, well, the view does not get updated.
    Please consider the list get modified based on events which are outside the QML control so i need the C++ side to trigger an update, possibly without getting too involved in the QML since i would like to keep it independent as much as possible...

    Am i missing something?

    P 1 Reply Last reply 22 Apr 2015, 07:13
    0
    • G gardiol
      22 Apr 2015, 06:46

      I have a listview on QML:

        ListView {
              anchors.fill: parent
              model: mymodel
              delegate: ListDelegate  {
              }
          }
      

      And my delegate (it's into a saperate file called ListGelegate.qml):

      Item {
          width: parent.width
          height: button1.height
          Text {
              id: name
              text: title
              anchors.left: parent.left
              anchors.top: parent.top
              anchors.bottom: parent.bottom
              verticalAlignment: Text.AlignVCenter
              horizontalAlignment: Text.AlignLeft
          }
          Button {
              id: button1
              anchors.right: parent.right
              text: "open"
              onClicked:{
                   do my stuff here
              }
          }
      }
      

      My model is implemented in C++, and looks like:

      class MyClass
      {
          private:
              QList<QObject*> list_of_objects;
          public:
              QList<QObject*>& getModel() const
              {
                  return  list_of_objects;
              }
              <other class related stuff here>
      }
      

      Then i register the model for the QML:

          myClass = new MyClass();
          engine.rootContext()->setContextProperty( "mymodel", QVariant::fromValue( myClass.getModel() ) );
      

      I can properly see in the view any item which has been already loaded in the model BEFORE i call the setContectProperty. Anything i add or remove AFTER that, well, the view does not get updated.
      Please consider the list get modified based on events which are outside the QML control so i need the C++ side to trigger an update, possibly without getting too involved in the QML since i would like to keep it independent as much as possible...

      Am i missing something?

      P Offline
      P Offline
      p3c0
      Moderators
      wrote on 22 Apr 2015, 07:13 last edited by
      #2

      Hi @gardiol
      There is no way to do so unless you call setContextProperty again. Its documented here.

      Note: There is no way for the view to know that the contents of a QList has changed. If the QList changes, it is necessary to reset the model by calling QQmlContext::setContextProperty() again.

      A more better and controlled approach would be to create custom model by subclassing QAbstractItemModel. You can use methods like beginResetModel() and endResetModel() or dataChanged signal to make view aware of the changes.

      157

      1 Reply Last reply
      1
      • G Offline
        G Offline
        gardiol
        wrote on 22 Apr 2015, 07:42 last edited by gardiol
        #3

        Thanks for the quick reply!

        I have a question, suppose i create my model like this:

        class MyModel: public QAbstractListModel
        {
        public:
            MyModel();
            ~MyModel();
            void addITem( QObject* item )
            {
                int n_items = _items.size();
                _items.append( item );
                emit dataChanged( n_items, n_items+1 );
            }
            int rowCount(const QModelIndex &parent) const;
            QVariant data(const QModelIndex &index, int role) const;
            QVariant headerData(int section, Qt::Orientation orientation, int role) const;
        private:
            QList<QObject*> _items;
        };
        

        How do i pass this to the QML side? If i still call (see OP for code):

        setContextProperty( "mymodel", QVariant::fromValue( myClass.getModel() ) );
        

        Would'nt this still bind a COPY of the model to the QML side, so that an update will update the MyClass internal member and NOT the QML copy?

        (supposing, of course, i change the return type of getModel() and MyClass to host a MyModel instance instead of a QList instance)

        P 1 Reply Last reply 22 Apr 2015, 08:04
        0
        • G gardiol
          22 Apr 2015, 07:42

          Thanks for the quick reply!

          I have a question, suppose i create my model like this:

          class MyModel: public QAbstractListModel
          {
          public:
              MyModel();
              ~MyModel();
              void addITem( QObject* item )
              {
                  int n_items = _items.size();
                  _items.append( item );
                  emit dataChanged( n_items, n_items+1 );
              }
              int rowCount(const QModelIndex &parent) const;
              QVariant data(const QModelIndex &index, int role) const;
              QVariant headerData(int section, Qt::Orientation orientation, int role) const;
          private:
              QList<QObject*> _items;
          };
          

          How do i pass this to the QML side? If i still call (see OP for code):

          setContextProperty( "mymodel", QVariant::fromValue( myClass.getModel() ) );
          

          Would'nt this still bind a COPY of the model to the QML side, so that an update will update the MyClass internal member and NOT the QML copy?

          (supposing, of course, i change the return type of getModel() and MyClass to host a MyModel instance instead of a QList instance)

          P Offline
          P Offline
          p3c0
          Moderators
          wrote on 22 Apr 2015, 08:04 last edited by
          #4

          @gardiol Yes that should work.

          157

          1 Reply Last reply
          0
          • G Offline
            G Offline
            gardiol
            wrote on 22 Apr 2015, 09:12 last edited by
            #5

            Ok, i am having some pratcical issues here:

            QVariant MyModel::data(const QModelIndex &index, int /*role*/) const
            {
                if ( !index.isValid() )
                    return QVariant();
                QObject* item= _items.at( index.row() );
                return item;
            }
            

            This does not compile because QVariant's void* constructor is private.... But then what do i need to do???

            Also, i had to change:

            MyModel& MyClass::getModel();
            setContextProperty( "mymodel", QVariant::fromValue( myClass.getModel() ) );
            

            to:

            MyModel* MyClass::getModel();
            setContextProperty( "mymodel", myClass.getModel() );
            

            Or it would not compile, is this correct?

            P 1 Reply Last reply 22 Apr 2015, 09:54
            0
            • G gardiol
              22 Apr 2015, 09:12

              Ok, i am having some pratcical issues here:

              QVariant MyModel::data(const QModelIndex &index, int /*role*/) const
              {
                  if ( !index.isValid() )
                      return QVariant();
                  QObject* item= _items.at( index.row() );
                  return item;
              }
              

              This does not compile because QVariant's void* constructor is private.... But then what do i need to do???

              Also, i had to change:

              MyModel& MyClass::getModel();
              setContextProperty( "mymodel", QVariant::fromValue( myClass.getModel() ) );
              

              to:

              MyModel* MyClass::getModel();
              setContextProperty( "mymodel", myClass.getModel() );
              

              Or it would not compile, is this correct?

              P Offline
              P Offline
              p3c0
              Moderators
              wrote on 22 Apr 2015, 09:54 last edited by p3c0
              #6

              @gardiol Dont return the object itself instead create setters and getters methos to get and set data. Follow the simple example here.

              Regarding second problem, it depends on how you return (reference or pointer) from that function.
              For eg:
              Following will work:

              MyModel *model = new MyModel;
              ...
              
              MyModel &MyClass::getModel()
              {
                  return *model;
              }
              ...
              setContextProperty( "mymodel", QVariant::fromValue( myClass.getModel() ) );
              

              Also this too

              MyModel *model = new MyModel;
              
              MyModel *MyClass::getModel()
              {
                  return model;
              }
              
              setContextProperty( "mymodel", QVariant::fromValue( myClass.getModel() ) );
              

              157

              1 Reply Last reply
              1
              • G Offline
                G Offline
                gardiol
                wrote on 22 Apr 2015, 10:48 last edited by
                #7

                Thank you very much!

                I am now returning a pointer and it works perfectly. I also studied a bit about roles in models and it seems i managed to get it working properly!

                I have to say, it's quite complex and elaborated. I understand it's a solution to a generic problem, but still a very verbose solution to a simple specific problem. Never been a fan of the model/view paradigm myself, but it's pretty flexible once you get it going.

                P 1 Reply Last reply 22 Apr 2015, 10:58
                0
                • G gardiol
                  22 Apr 2015, 10:48

                  Thank you very much!

                  I am now returning a pointer and it works perfectly. I also studied a bit about roles in models and it seems i managed to get it working properly!

                  I have to say, it's quite complex and elaborated. I understand it's a solution to a generic problem, but still a very verbose solution to a simple specific problem. Never been a fan of the model/view paradigm myself, but it's pretty flexible once you get it going.

                  P Offline
                  P Offline
                  p3c0
                  Moderators
                  wrote on 22 Apr 2015, 10:58 last edited by
                  #8

                  @gardiol Yeah at first it seems to be quite complex (overriding so much stuff etc.. ) but as the data grows and the view becomes more complex the Model/View turns out to be a boon.

                  157

                  1 Reply Last reply
                  0

                  5/8

                  22 Apr 2015, 09:12

                  • Login

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