Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. General talk
  3. Brainstorm
  4. Update C++ list model from QML

Update C++ list model from QML

Scheduled Pinned Locked Moved Solved Brainstorm
11 Posts 4 Posters 2.3k 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.
  • T Offline
    T Offline
    TomZ
    wrote on 15 Jan 2023, 10:31 last edited by
    #2

    The simplest answer to this is that you should not try this.

    To add a new listitem from QML, you can have a invokable C++ method you call, but that should not have anything other than default types. Like ints, strings, date etc.
    (Only exception to this is when you pass a class back from QML which was earlier passed into QML from C++).

    So, you can make your append() method simply be the one that instantiates the item on your list, and then emit the signal to indicate the list has been changed.

    M 1 Reply Last reply 15 Jan 2023, 15:37
    0
    • T TomZ
      15 Jan 2023, 10:31

      The simplest answer to this is that you should not try this.

      To add a new listitem from QML, you can have a invokable C++ method you call, but that should not have anything other than default types. Like ints, strings, date etc.
      (Only exception to this is when you pass a class back from QML which was earlier passed into QML from C++).

      So, you can make your append() method simply be the one that instantiates the item on your list, and then emit the signal to indicate the list has been changed.

      M Offline
      M Offline
      mzimmers
      wrote on 15 Jan 2023, 15:37 last edited by
      #3

      @TomZ when you say "should not try this," what specifically are you referring to? The tutorial I mentioned above uses a QVector<a_struct> as the basis for its list.

      The tutorial does have a couple curious aspects, though. I've watched it 3 times now (at 50 minutes per!), and I still don't understand why he creates a new C++ class (ToDoList) as the "back end," then references that class in his QML. Isn't the point of a model to insulate the rest of the code from the back end?

      Thanks...

      T 1 Reply Last reply 15 Jan 2023, 22:22
      0
      • M mzimmers
        15 Jan 2023, 15:37

        @TomZ when you say "should not try this," what specifically are you referring to? The tutorial I mentioned above uses a QVector<a_struct> as the basis for its list.

        The tutorial does have a couple curious aspects, though. I've watched it 3 times now (at 50 minutes per!), and I still don't understand why he creates a new C++ class (ToDoList) as the "back end," then references that class in his QML. Isn't the point of a model to insulate the rest of the code from the back end?

        Thanks...

        T Offline
        T Offline
        TomZ
        wrote on 15 Jan 2023, 22:22 last edited by
        #4

        @mzimmers said in Passing data structures from QML to C++:

        when you say "should not try this," what specifically are you referring to?

        The idea to write Q_INVOKABLE void appendItem(Activity item) and the implications of it. Rationale (and solution) I wrote in my previous reply.

        M 1 Reply Last reply 15 Jan 2023, 23:29
        0
        • T TomZ
          15 Jan 2023, 22:22

          @mzimmers said in Passing data structures from QML to C++:

          when you say "should not try this," what specifically are you referring to?

          The idea to write Q_INVOKABLE void appendItem(Activity item) and the implications of it. Rationale (and solution) I wrote in my previous reply.

          M Offline
          M Offline
          mzimmers
          wrote on 15 Jan 2023, 23:29 last edited by
          #5

          @TomZ if I understand you, you're objecting to my use of a struct as my list element? Not sure what I'd do instead. Here's the code for appendItem():

          void ActivityModel::appendItem(Activity item)
          {
              m_list->appendItem(item); // another class with the actual list.
              emit listChanged(m_list);
          }
          

          Not sure what I'd do differently here. I could modify appendItem() to not have a parameter, but then I don't know how I'd populate the newly-created item in QML.

          Sorry if I sound confused; it's only because I really am.

          T 1 Reply Last reply 16 Jan 2023, 10:06
          0
          • M mzimmers
            15 Jan 2023, 23:29

            @TomZ if I understand you, you're objecting to my use of a struct as my list element? Not sure what I'd do instead. Here's the code for appendItem():

            void ActivityModel::appendItem(Activity item)
            {
                m_list->appendItem(item); // another class with the actual list.
                emit listChanged(m_list);
            }
            

            Not sure what I'd do differently here. I could modify appendItem() to not have a parameter, but then I don't know how I'd populate the newly-created item in QML.

            Sorry if I sound confused; it's only because I really am.

            T Offline
            T Offline
            TomZ
            wrote on 16 Jan 2023, 10:06 last edited by TomZ
            #6

            @mzimmers said in Passing data structures from QML to C++:

            if I understand you, you're objecting to my use of a struct as my list element?

            No, I stated you should not have an invokable append() method which has the struct.
            I further stated; "To add a new listitem from QML, you can have a invokable C++ method you call, but that should not have anything other than default types. Like ints, strings, date etc."

            So go ahead and have anything as your list item. Most of us use QObject or string based list-items.

            1 Reply Last reply
            0
            • T Offline
              T Offline
              TomZ
              wrote on 16 Jan 2023, 10:11 last edited by
              #7

              Maybe the point can be driven home by simply understanding object ownership.

              Your list is owned by the model. The QML can read it, but can never directly delete items from your list. The model is the one that creates new items and deletes items. It owns the list and its list-items.

              So if you want your QML to add a new item somehow, you will still need the model to be the one that instantiates the new list-item. And understand that as soon as the list changes, the view will follow.

              M 1 Reply Last reply 16 Jan 2023, 14:59
              0
              • T TomZ
                16 Jan 2023, 10:11

                Maybe the point can be driven home by simply understanding object ownership.

                Your list is owned by the model. The QML can read it, but can never directly delete items from your list. The model is the one that creates new items and deletes items. It owns the list and its list-items.

                So if you want your QML to add a new item somehow, you will still need the model to be the one that instantiates the new list-item. And understand that as soon as the list changes, the view will follow.

                M Offline
                M Offline
                mzimmers
                wrote on 16 Jan 2023, 14:59 last edited by
                #8

                @TomZ I've modified my append function as follows:

                void ActivityModel::appendItem(Activity item)
                {
                    Activity newItem = item;
                    m_list->appendItem(newItem);
                    emit listChanged(m_list);
                }
                

                Using the debugger, I verified that the list now contains the new item. But the view doesn't change.

                J 1 Reply Last reply 16 Jan 2023, 15:13
                0
                • M mzimmers
                  16 Jan 2023, 14:59

                  @TomZ I've modified my append function as follows:

                  void ActivityModel::appendItem(Activity item)
                  {
                      Activity newItem = item;
                      m_list->appendItem(newItem);
                      emit listChanged(m_list);
                  }
                  

                  Using the debugger, I verified that the list now contains the new item. But the view doesn't change.

                  J Offline
                  J Offline
                  JoeCFD
                  wrote on 16 Jan 2023, 15:13 last edited by
                  #9

                  @mzimmers Try the following and read the doc.

                  void ActivityModel::appendItem(Activity item)
                  {
                      Activity newItem = item;
                      beginResetModel();  
                      m_list->appendItem(newItem);
                      endResetModel();
                  }
                  
                  M 1 Reply Last reply 16 Jan 2023, 16:12
                  1
                  • J JoeCFD
                    16 Jan 2023, 15:13

                    @mzimmers Try the following and read the doc.

                    void ActivityModel::appendItem(Activity item)
                    {
                        Activity newItem = item;
                        beginResetModel();  
                        m_list->appendItem(newItem);
                        endResetModel();
                    }
                    
                    M Offline
                    M Offline
                    mzimmers
                    wrote on 16 Jan 2023, 16:12 last edited by
                    #10

                    @JoeCFD that did it. Following the example in the tutorial, I had created this function:

                    void ActivityModel::setList(ActivityList *list)
                    {
                        beginResetModel();
                        if (m_list != nullptr) {
                            m_list->disconnect(this);
                        }
                    
                        m_list = list;
                    
                        if (m_list != nullptr) {
                            connect(m_list, &ActivityList::preItemAppended, this, [=]() {
                                const int index = m_list->activities().size();
                                beginInsertRows(QModelIndex(), index, index);
                            });
                            connect(m_list, &ActivityList::postItemAppended, this, [=]() {
                                endInsertRows();
                            });
                    
                            connect(m_list, &ActivityList::preItemRemoved, this, [=](int index) {
                                beginRemoveRows(QModelIndex(), index, index);
                            });
                            connect(m_list, &ActivityList::postItemRemoved, this, [=]() {
                                endRemoveRows();
                            });
                        }
                    
                        endResetModel();
                    }
                    

                    but I guess it didn't get invoked.

                    The tutorial really is confusing in the area where it creates a new class for the list. It adds a level of indirection that makes it harder to understand the interaction between C++ and QML.

                    1 Reply Last reply
                    0
                    • ChronalC Offline
                      ChronalC Offline
                      Chronal
                      wrote on 31 Jan 2023, 13:01 last edited by
                      #11

                      You can use a QAbstractListModel to update the list model from QML. The QAbstractListModel provides an interface for accessing data from a list of items. It can be used to update the list model from QML by using the setData() method.

                      To update the list model from QML, you will need to create a QAbstractListModel subclass and implement the setData() method. The setData() method should take the index of the item to be updated and the new value for the item. You can then call the setData() method from QML to update the list model.

                      For example, if you have a list of strings, you can create a QAbstractListModel subclass and implement the setData() method as follows:

                      void MyListModel::setData(const QModelIndex &index, const QVariant &value, int role)
                      {
                      if (index.isValid() && role == Qt::EditRole) {
                      int row = index.row();
                      QStringList list = data(index, Qt::DisplayRole).toStringList();
                      list[row] = value.toString();
                      setData(index, QVariant::fromValue(list), Qt::DisplayRole);
                      }
                      }

                      You can then call the setData() method from QML to update the list model. For example:

                      MyListModel {
                      id: myListModel
                      // ...
                      }

                      Button {
                      text: "Update List Model"
                      onClicked: {
                      myListModel.setData(myListModel.index(0, 0), "New Value", Qt.EditRole);
                      }
                      }

                      This will update the first item in the list model with the new value.

                      1 Reply Last reply
                      0
                      • M mzimmers has marked this topic as unsolved on 28 Mar 2023, 23:20
                      • M mzimmers has marked this topic as solved on 28 Mar 2023, 23:20

                      • Login

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