2
votes

I have a QML TreeView like this:

  TreeView
  {
    id: treeview
    model: myModel
    anchors.fill: parent
    alternatingRowColors: false
    headerVisible: false

    TableViewColumn
    {
      title: "Name"
      role: "name"
      delegate: Text
      {
      text: styleData.value
      }
    }

However, when I emit dataChanged from a custom method in C++, nothing is updated:

void MyModel::NameChanged()
{
  // beginResetModel(); <=== Works
  // endResetModel();

  // emit dataChanged(QModelIndex(), QModelIndex()); // Does not work

  auto topLeftIndex = createIndex(0, 0, m_root.get());
  auto bottomRightIndex = createIndex(rowCount(), columnCount(), m_root.get());
  (( emit dataChanged(topLeftIndex, bottomRightIndex);  // Does not work.
  emit dataChanged(topLeftIndex, topLeftIndex);  // Does not work.
}

In QML, text is bound to styleData.value and I am not setting text anywhere else. Also, dataChanged is not redefined elsewhere. So I am sure I am really emitting QAbstractItemModel::dataChanged(...).

Any idea what I am doing wrong?

My index method:

QModelIndex index(int row, int column, const QModelIndex &parentIdx) const
{
  if (hasIndex(row, column, parentIdx) == false)
  {
    return QModelIndex();
  }

  auto parentItem = m_root.get();
  if (parentIdx.isValid() == true)
  {
    parentItem = static_cast<ModelItem *>(parentIdx.internalPointer());
  }

  auto childItem = parentItem->GetChild(row);
  auto childName = childItem->GetName().toStdString();
  if (childItem)
  {
    auto index = createIndex(row, column, childItem.get());
    return index;
  }
  else
  {
    return QModelIndex();
  }
}

My parent method:

QModelIndex parent(const QModelIndex &childIndex) const
{
  if (childIndex.isValid() == false)
  {
    return QModelIndex();
  }

  auto childItem = static_cast<ModelItem*>(childIndex.internalPointer());
  auto parentItem = childItem->GetParent();

  if (parentItem.expired() == true)
  {
    return QModelIndex();
  }

  auto pItem = parentItem.lock();
  if (pItem == nullptr)
  {
    return QModelIndex();
  }

  auto parentIndex = createIndex(pItem->GetRow(), 0, pItem.get());
  return parentIndex;
}

UPDATE: if I use my model in C++ using a QTreeView, then it works.

1
You need to provide valid indexes of which data changed.Hayt
@Hayt: are you sure about this? Because I read that if we pass invalid indices, then it will update the entire model.Korchkidu
the documentation says nothing about this: doc.qt.io/qt-5/qabstractitemmodel.html#dataChangedHayt
This question is still highly relevant and there is no answer yet!IceFire

1 Answers

1
votes

While beginResetModel() and endResetModel() will invalidate the whole view, dataChanged() only invalidates a range you give it.

If you know what value changed you can use it like

 emit dataChanged(createIndex(row,col),createIndex(row,col));

or when multiple lines/cells change the second parameter is the "last" index which changed.