giuspen / cherrytree

cherrytree
https://www.giuspen.net/cherrytree/
Other
3.29k stars 457 forks source link

[Feature Request] Cloning Nodes #1222

Open SultanOfSolder opened 3 years ago

SultanOfSolder commented 3 years ago

It would be great to have clone feature that allows a single node appear in multiple locations in the tree. This is different from a duplication of the node, because changing the text in one node changes the text in all of the cloned nodes. This is also different from creating a link, because exporting a node exports the text, and not the link name. A real world use of this feature is generating documentation for multiple variations of a product. For example, openbot.org (DIY robot project) has three different body styles based on the size of the 3D printer used to print the body of the robot. But, wiring the drive motors for all three styles is exactly the same. So, in CherryTree, you create three main nodes for the three different manuals, and clone the subnode that contains the instructions for wiring the motors between the three of them. Updating the instructions for wiring the motor in one of them updates the text in all of them. (Allows you to modify one source instead of three.)

singularis-mzf commented 3 years ago

I would name it rather 'hard links' instead of cloning, because this is exactly the way how hard links work in filesystems — multiple names and locations for the same underlying data and metadata.

z33ky commented 11 months ago

I looked/am looking to take a stab at this.

One of the required changes is stopping removal from the SQL storage since nodes will be shared. This could be implemented either via reference-counting nodes, or by searching the tree for the node_id that is supposed to be removed, to stop removal of the node (and only remove the child) if the node_id is referenced from another child. A reference-counting approach sounds better than the search to me. I think the XML storage is unaffected because it regenerates the document from scratch, whereas the SQL storage instead works by updating the existing database.

I'm also wondering what the best approach for the XML format is. We could keep it mostly as-is, meaning the node content will be repeated when cloned/hard-linked. The "unique_id" attribute can be used to detect clones/hard-links. This means however that there is no single point of truth concerning the repeated content. We could just take the first occurrence for "truth" and maybe ask the user what to do if later clones/hard-links have differing contents - which should not happen of course -: use the existing content, use the new content or create a copy instead. Maybe only the first occurrence should write the contents and following cloned/hard-linked nodes simply omit it. This allows for a single point of truth. It's possible of course that a weird file is loaded where contents are repeated regardless and this situation should still be handled in some special way. Alternatively the format can be changed such that node-contents are stored in a separately from the nodes. Something like

<cherrytree>
  <rich_text unique_id="2">content</rich_text>
  <rich_text unique_id="3">more content</rich_text>
  <node name="foo" unique_id="1">
    <node name="text" unique_id="2"/>
    <node name="more text" unique_id="3"/>
  </node>
  <node name="bar" unique_id="4">
    <node name="text (clone/hard-link)" unique_id="2"/>
  </node>
</cherrytree>

I'm more fond of that idea, but one down-side is that manual inspection of the XML file is no longer a good human-readable representation of the tree, since contents are not shown inline anymore. Also migrating the old XML format to the new format may be in order, which has consequences regarding backwards-compatibility, or maintaining both formats and alerting the user that the old format does not support clones/hard-links.

There could be different degrees of this feature. Me personally I'm fine just sharing node contents, but there may be use-cases where sharing other properties such as name, color and icon are also desired. Cloning more properties that just the contents is more work I think, especially if this should be controllable by the user. This also goes for sub-nodes. Should this regard nodes in isolation, or should children be considered. I think with the current code it's easier to clone/hard-link in isolation. Me personally I'd plan to use it merely for contents of leaf nodes, so the simplest variant is sufficient for me, but taking a broader view it seems sensible to consider the options here before going ahead with an implementation. It may not be necessary to tackle everything at once, but it could inform decisions about storage format changes for instance.

Adding functionality for deduplicating entries may also be useful, but I think this can be added separately once cloning/hard-linking nodes is possible.

These are design decisions for @giuspen to make I think, assuming they'd consider having this feature at all. I can currently work well without cloning/hard-linking, so I may leave this lying around even if the mentioned details are worked out - just to make my intentions here clear. I would like to have this feature, but I may not be sufficiently motivated since I can use cherrytree pretty well without it... BTW thank you @giuspen & contributors for this software :)

Also another term that could be considered is "mirror(ing)". Maybe "synced copy", "shared copy", "mimicked copy" or something along those lines.

giuspen commented 11 months ago

I was thinking to work on this next actually. I'm releasing the new version 1.0.0 tomorrow or so and afterwards I'll give it a go. I was thinking that the hard linked nodes share the node content / properties and the oldest created node is the one that physically has the data and if that is deleted the data will be reassigned to another member of the group.

RFImages commented 6 months ago

Please check my understanding of this: Rather than a link that takes you to another node for reference, the contents of that node can be made visible in any multiple of other nodes that refer to it. Hopefully it can also be edited from any other node and all nodes that refer to it will be updated such that there is one source of truth being edited. Do I have that right? Sounds useful.

giuspen commented 6 months ago

That's correct, the text content but also the properties of the nodes belonging to the group (e.g. the name, a custom icon, tags for searching...) all can be visualised and edited equally from any of these nodes belonging to the same group. I'm still not sure how to call these nodes, I thought about 'virtual nodes' but I'm not sure if it's the most intuitive.

RFImages commented 6 months ago

Common nodes? Reference nodes? I think Virtual nodes implies that they don't exist physically but rather in the cloud somewhere, like a virtual machine?

giuspen commented 6 months ago

You're right, Virtual is not clear. Maybe Shared nodes could do as well.

RFImages commented 6 months ago

Shared nodes sounds more correct.

giuspen commented 4 months ago

This has now been implemented and will be released in upcoming v1.1.0 I still have to do some testing and implement unit tests, but then if anybody would be available to help me with additional tests, that would be very useful. In case write here which binary you need. NOTE: older cherrytree version do not understand shared nodes so will fail to open, you have to delete the shared nodes in the group (leave only one) if you wish to return to an older version.

RFImages commented 4 months ago

Does this mean Collapsible headers are next? :D https://github.com/giuspen/cherrytree/issues/2389

giuspen commented 4 months ago

@RFImages I will certainly study what can be done and update on the ticket after the release