QAbstractProxyModel is not updated by dataChanged () signal

Here's mine setData

in the original model:

bool TreeModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
    if (!index.isValid() || role != Qt::EditRole)
        return false;

    TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
    item->setData(index.column(), value);
    emit dataChanged(index, index);

    return true;
}

      

I have hooked up a signal dataChanged

from the original model to dataChanged

the proxy model signal, but a table view that shows the proxy model is updated only if I click on it. What could be wrong in this situation? Do I have to emit the dataChanged

signal manually somehow in the proxy model?

Model data:

QVariant TreeModel::data(const QModelIndex& index, int role) const
{
    if (!index.isValid() || role != Qt::DisplayRole)
        return {};

    TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
    return item->dataAt(index.column());
}

      

And from TreeItem:

QVariant TreeItem::dataAt(int n) const
{
    if (n < m_data.size())
        return m_data[n];
    else
        return {};
}

      

Update: I assumed that the proxy model should be used mapFromSource

for the indexes that came from TreeModel::dataChanged

, but it seems that the proxy doesn't call mapFromSource

, so I don't understand how the update happens.

Also the same behavior when I try to edit a tree item via the proxy model - the original model does not update it. However, in this case, I can set the data in the proxy using the original model:

bool ProxyModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
//    if (!index.isValid() || role != Qt::EditRole)
//        return false;

//    TreeItem* item = static_cast<TreeItem*>(mapToSource(index).internalPointer());
//    item->setData(index.column(), value);
//    emit dataChanged(index, index);

//    return true;

    return sourceModel()->setData(mapToSource(index), value, role);
}

      

UPDATE: Finally, it seems like I almost figured it out. The KDE KDescendantsProxyModel model emits the dataChanged

signal itself, so I also created a slot onSourceDataChanged

and connected it to the source signal dataChanged

(now it only updates the first index):

void ProxyModel::onSourceDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight,
                                     const QVector<int>& roleNames)
{
    auto index = mapFromSource(topLeft);
    emit dataChanged(index, index);
}

      

The only question is: is it right or is something wrong?

+3


source to share


1 answer


I have connected signal dataChanged

from original model to dataChanged

proxy mode signal

You cannot re-radiate the signal of the original model, as this signal is indexed to the wrong model. Remember the contract dataChanged

: the index it emits is a valid index for the model the signal is coming from. However, you are emitting an index that is not valid for your proxy model.



You need to wire the original signal to a slot or functor, which then maps the index to the proxy index and emits that.

+1


source







All Articles