如何在QAbstractItemModel包装模型中转发信号



我打算创建自己的项目模型,该模型源自QAbstractItemModel。该模型不包含数据,但包装了一些数据存储库。该存储库在插入、删除、重命名等项目后发出信号。

每当存储库中发生变化时,我的项目模型都需要转发这些信号。

然而,存储库具有独立的信号,如void itemRemoved(int index);,而QAbstractItemModel具有受保护函数(和信号)的开始/结束对,如beginInsertRows()endInsertRows()

我该如何处理?例如,我可以将如下插槽连接到存储库的itemRemoved()信号:

void RepositoryItemRemoved(int i)
{
   beginInsertRows(QModelIndex(), i, i);
   endInsertRows();
}

基于上面的例子:在存储库中插入一行之后,连续调用beginInsertRows()/endInsertRows()是否有效?

我有过类似的场景,其中数据在不同的对象中,模型只是一个包装器,只有当数据集显示在视图中时才会创建。我在数据对象中使用了一个指向模型对象的指针,在插入操作中检查它是否为null,如果不为null,则通过它调用beginInsertRows()endInsertRows()。当然,由于这些都受到保护,因此必须将数据类声明为模型类的友元。

文档强调,在插入任何数据之前调用beginInsertRows()是很重要的:

在子类中重新实现insertRows()时,必须调用函数,然后将数据插入模型的底层数据存储。。。

否则,视图可能最终处于无效状态。

您应该使用视图进行测试,或者检查源代码中的实际实现。

我也遇到过类似的场景,只是在我的情况下,Qt模型对底层模型的包装更为字面:底层模型包含的数据比视图所需了解的数据多得多。因此,我让Qt模型包含每个底层模型的数据项的小块列表,供视图/委托处理。因此,处理底层模型更新的插槽看起来是这样的:

void RepositoryItemRemoved(int i)
{
    beginRemoveRows(QModelIndex(), i, i);
    removeModelItem(i);
    endRemoveRows();
}

这样的设计解决了视图无效状态的问题,尽管对于让Qt模型包含自己的项目列表意味着复制足够数量的数据的用例来说,这可能是不切实际的。

相关内容

  • 没有找到相关文章

最新更新