我正在尝试创建一个代理模型,以动态映射源模型中的项目。

打算从那里执行QIdentityProxyModel之后,我发现实际上不可能通过检查4个核心功能来复制它:

mapFromSource()
mapToSource()
index()
parent()

考虑基于QIdentityProxyModel:

mapFromSource()
QModelIndex ProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
{
    if(sourceIndex.isValid())
        return createIndex(sourceIndex.row(), sourceIndex.column(), sourceIndex.internalPointer());
    else
        return QModelIndex();
}

mapToSource()
QModelIndex ProxyModel::mapToSource(const QModelIndex &proxyIndex) const
{
    if(proxyIndex.isValid())
        return sourceModel()->createIndex(proxyIndex.row(), proxyIndex.column(), proxyIndex.internalPointer());
    else
        return QModelIndex();
}

指数()
QModelIndex ProxyModel::index(int row, int column, const QModelIndex &parent) const
{
    const QModelIndex sourceParent = mapToSource(parent);
    const QModelIndex sourceIndex = sourceModel()->index(row, column, sourceParent);
    return mapFromSource(sourceIndex);
}

parent()
QModelIndex ProxyModel::parent(const QModelIndex &index) const
{
    const QModelIndex sourceIndex = mapToSource(index);
    const QModelIndex sourceParent = sourceIndex.parent();
    return mapFromSource(sourceParent);
}

发行

问题出在mapToSource()
return sourceModel()->createIndex(proxyIndex.row(), proxyIndex.column(), proxyIndex.internalPointer());
QAbstractItemModel::createIndex是 protected 函数,除非调用者被声明为好友,否则无法使用。如果不直接修改QAbstractItemModel类,那显然不是一个选择。唯一的选择是使用常规QAbstractItemModel::index,但这需要QModelIndex形式的父级作为参数之一。但是这样做:
return sourceModel()->index(proxyIndex.row(), proxyIndex.column(), proxyIndex.parent());

由于parent()函数依赖mapToSource() ,而现在变成,则导致无限循环。

for example here显示的另一种方法依赖于上述函数中查询的QPersistentModelIndex对象的存储映射。这种方法虽然可行,但有几个缺点:
  • 它需要大量额外的内存来存储索引
  • 每次结构更改时,源模型都需要更新所有持久索引(与动态模型中的按需索引查找相反)
  • 遍历 map 的kyes时,对 map 的查询可能会很慢(可以通过反向制作两个相同的 map 以节省更多内存的方式来补救)

    因此,我的问题是:

    是否有另一种方法可以动态处理分层代理模型,而不依赖于createIndex()且不陷入函数调用的无限循环?

    实际上是否有必要相对于源结构在存储中创建和维护代理模型的结构,还是有办法创建动态代理模型?

    谢谢!

    最佳答案

    也许这是一个较晚的答复,但是我也遇到了同样的问题。我通过将sourceModel()转换为模型来解决它,同时我将ProxyModel声明为 friend 。

    这是我的mapToSource定义:

    QModelIndex ProxyModel::mapToSource(const QModelIndex& proxyIndex) const
    {
       Model* pModel = qobject_cast<Model*>(sourceModel());
       if (!pModel || !proxyIndex.isValid()) return QModelIndex();
    
       ...
       return pModel->createIndex(row, col, proxyIndex.internalPointer());
    }
    

    和 friend 声明:
    class Model : public QAbstractTableModel
    {
       Q_OBJECT
    
       friend class ProxyModel;
       ...
    };
    

    我了解您对仅使用QAbstractItemModel接口(interface)的担心(相信我,我有相同的想法),但是让我们面对现实吧ProxyModel只能与我的Model一起使用,而不能与其他任何方式一起使用(至少根据我的实现)。因此,在这样的“友谊”中我看不到任何不好的地方。至于UB,这里也不应该有任何问题,因为如果提供了除我以外的其他模型,则qobject_cast将返回0

    关于c++ - QAbstractProxyModel子类中的sourceModel()-> createIndex(),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23896182/

  • 10-09 22:14