2

问候,

我一直在编写一些讨厌的代码来支持从我的模型中删除任意一组对象的撤消/重做。我觉得我做对了,因为所有其他的修改器(添加/复制粘贴)都是这个功能的子集。

代码比我需要的更糟糕,主要是因为改变模型的唯一方法是调用 beginInsertRows/beginRemoveRows 并删除一个范围内的行(一次只做 1 行,无需将“邻居”优化为单个打电话呢)

beginInsertRows/beginRemoveRows 的问题是删除一行可能会影响另一个 QModelIndex(例如,缓存在列表中的一个)。例如:

ParentObj
   ->ChildObj1
   ->ChildObj2
   ->ChildObj3

假设我选择 ChildObj1 和 ChildObj3 并删除它们,如果我先删除 ChildObj1,我已经更改了 ChildObj3 的 QModelIndex(行现在不同)。如果我删除父对象(但我已通过从对象列表中“修剪”子对象来解决此问题),则会出现类似问题。

以下是我考虑过解决此界面限制的方法,但我想在继续前进之前我会要求更好的方法:

  1. 移动“向后”,假设提供的 QModelIndices 列表是从上到下排序的,只是从下往上。这确实需要可靠的排序,并且排序可能是幼稚和缓慢的(也许有一种对 QModelIndexes 集合进行排序的聪明方法?或者 QItemSelectionModel 提供好的(有序)列表?)

  2. 每次删除/添加对象时更新其他 QModelIndeces(想不出非天真的解决方案,搜索列表,在需要的地方获取新的 QModelIndeces)

  3. 由于更新实际数据很容易,只需更新数据并重建模型即可。这看起来很奇怪,我可以想象它在处理大量数据时会变得很慢。

这些是我目前的想法。我现在正在研究选项 1。

问候,丹 O

4

2 回答 2

4

将 beginRemoveRows/endRemoveRows 等视为要求 QAbstractItemModel 基类为您修复持久模型索引的方法,而不仅仅是一种更新视图的方法,并且尽量不要在处理这些索引时混淆 QAbstractItemModel 基类。查看http://labs.trolltech.com/page/Projects/Itemview/Modeltest来练习你的模型,看看你是否让 QAbstractItemModel 基类满意。

如果您想将撤消/重做数据保留在模型之外,QPersistentModelIndex 没有帮助的地方。我构建了一个经过大量编辑的模型,我不想尝试将所有内容都保留在模型中。我将撤消/重做数据存储在撤消堆栈上。问题是,如果您编辑一个列,将该列的持久索引存储在撤消堆栈上,然后删除包含该列的行,则该列的持久索引将变为无效。

我所做的是同时保留一个持久模型索引和一个“历史”常规 QModelIndex。当需要撤消/重做时,我会检查持久索引是否无效。如果有,我将历史 QModelIndex 传递给我的模型的一个特殊方法,要求它根据行、列和 internalPointer 重新创建索引。由于我的所有编辑都在撤消堆栈上,当我备份到撤消堆栈上的该列编辑时,该行肯定在模型中。我在 internalPointer 中保留了足够的状态来重新创建原始索引。

于 2009-12-18T21:44:07.253 回答
1

我会考虑使用“全数据”模型和带有数据模型的过滤器代理模型。数据只会被添加到全数据模型中,永远不会被删除。这样,您可以使用对该模型的引用来存储您的撤消/重做信息。(我可以建议QPersistentModelIndex吗?)。您的数据模型还可以以某种方式跟踪应该显示的内容。然后过滤器模型将只返回应该在给定时间显示的项目的信息。

于 2009-11-12T18:24:32.633 回答