sourceModel()->createIndex() in QAbstractProxyModel sub-class
sourceModel()->createIndex() in QAbstractProxyModel sub-class
我正在尝试创建一个代理模型,从源模型动态映射项目。
随着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);
}
父()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
是保护函数,除非将调用方声明为友方,否则不能使用。如果不直接修改QAbstractItemModel
类,这显然是不可能的。唯一的选择是使用常规的QAbstractItemModel::index
,但这需要QModelIndex
形式的parent作为参数之一。但是这样做:
return sourceModel()->index(proxyIndex.row(), proxyIndex.column(), proxyIndex.parent());
导致无限循环,因为parent()
函数依赖于mapToSource()
,反之亦然,现在。
此处显示的替代方法依赖于在上述函数中查询的QPersistentModelIndex
对象的存储映射。这种方法虽然可行,但有几个缺点:
- 需要大量的额外内存来存储索引
- 所有持久索引需要在每次结构更改时由源模型更新(与动态模型的随需应变索引查找相反)
- 当迭代map的键时,对map的查询可能很慢(这可以通过反向创建两个相同的map来弥补,但代价是更多的内存)
所以我的问题是:
是否有另一种方法来动态处理分层代理模型,而不依赖于createIndex()和不运行到函数调用的无限循环?
实际上是否有必要在存储中创建和维护代理模型的结构-à-vis源结构,或者是否有一种方法可以创建动态代理模型?
谢谢!
也许这是一个迟来的回复,但我刚刚遇到了同样的问题。我通过将sourceModel()投射到我的模型来解决这个问题,同时我将我的ProxyModel
声明为朋友。
这是我的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());
}
和友元声明:
class Model : public QAbstractTableModel
{
Q_OBJECT
friend class ProxyModel;
...
};
我理解你对只使用QAbstractItemModel接口的担忧(相信我,我有相同的),但让我们面对它,ProxyModel
只能与我的Model
一起使用,而不是其他(至少根据我的实现)。因此,我不认为这样的"友谊"有什么不好。至于UB,这里也不应该有任何问题,因为如果提供了除我以外的其他模型,qobject_cast
将返回0
。
在前面回答的基础上,我想添加一些替代方法
首先,历史上最丑陋的hack本身在大多数编译器上是安全的:
class HackyDummy : public QAbstractItemModel
{
friend class ProxyModel;
};
QModelIndex ProxyModel::createSourceIndex(int r, int c, void *i) {
return ((HackyDummy*) sourceModel())->createIndex(r,c,i);
}
当然,这是一个非常非常糟糕的hack。它也不能在一些编译器中编译,因为c++规范不是很清楚(或者至少被一些人误解了)访问父类private和子类友类的protected方法。这使我们有了一个更好的计划。但首先,有一点细节:QIdentityProxyModel(几乎)做到了这一点。QIdentityModel自己的mapToSource/mapFromSource是公共的和可重新实现的,它的createIndex也是。因此,可以使用一个内部/私有的QIdentityProxyModel方法,通过访问QIdentityProxyModel本身内部包含的hack,从行、列和内部指针创建我们的小源索引。
编辑:错误
我刚刚继承了QIdentityProxyModel,并在我的maptosourcememethod中使用了它的mapToSource方法。
QModelIndex PropertyModel::mapToSource(const QModelIndex & proxyIndex) const
{
if(hasNoModel())
{
return QModelIndex();
}
QModelIndex remapped = createIndex( /* transform proxyIndex here */ );
return QIdentityProxyModel::mapToSource(remapped);
}
这意味着如果您更改源模型类型而忘记更新您的强制转换,您不会以可能导致代码崩溃的强制转换告终。
- netcat command in c++
- Difference in displaying cv2 Mat
- C++ MFC Libraries in Travis CI
- 如何在OpenSSL中从configuration.h.in获取configuration.h
- 创建具有 new in 函数和"this is nullptr"异常的对象
- IN, OUT, INOUT Parameters
- 应用程序崩溃并显示"symbol _ZdlPvm, version Qt_5 not defined in file libQt5Core.so.5 with link time reference"
- 有人安装"IITB Simplecpp in mac"吗?
- 从 C 样式字符串中删除子字符串 "in place" 在C++代码中
- 如何修复"error: ‘_1’ was not declared in this scope"?
- Softmax Implementation in C++
- 将 out/in out 参数与 if/switch 的 init 语句一起使用
- IF-nesting in c++
- Gurobi GRBModel and GRBmodel in C++
- Tensorflow Hub in C++
- Centos7 g++ "to_string is not in a member of std"
- InitializeCriticalSectionEx Not Located In KERNEL32.Dll
- 将 lambda 表达式传递给 std::function in C++
- @CPPFLAGS@在 Makefile.in 中意味着什么?
- std::async from std::async in windows xp