Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ sourceModel()->;QAbstractProxyModel子类中的createIndex()_C++_Qt_Model - Fatal编程技术网

C++ sourceModel()->;QAbstractProxyModel子类中的createIndex()

C++ sourceModel()->;QAbstractProxyModel子类中的createIndex(),c++,qt,model,C++,Qt,Model,我正在尝试创建一个代理模型,用于从源模型动态映射项目。 在实现了QIdentityProxyModel之后,我发现实际上不可能通过检查4个核心功能来复制它: mapFromSource() mapToSource() index() parent() 基于QIdentityProxyModel考虑这一点: mapFromSource() mapToSource() 索引() 父项() 问题 问题在于mapToSource()line return sourceModel()->creat

我正在尝试创建一个代理模型,用于从源模型动态映射项目。

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

mapFromSource()
mapToSource()
index()
parent()
基于
QIdentityProxyModel
考虑这一点:

mapFromSource()

mapToSource()

索引()

父项()

问题

问题在于
mapToSource()
line

return sourceModel()->createIndex(proxyIndex.row(), proxyIndex.column(), proxyIndex.internalPointer());
qabstractemmodel::createIndex
是受保护的函数,除非调用方声明为朋友,否则不能使用该函数。如果不直接修改
qabstractemmodel
类,这显然不是一个选项。唯一的替代方法是使用常规的
qabstractemmodel::index
,但这需要将
QModelIndex
形式的父项作为参数之一。然而,这样做:

return sourceModel()->index(proxyIndex.row(), proxyIndex.column(), proxyIndex.parent());
由于
parent()
函数依赖于
mapToSource()
这一事实,导致无限循环,反之亦然

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

  • 它需要大量额外的内存来存储索引
  • 每次结构更改时,源模型都需要更新所有持久索引(与动态模型的按需索引查找相反)
  • 当迭代映射的kyes时,对映射的查询可能会很慢(这可以通过以牺牲更多内存为代价反向生成两个相同的映射来解决)
因此,我的问题是:

有没有其他方法可以在不依赖createIndex()和不运行无限函数调用循环的情况下动态处理分层代理模型

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


谢谢

也许这是一个迟到的答复,但我刚刚遇到了同样的问题。我通过将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());
}

我理解您对只使用QabstracteModel接口的担忧(相信我,我也有过同样的担心),但让我们面对现实,
ProxyModel
只能用于我的
模型,而不能用于其他任何东西(至少根据我的实现)。因此,我看不出像这样的“友谊”有什么不好的地方。至于UB,这里也不应该有任何问题,因为如果提供了除我之外的其他模型,
qobject\u cast
将返回
0

基于前面的答案,我想添加一些替代方法

首先,时间历史上最丑陋的黑客在大多数情况下都是安全的:

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内部包含的hack,使用一种方法来创建内部/私有QIdentityProxyModel,从行、列和内部指针创建我们的小源索引


编辑:输入错误

我刚从QIdentityProxyModel继承,并在我的mapToSource方法中使用了它的mapToSource方法

QModelIndex PropertyModel::mapToSource(const QModelIndex & proxyIndex) const
{
    if(hasNoModel())
    {
        return QModelIndex();
    }

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

    return QIdentityProxyModel::mapToSource(remapped);
}

这意味着您不会因为更改源模型类型而忘记更新cast而导致代码崩溃。

我面临着同样的问题,答案显然是创建了一个过于复杂的代码,使用
QPersistentIndex
,就像您所说的,这显然是不值得花费时间的。显然,您所能做的最好的事情就是绑定到行添加和此类事件,并将所需的持久索引存储在一个高效的查找结构中。您能展示相关的代码吗?我不认为将对象强制转换为不完全正确的类型是一个好主意。我想象一个人可以使用一个包装器类,并且只在ProxyModel中接受它,但是这会破坏Qt接口。或者你把它扔进这样一个包装里?我认为从技术上讲,这应该是可行的,但对我来说,这绝对是一种UB的味道,即使目标只是暴露一些你知道的东西。不管怎样,我很好奇你的解决方案@复活我也是,但我认为这毕竟是公平的交换。我今天晚些时候一回到家就会发布代码。@复活我发布了相关代码和我的解释。我注意到你来自布拉格。几天前我们刚从布拉格度假回来,谢谢!我觉得很好。我期待一些疯狂的事情,比如将任何sourceModel强制转换为您的朋友声明的包装器模型(理论上也可以这样做,如果您只接触QabstracteModel方法,但可能不会,因为类的布局不同,所以指针偏移量会因为假设不同的布局而出错)。是的,布拉格很棒。希望您喜欢。:-)
return sourceModel()->index(proxyIndex.row(), proxyIndex.column(), proxyIndex.parent());
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;
   ...
};
class HackyDummy : public QAbstractItemModel
{
   friend class ProxyModel;
};

QModelIndex ProxyModel::createSourceIndex(int r, int c, void *i) {
    return ((HackyDummy*) sourceModel())->createIndex(r,c,i);
}
QModelIndex PropertyModel::mapToSource(const QModelIndex & proxyIndex) const
{
    if(hasNoModel())
    {
        return QModelIndex();
    }

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

    return QIdentityProxyModel::mapToSource(remapped);
}