Most elegant/safe/easy solution to store and edit (GUI) a directory-like tree structure?
-
18-09-2019 - |
Question
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. :)
Solution 2
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.
OTHER TIPS
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.