QAbstractProxyModel没有更新dataChanged()信号

时间:2017-05-18 08:09:28

标签: 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;
}

我将来自源模型的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());
}

来自TreeItem:

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

更新: 我认为代理模型应该对来自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);
}

更新: 最后,似乎我几乎得到了它。 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);
}

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

1 个答案:

答案 0 :(得分:1)

  

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

您无法重新发射源模型的信号,因为该信号具有错误模型的索引。记住dataChanged的合同:它发出的索引是信号来自模型的有效索引。但是,您发布的索引在代理模型上无效。

您需要将源信号连接到插槽或仿函数,然后将索引映射到代理的索引并发出该信号。