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. handling deletion of item in C++ model
Qt 6.11 is out! See what's new in the release blog

handling deletion of item in C++ model

Scheduled Pinned Locked Moved Solved QML and Qt Quick
10 Posts 3 Posters 1.5k Views 3 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.
  • mzimmersM Offline
    mzimmersM Offline
    mzimmers
    wrote on last edited by
    #1

    Hi all -

    I have a C++ defined model:

    typedef std::shared_ptr<Schedule> SchedulePtr;
    typedef QList<SchedulePtr> ScheduleList;
    
    class ScheduleModel : public QAbstractListModel
    {
        Q_OBJECT
        QML_ELEMENT
    
        ScheduleList m_list;
    

    Exposed properly to QML, and used as follows:

    // ScheduleScreen.qml
    GridView {
        id: gridView
        model: scheduleModel
        delegate: ScheduleCard {
            id: scheduleCard
            schedule: scheduleObject // a role in my model.
    
    // ScheduleCard.qml
    Pane {
        property Schedule schedule
        Label {
            text: schedule.name // a Q_PROPERTY in my Schedule class.
    

    Everything seems to work fine, until I delete an item from my model, at which point, the console gives me a bunch of TypeErrors like this one:

     TypeError: Cannot read property 'name' of null
    

    I think I understand why this is happening (the object's been deleted), but I'm wondering if there's something I could be doing to cause a more graceful handling of the deletion.

    Thanks...

    1 Reply Last reply
    0
    • mzimmersM mzimmers

      @JonB

      int ScheduleModel::rowCount(const QModelIndex &parent) const
      {
          // For list models only the root node (an invalid parent) should return the list's size. For all
          // other (valid) parents, rowCount() should return 0 so that it does not become a tree model.
          if (parent.isValid())
              return 0;
          return m_list.size();
      }
      
      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #8

      @mzimmers
      Your C++ code looks good. You know I know nothing about QML. If this is true you ought be able to knock up a one page standalone QML project with that code and test against a standard model or your model to test. It ought not go wrong.

      Signals like QAbstractItemModel::rowsAboutToBeRemoved() and QAbstractItemModel::rowsRemoved() are emitted by any model. They come from your begin/endRemoveRows() calls. Your QML view should see that and work accordingly. I don't know if you can test from QML this is being received just to check.

      mzimmersM 1 Reply Last reply
      1
      • MesrineM Offline
        MesrineM Offline
        Mesrine
        wrote on last edited by Mesrine
        #2

        @mzimmers
        If the object is deleted there may be no point in having the row on the model.

        So, you need to call beginRemoveRows before deleting the object.

        mzimmersM 1 Reply Last reply
        0
        • MesrineM Mesrine

          @mzimmers
          If the object is deleted there may be no point in having the row on the model.

          So, you need to call beginRemoveRows before deleting the object.

          mzimmersM Offline
          mzimmersM Offline
          mzimmers
          wrote on last edited by
          #3

          @Mesrine my removeRows() routine:

          bool ScheduleModel::removeRows(int row, int count, const QModelIndex &parent)
          {
              beginRemoveRows(parent, row, row + count - 1);
              m_list.remove(row, count);
              endRemoveRows();
              return true;
          }
          

          This is all I do when I'm deleting an item. Am I missing a step? My model is a list of shared_ptrs.

          MesrineM 1 Reply Last reply
          0
          • mzimmersM mzimmers

            @Mesrine my removeRows() routine:

            bool ScheduleModel::removeRows(int row, int count, const QModelIndex &parent)
            {
                beginRemoveRows(parent, row, row + count - 1);
                m_list.remove(row, count);
                endRemoveRows();
                return true;
            }
            

            This is all I do when I'm deleting an item. Am I missing a step? My model is a list of shared_ptrs.

            MesrineM Offline
            MesrineM Offline
            Mesrine
            wrote on last edited by
            #4

            @mzimmers
            It seems you are doing what the docs say.
            I do not know why I also add
            emit countChanged(count());
            Between beginRemoveRows and endRemoveRows where count is a QProperty I define like
            Q_PROPERTY(int count READ count NOTIFY countChanged)
            .
            This may not solve your issue but you can try until a better answer comes up.

            mzimmersM 1 Reply Last reply
            0
            • MesrineM Mesrine

              @mzimmers
              It seems you are doing what the docs say.
              I do not know why I also add
              emit countChanged(count());
              Between beginRemoveRows and endRemoveRows where count is a QProperty I define like
              Q_PROPERTY(int count READ count NOTIFY countChanged)
              .
              This may not solve your issue but you can try until a better answer comes up.

              mzimmersM Offline
              mzimmersM Offline
              mzimmers
              wrote on last edited by
              #5

              @Mesrine sorry it took me so long to get back to this. Your suggestion is intriguing, but I'm not sure I fully understand it. To what slot does countChanged() connect?

              JonBJ 1 Reply Last reply
              0
              • mzimmersM mzimmers

                @Mesrine sorry it took me so long to get back to this. Your suggestion is intriguing, but I'm not sure I fully understand it. To what slot does countChanged() connect?

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

                @mzimmers And just confirm what the code of your ScheduleModel::rowCount() override is?

                mzimmersM 1 Reply Last reply
                0
                • JonBJ JonB

                  @mzimmers And just confirm what the code of your ScheduleModel::rowCount() override is?

                  mzimmersM Offline
                  mzimmersM Offline
                  mzimmers
                  wrote on last edited by
                  #7

                  @JonB

                  int ScheduleModel::rowCount(const QModelIndex &parent) const
                  {
                      // For list models only the root node (an invalid parent) should return the list's size. For all
                      // other (valid) parents, rowCount() should return 0 so that it does not become a tree model.
                      if (parent.isValid())
                          return 0;
                      return m_list.size();
                  }
                  
                  JonBJ 1 Reply Last reply
                  1
                  • mzimmersM mzimmers

                    @JonB

                    int ScheduleModel::rowCount(const QModelIndex &parent) const
                    {
                        // For list models only the root node (an invalid parent) should return the list's size. For all
                        // other (valid) parents, rowCount() should return 0 so that it does not become a tree model.
                        if (parent.isValid())
                            return 0;
                        return m_list.size();
                    }
                    
                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by JonB
                    #8

                    @mzimmers
                    Your C++ code looks good. You know I know nothing about QML. If this is true you ought be able to knock up a one page standalone QML project with that code and test against a standard model or your model to test. It ought not go wrong.

                    Signals like QAbstractItemModel::rowsAboutToBeRemoved() and QAbstractItemModel::rowsRemoved() are emitted by any model. They come from your begin/endRemoveRows() calls. Your QML view should see that and work accordingly. I don't know if you can test from QML this is being received just to check.

                    mzimmersM 1 Reply Last reply
                    1
                    • JonBJ JonB

                      @mzimmers
                      Your C++ code looks good. You know I know nothing about QML. If this is true you ought be able to knock up a one page standalone QML project with that code and test against a standard model or your model to test. It ought not go wrong.

                      Signals like QAbstractItemModel::rowsAboutToBeRemoved() and QAbstractItemModel::rowsRemoved() are emitted by any model. They come from your begin/endRemoveRows() calls. Your QML view should see that and work accordingly. I don't know if you can test from QML this is being received just to check.

                      mzimmersM Offline
                      mzimmersM Offline
                      mzimmers
                      wrote on last edited by
                      #9

                      @JonB makes sense. I can accept any signal in QML, so that's not the challenge. What I'm wondering is what I should do on the QML side once I realize that a model element has been deleted. (I realize this isn't in your wheelhouse.)

                      JonBJ 1 Reply Last reply
                      0
                      • mzimmersM mzimmers

                        @JonB makes sense. I can accept any signal in QML, so that's not the challenge. What I'm wondering is what I should do on the QML side once I realize that a model element has been deleted. (I realize this isn't in your wheelhouse.)

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

                        @mzimmers
                        If you are displaying a list of them in a "grid view" or "table view" I would not expect you to have to do anything. Like the QTableView widget I would expect it to see those signals and handle it itself without getting null references. If you keep something around in the QML referencing the deleted row/item then that might error?

                        1 Reply Last reply
                        0
                        • mzimmersM mzimmers has marked this topic as solved on

                        • Login

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