存储和编辑(GUI)类似目录的树结构的最优雅/安全/简单的解决方案?
我有一个稍微棘手的问题需要解决;想象一下:
我的一个应用程序需要大量使用脚本,因此我的想法是为用户提供一种编写脚本片段并将它们组织在类似目录的树结构中的方法。这很像带有子目录和源文件的源代码目录。
数据类/存储
我遇到的第一个问题是我需要找到一种好方法来存储整个树结构(在磁盘上,以及在运行时在应用程序中)。为此,我有以下想法:
- 使用 QObject 派生类,它可以使用 QObject 的父/子功能来表示树。这样,如果它们的父对象被删除,我就不必担心删除这些对象。
- 使用一个简单的类,其中可能包含子级的 QList(没有指针)和一些存储每个组/脚本的属性的属性。
- 使用方法 #2,但使用指针而不是静态对象 - 当我必须将树的组或一部分传递给函数等时,这将避免无用的复制。
- 使用 SQLite(或类似)数据库的实时后端,并且在运行时查询它。这将避免一次加载整个树并将其保存在 RAM 中。
- 在文件系统上使用平面文件和目录结构;尽管我认为这会带来不必要的麻烦,因为无法存储有关对象的元信息。
编辑器
我遇到的下一个问题是用户可能想要编辑整个树结构。他想要单击一个组或脚本,编辑脚本代码,并可能进行拖放操作。在树中放置目录和脚本;从而改变整个树的结构。
这会产生以下问题:
- 如果用户关闭编辑器,向他提供“您想保存更改吗?”可能是个好主意。对话。就像文本编辑器一样,您不小心在现有文档中输入了一些内容,但您退出了而不保存更改。 - 这需要我们编辑整个树的副本,并在需要时覆盖应用程序中的现有树。
- 允许拖放掉落可能会有问题...
- ...使用存储方法#1:当前不存在更改 QObject 子级顺序的好方法。在程序的其他部分可能访问对象的同时在运行时移动对象并不是一个好主意。
- ...使用存储方法 #2 会更容易,因为整个树都像单个值一样处理,并且没有我必须移动和重新设置父级的子项。复制树的一部分会自动复制所有子树,依此类推。不幸的是,这意味着大量的开销和灵活性的损失(我必须再次将整个树写入磁盘,因为我无法确定究竟发生了什么变化)。
当我想到更多事情时,我可能会稍微更新这个问题,但我真的很好奇其他人如何解决这个问题。任何建议和想法表示赞赏。 :)
I've got a slightly tricky problem to solve; imagine this:
One of my applications needs to make heavy use of scripting, so my idea was to provide the user a way to write script snippets and organize them in a directory-like tree structure. This is much like a source code directories with subdirectories and source files.
Data Classes/Storing
The first problem I come across is that I need to find a good way to store the whole tree structure (on the disk, and within the application at runtime). For this I had these ideas:
- Use a QObject derived class which can represent the tree using QObject's parent/child features. This way I don't have to worry about deleting those objects if they parents get deleted.
- Use a simple class which may contain a QList (without pointers) of children and a few properties which store the properties of each group/script.
- Use approach #2, but use pointers instead of static objects - this would avoid useless copying whenver I have to pass a group or part of a tree to a function, etc.
- Use a live backend to a SQLite (or similar) database, and query it at runtime. This would avoid loading the whole tree at once and keeping it in RAM.
- Use a flat file and directory structure on the file system; although I think this introduces more trouble than necessary because there is no way to store meta information about objects.
Editor
The next problem I come across is the fact that the user probably wants to edit the whole tree structure. He wants to click on a group or script, edit the script code and possibly Drag & Drop directories and scripts around within the tree; thus changing the structure of the whole tree on the way.
This raises the following problems:
- If the user closes the editor, it might be a good idea to provide him a "Do you want to save the changes?" dialog. Much like a text editor where you accidently typed something into an existing document, but you quit without saving the changes. - This would require that we edit a copy of the whole tree, and overwrite the existing tree within the application when needed.
- Allowing Drag & Drop could be problematic...
- ... with the storing approach #1: currently no good way exists to change the order of children of QObjects. Also moving objects around at runtime while other parts of the program might access them is not a good idea.
- ... this is easier with storing approach #2, since the whole tree is handled like a single value and there are no children I'd have to move and re-parent. Copying a part of the tree automatically copies all children and so on. Unfortunately this would mean a lot of overhead and loss in flexibility (I'd have to write the whole tree onto the disk again since I can't be sure what exactly changed).
I'll probably update this question a little when more things come to my mind, but I'm really curious how other people solve this problem. Any suggestions and ideas are appreciated. :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我建议您查看 QFileSystemModel 以获得良好的实践。该模型应使用单独的线程进行自身更新,以实现 UI 响应、保留缓存等。行为良好的模型还应该使您在编辑器上的工作更加轻松。
我还会派生 QObject 来创建 TreeItem 类。使用 QSharedData 作为基类的共享数据方法会很好。我还想拥有一个适合它的订单的属性。这样,当用户拖放或以任何其他方式更改顺序时,您就有办法保持控制。由于数据是共享的,因此将您自己的对象列表保留在您的顺序中以提高性能几乎没有成本。
另外,请查看 ModelTest。
I'd suggest you to take a look at QFileSystemModel for good practices. The model should update itself using a separate thread for UI responsiveness, keeping a cache and so on. A well behaved model should also make your work on the editor easier.
I'd also would go for deriving QObject for creating your TreeItem classes. A shared data aproach with QSharedData for a base class would be nice. I'd also have a property for it's order. This way when user drags and drops or change the order in any other way you have a way to keep control. Since the data is shared, keeping your own list of objects in your order for performance would have little cost.
Also, take a look at ModelTest.
到目前为止,我通过使用专用类限制树的深度解决了这个问题。这意味着只需要处理有限的树深度,所以现在我只使用 QTreeTreeWidget 和一些允许排序、拖动和排序的辅助方法。掉落和其他不错的功能。
By now I solved the problem by limiting the depth of the tree using dedicated classes. That means there is only a limited amount of tree depth that needs to be handled, so for now I simply use QTreeTreeWidget and a few helper methods that allow for sorting, drag & drop and other nice features.