QAbstractProxyModel 不更新 dataChanged() 信号

qlo*_*loq 6 c++ qt

这是我setData的源模型:

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;
}
Run Code Online (Sandbox Code Playgroud)

我将dataChanged信号从源模型连接到dataChanged代理模型的信号,但显示代理模型的表视图只有在我点击它时才会更新。在这种情况下会出现什么问题?我应该以某种方式dataChanged在代理模型中手动发出信号吗?

来自模型的数据:

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());
}
Run Code Online (Sandbox Code Playgroud)

来自 TreeItem:

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

更新:我认为代理模型应该用于mapFromSource来自的索引,TreeModel::dataChanged但似乎代理没有调用mapFromSource,所以我不明白更新是如何发生的。

当我尝试通过代理模型编辑树项时也有相同的行为 - 源模型不会更新它的视图。但是在这种情况下,我可以使用源模型在代理中设置数据:

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);
}
Run Code Online (Sandbox Code Playgroud)

更新:最后,我似乎快要明白了。KDE 的 KDescendantsProxyModel 模型dataChanged本身发出信号,所以我还创建了onSourceDataChanged插槽并将其连接到源的dataChanged信号(它现在只更新第一个索引):

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

唯一的问题是:这是正确的方法还是我做错了什么?

Rei*_*ica 6

我将dataChanged源模型的信号连接到dataChanged代理模式的信号

您无法重新发出源模型的信号,因为该信号具有错误模型的索引。记住dataChanged的契约:它发出的索引是信号来源模型的有效索引。然而,您发出的索引在您的代理模型上无效。

您需要将源信号连接到一个槽或函子,然后将索引映射到代理的索引并发出它。