首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >sourceModel()->createIndex()在QAbstractProxyModel子类中

sourceModel()->createIndex()在QAbstractProxyModel子类中
EN

Stack Overflow用户
提问于 2014-05-27 18:10:43
回答 3查看 1.8K关注 0票数 3

我正在尝试创建一个代理模型,该模型动态地映射来自源模型.的项。

在实现QIdentityProxyModel之后,我发现实际上不可能通过检查4个核心功能来复制它:

代码语言:javascript
复制
mapFromSource()
mapToSource()
index()
parent()

考虑一下基于QIdentityProxyModel的这一点

mapFromSource()

代码语言:javascript
复制
QModelIndex ProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
{
    if(sourceIndex.isValid())
        return createIndex(sourceIndex.row(), sourceIndex.column(), sourceIndex.internalPointer());
    else
        return QModelIndex();
}

mapToSource()

代码语言:javascript
复制
QModelIndex ProxyModel::mapToSource(const QModelIndex &proxyIndex) const
{
    if(proxyIndex.isValid())
        return sourceModel()->createIndex(proxyIndex.row(), proxyIndex.column(), proxyIndex.internalPointer());
    else
        return QModelIndex();
}

索引()

代码语言:javascript
复制
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);
}

家长()

代码语言:javascript
复制
QModelIndex ProxyModel::parent(const QModelIndex &index) const
{
    const QModelIndex sourceIndex = mapToSource(index);
    const QModelIndex sourceParent = sourceIndex.parent();
    return mapFromSource(sourceParent);
}

THE ISSUE

问题在mapToSource()线上

代码语言:javascript
复制
return sourceModel()->createIndex(proxyIndex.row(), proxyIndex.column(), proxyIndex.internalPointer());

QAbstractItemModel::createIndex是受保护的函数,除非调用者声明为朋友,否则不能使用。如果不直接修改QAbstractItemModel类,这显然不是一个选项。唯一的选择是使用常规的QAbstractItemModel::index,但这需要以QModelIndex的形式作为参数之一。然而,这样做:

代码语言:javascript
复制
return sourceModel()->index(proxyIndex.row(), proxyIndex.column(), proxyIndex.parent());

由于parent()函数依赖于mapToSource() 而导致无限循环,反之亦然,现在是

显示举个例子的替代方法依赖于在上述函数中查询的QPersistentModelIndex对象的存储映射。这种办法虽然可行,但有几个缺点:

  • 它需要大量额外的内存来存储索引。
  • 所有持久性索引都需要在每次结构变化时由源模型更新(而不是使用动态模型进行按需索引查找)。
  • 当迭代映射的kyes时,对映射的查询可能很慢(这可以通过相反的两个相同的映射来补救,而牺牲更多的内存)

因此,我提出以下问题:

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

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

谢谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-05-29 11:51:56

也许这是一个迟来的答复,但我只是面临同样的问题。我通过将sourceModel()转换到我的模型来解决这个问题,同时我宣布我的ProxyModel是我的朋友。

这是我的mapToSource定义:

代码语言:javascript
复制
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());
}

朋友宣言:

代码语言:javascript
复制
class Model : public QAbstractTableModel
{
   Q_OBJECT

   friend class ProxyModel;
   ...
};

我理解您对于只使用QAbstractItemModel接口的担忧(相信我,我也使用过),但是让我们面对它-- ProxyModel只能与我的Model一起使用,而不能用于其他任何东西(至少根据我的实现)。所以我看不出这样的“友谊”有什么不好的地方。至于UB,这里也不应该有任何问题,因为如果提供了除我的模型之外的其他模型,qobject_cast将返回0

票数 2
EN

Stack Overflow用户

发布于 2016-10-28 09:07:39

在前面回答的基础上,我想添加一些替代的方法。

首先,时间历史上最丑陋的黑客在大多数编译中都是安全的:

代码语言:javascript
复制
class HackyDummy : public QAbstractItemModel
{
   friend class ProxyModel;
};

QModelIndex ProxyModel::createSourceIndex(int r, int c, void *i) {
    return ((HackyDummy*) sourceModel())->createIndex(r,c,i);
}

现在,当然,这是一个可怕的,可怕的黑客。它也不会在某些编译器中编译,因为C++规范对于从子类朋友访问父类、私有和受保护的方法不太清楚(或者至少被一些人误解了)。这使我们找到了一个更好的计划。但首先,有一点细节: QIdentityProxyModel几乎做到了这一点。QIdentityModel自己的mapToSource/mapFromSource是公共的,可重新实现的,它的createIndex也是如此。因此,可以使用一种方法执行内部/私有QIdentityProxyModel,通过访问QIdentityProxyModel本身包含的哈克,从行、列和内部指针创建我们的小源索引。

编辑:打字

票数 1
EN

Stack Overflow用户

发布于 2017-01-30 00:15:24

我只是继承了QIdentityProxyModel,并在我的mapToSourceMethod中使用了它的mapToSource方法。

代码语言:javascript
复制
QModelIndex PropertyModel::mapToSource(const QModelIndex & proxyIndex) const
{
    if(hasNoModel())
    {
        return QModelIndex();
    }

    QModelIndex remapped = createIndex( /* transform proxyIndex here */ );

    return QIdentityProxyModel::mapToSource(remapped);
}

这意味着,如果您更改源模型类型并忘记更新强制转换,则不会出现可能导致代码崩溃的强制转换。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23896182

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档