Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-122958

DelegateChooser does not react to the model's dataChanged() signal, fails to re-check Role

    XMLWordPrintable

Details

    • Bug
    • Resolution: Duplicate
    • P2: Important
    • None
    • 5.15.16, 6.2.11, 6.5.4, 6.6.2
    • Quick: Other
    • Windows 10 22H2, MSVC 2019 x64

    Description

      The example below is a bit contrived, but it demonstrates the issue.

       

      Code

      // mylistmodel.h
      class MyListModel : public QAbstractListModel
      {
          Q_OBJECT
          QML_ELEMENT
      
      public:
          explicit MyListModel(QObject *parent = nullptr) : QAbstractListModel(parent) {}
      
          int rowCount(const QModelIndex &parent = QModelIndex()) const override
          { return parent.isValid() ? 0 : 5; }
      
          QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
          {
              if (index.isValid())
              {
                  if (role == Qt::ItemDataRole::DisplayRole)
                  {
                      qDebug() << "Getting DisplayRole data for" << index;
                      return QString::number(index.row());
                  }
                  if (role == Qt::ItemDataRole::StatusTipRole)
                  {
                      qDebug() << "Getting StatusTipRole data for" << index;
                      return (m_roleSwitch && index.row() == SWITCHABLE_ROW) ? "B" : "A";
                  }
              }
              return QVariant();
          }
      
          Q_INVOKABLE void switchRole()
          {
              m_roleSwitch = !m_roleSwitch;
              emit dataChanged(index(SWITCHABLE_ROW, 0), index(SWITCHABLE_ROW, 0)); // Signal change for all roles
          }
      
      private:
          bool m_roleSwitch = false;
          static constexpr int SWITCHABLE_ROW = 2;
      };
      
      // Main.qml
      ApplicationWindow {
          width: 320
          height: 480
          visible: true
      
          header: Button {
              text: "Switch Role"
              onClicked: listModel.switchRole()
          }
      
          ListView {
              id: listView
              anchors.fill: parent
              model: MyListModel { id: listModel }
      
              delegate: DelegateChooser {
                  role: "statusTip"
                  DelegateChoice {
                      roleValue: "A"
                      Label {
                          required property string display
                          width: listView.width
                          height: 20
                          text: display
                          horizontalAlignment: Text.AlignHCenter
                          background: Rectangle { color: "cyan"; border.width: 1 }
                      }
                  }
                  DelegateChoice {
                      roleValue: "B"
                      Label {
                          required property string display
                          width: listView.width
                          height: 20
                          text: display
                          horizontalAlignment: Text.AlignHCenter
                          background: Rectangle { color: "orange"; border.width: 1 }
                      }
                  }
              }
          }
      }
      

       

      Steps to reproduce

      1. Build and run the attached project
      2. Click on the "Switch Role" button

       

      Expected outcomes after Step 2

      • The console log shows that data for both DisplayRole and StatusTipRole are queried.
      • Row 2's colour changes.

       

      Actual outcomes after Step 2

      • The console log shows that only data for DisplayRole is queried. StatusTipRole is not queried.
      • Row 2's colour does not change.

       

      Workarounds
      In the switchRole() function, instead of emitting the dataChanged() signal...

      • Wrap the operation with beginResetModel()/endResetModel(). OR,
      • Pretend that the affected row was removed and then re-added:
      beginRemoveRows({}, SWITCHABLE_ROW, SWITCHABLE_ROW);
      endRemoveRows();
      beginInsertRows({}, SWITCHABLE_ROW, SWITCHABLE_ROW);
      m_roleSwitch = !m_roleSwitch;
      endInsertRows();
      

      Attachments

        Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              santhoshkumar Santhosh Kumar Selvaraj
              skoh-qt Sze Howe Koh
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes