Undo/Redo for Qt Tree Model
Undo/Redo for Qt Tree Model
Abstract. Qt contains a set of item view classes that use a model/view architecture to manage the relationship between data and the way it is presented to the user. The separation of functionality introduced by this architecture gives developers greater flexibility to customize the presentation of items, and provides a standard model interface to allow a wide range of data sources to be used with existing item views. Model 3D aided design software such as AVEVA Plant/PDMS, Marine use the architecture to manage the design data source. The article demonstrate the Undo/Redo on the Qt Tree model.
Key Words. Model/View, MVC pattern, Undo/Redo, Tree Model
1. Introduction
现 代稍微大型一点的软件,要处理的数据量通常会比较大。这时就需要有一个唯一的数据源,且会对这个数据源中的数据进行增、删、改的操作。如果没有统一的数据 源,数据会随意地被创建和删除,且创建和删除的用户界面也不统一,不利于软件管理。基于唯一的数据源,并在这个基础上提供统一的增删改接口,不仅有利于软 件数据管理,还有利于事务的处理,即Undo/Redo功能。若引入脚本语言,如Tcl或Python,甚至可实现脚本命令对数据的操作,为程序增加二次 开发功能。
![]()
Figure 1. AVEVA Plant/PDMS Software
如 上图1所示为英国剑桥大学CADCENTRE出品的AVEVA Plant/PDMS软件。PDMS使用了统一的数据源,左边的导航树及右边的三维模型都是这个数据源的一种展示方式,可以在导航树上创建及删除数据;也 可以在三维视图中进行交互,方便地创建及修改模型。这种方式与GoF描述的Observer观察者模式相似,即:
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
对应上面的软件,即对于唯一的数据源这个对象,导航树及三维视图都依赖于他。当数据源这个对象中有数据的增删改时,导航树及三维视图都会得到通知并自动更新了。
图1右下角的CommandWindow中可以输入命令,即PML,也可以对数据源进行修改。引入Observer模式,即可实现这些功能。
Qt 中包含了一系列的Model/View类,这些类都是基于MVC架构的,这种将数据与视图分开的处理,使同一个数据源可以不同的视图中进行展示,且不需要 修改数据源的结构。Qt中基于Command命令模式实现了一个Undo/Redo的框架,将Undo/Redo框架应用于Model/View的类,即 可得到与AVEVA Plant/PDMS中类似的功能。
本文主要对Qt中的model/view及undo/redo框架进行介绍,及如何将Undo/Redo框架应用到model/view中去,实现对以层次方式组织数据的树模型进行undo/redo,进而实现一个三维CAD工厂设计的原型。
2.Tree Model
软件中使用层次方式来组织数据,可护展性好。如OpenCASCADE中的OCAF框架的数据也是树形方式组织:
![]()
Figure 2.1 OpenCASCADE OCAF data tree
每 个Label中可以存放属性,还包含子Label,这样就提供了一个通用的程序框架,灵活使用,可以用一种统一的方式来存放数据。有一个缺点就是每个 Label中的属性类型只能包含一种,这种方式相对于AVEVA的自定义属性UDA来说,就显得很不方便了,需要提前对数据的存储进行规划,扩展起来稍有 不便。
AVEVA中对每个数据Element都提供了自定义属性(User Definable Attribute),每种类型的属性(数值型、字符串型等)都可以包含任意数量,没有限制。所以可扩展性更好。
Qt 中基于MVC模式的model/view架构提供了一些预定义的模型及视图,如列表模型及对应的视图,树模型及树视图等。在model/view架构中, 为model提供了统一的访问数据的方式,即Model Index。对于列表model,通过QModelIndex::row()即可访问。对于表格model,需要QModelIndex::row()和 QModelIndex::column()。对于树model,除了上述两个函数,还需要提供QModelIndex::parent()来对父节点进 行访问。如下图2.2所示:
![]()
Figure 2.2 Schematic view of Qt’s Models
若需要对列表及表格model应用Undo框架,还是很方便的,只要记住数据操作的对应的row或row及column即可。若要对树形model进行undo,原理也是一样的,即在redo中生成数据在undo中恢复数据。
3.Key Points
将undo框架与model/view结合有两种方式:
v 通过在undo/redo命令中调用QAbstractItemModel的API来改变底层数据;
v 自定义model使其创建命令并推送到undo栈Stack中去;
第 一种方式看起来要容易些,且可与任意model结合。The first approach seems simpler, as it works with any model and gives the undo framework total control --- you can create as many different types of commands as you want and each of them can call a number of methods from the model API in their undo() and redo() routines.
当model中有delete操作时,会将index内部的数据删除。对于这种情况,需要注意。Qt给出了两个解决办法:
There are two things to remember. The first is that, if you delete items, rows or columns, you should save the data of all the items getting deleted(including children) somewhere so that you can later revert the deletion. The second is that it would be nice to be able to set meaningful descriptions of commands pushed on the stack. To do that you can provide methods in the model, that are called each time a command is pushed onto the stack, which should each return a description based on the parameters of the command being executed.
基于上述思想,实现了Tree Model与Undo Framework结合的一个小例子:
![]()
Figure 3. Undo/Redo and Tree Model
4.Conclusion
Qt中基于Command命令模式的Undo框架,需要对数据操作及恢复仔细考量。尤其对于有删除数据的操作,若以QModelIndex作为参考依据,则会出错。对于此Qt提供了两个解决思路。
基于Qt的model/view及undo框架,也可以方便实现OpenCASCADE中的OCAF框架许多类似的功能,且Qt的代码可读性更高。若要快速开发程序,可以考虑使用Qt的model/view框架。
感谢晓天的建议。
5. References
1. Using Undo/Redo with Item Views. http://doc.qt.digia.com/qq/qq25-undo.html
2. OpenCASCADE. OCAF User’s Guide. 2014
3. GoF. Design Patterns-Element of Reusable Object-Oriented Software. 1995
PDF Version: Undo/Redo for Qt Tree Model
Undo/Redo for Qt Tree Model的更多相关文章
- Qt自定义model
前面我们说了Qt提供的几个预定义model.但是,面对变化万千的需求,那几个model是远远不能满足我们的需要的.另外,对于Qt这种框架来说,model的选择首先要能满足绝大多数功能的需要,这就是说, ...
- Qt的Model/View Framework解析(数据是从真正的“肉(raw)”里取得,Model提供肉,所以读写文件、操作数据库、网络通讯等一系列与数据打交道的工作就在model中做了)
最近在看Qt的Model/View Framework,在网上搜了搜,好像中文的除了几篇翻译没有什么有价值的文章.E文的除了Qt的官方介绍,其它文章也很少.看到一个老外在blog中写道Model/Vi ...
- MySQL,MariaDB:Undo | Redo [转]
本文是介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版 ...
- iOS: 为画板App增加 Undo/Redo(撤销/重做)操作
这个随笔的内容以上一个随笔为基础,(在iOS中实现一个简单的画板),上一个随笔实现了一个简单的画板: 今天我们要为这个画板增加Undo/Redo操作,当画错了一笔,可以撤销它,或者撤销之后后悔了, ...
- [转]MySQL日志——Undo | Redo
本文是介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版 ...
- 从Undo,Redo谈命令模式
一般的应用软件中,通常会提供Redo和Undo的操作,比如Paint.NET中的动作面板,Word中的撤销重做,一般我们按Ctrl-Z即可回退到上次操作. 要实现上面的这一功能,最直观的想法就是,我们 ...
- 【转载】MySQL 日志 undo | redo
本文是介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版 ...
- MySQL InnoDB存储引擎undo redo解析
本文介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo Log Undo Log 为了实现事务原子,在MySQL数据库InnoDB存储引擎,还使用Undo Log(简称:MVCC ...
- MySQL日志Undo&Redo
00 – Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版本并发控制(简称:MVCC). - 事务的原子性(Atomi ...
随机推荐
- [转] 前后端分离开发模式的 mock 平台预研
引入 mock(模拟): 是在项目测试中,对项目外部或不容易获取的对象/接口,用一个虚拟的对象/接口来模拟,以便测试. 背景 前后端分离 前后端仅仅通过异步接口(AJAX/JSONP)来编程 前后端都 ...
- swift初体验
swift是一门类型安全的语言,同样也是基于c语言 那么c语言的一些类型也是实用的,不同的是:swift声明变量和常量是不一样的 let:用来修饰常量:var用来修饰变量 e.g: let num=1 ...
- 【ORACLE】MD5加密
今天乌干达充值卡入库时,发现有资源已经存在的异常, 异常原因经过核实是由于卡资源密码在库中已经存在, 为进一步查找存在的原因, 因此需要对导入文件密码的MD5 加密, 通过MD5加密后的字符串 ...
- Excel转Html
项目结构: 这是一个maven项目,主函数在Client类里面 当运行程序的后,控制台情况: 当我们刷新了test.html文件后,用浏览器打开效果: 说一下这个过程的设计思路: 1.读取excel文 ...
- C#详解format函数,各种格式化
一.String Format for Double Digits after decimal point This example formats double to string with fix ...
- Xcode8中处理打印日志的配置
Xcode8中处理打印日志的配置
- 解决Ionic的ion-slide-box 2条数据渲染问题
当slider数据列表是动态获取时,如果数据结果只有2条数据时,slider列表会多复制俩个,通过下面的slideChange方法做个判断可以解决这个bug 第一步:添加slideChande方法 & ...
- Filter 数组过滤函数精解示例
'************************************************************************* '**模 块 名:Filter 数组过滤函数精解示 ...
- 初识Python
Python 简介 Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言. Python 的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号,它具有 ...
- Mpale 在汽车底盘悬架系统公差分析应用
汽车底盘的作用是接受发动机的动力,使车轮转动,并保证汽车按驾驶员的操纵正常行驶.底盘包括传动系统.行驶系统.转向系统和制动系统这四大部分,通常,这四大系统也简称为传动系.行驶系.转向系和制动系.悬架是 ...