Lazarus

Programming => Packages and Libraries => Topic started by: Nimral on August 02, 2021, 09:38:29 pm

Title: VirtualTreeView , IterateSubtree and DeleteNode
Post by: Nimral on August 02, 2021, 09:38:29 pm
Hi,

in the VTV Documentation, IterateSubtree section it says:

Quote
Notes

An application should not modify the content of the tree (e.g. delete nodes) during the iteration, otherwise the

outcome is unpredictable and may result in an access violation.

Unfortunately, I want to do exactly that: iterate through a tree and delete all nodes which meet a certain criteria.

Any chance to do an "Iterate-friendly" DeleteNode?

Thnx, Armin.




Title: Re: VirtualTreeView , IterateSubtree and DeleteNode
Post by: GetMem on August 02, 2021, 10:13:02 pm
Hi,

in the VTV Documentation, IterateSubtree section it says:

Quote
Notes

An application should not modify the content of the tree (e.g. delete nodes) during the iteration, otherwise the

outcome is unpredictable and may result in an access violation.

Unfortunately, I want to do exactly that: iterate through a tree and delete all nodes which meet a certain criteria.

Any chance to do an "Iterate-friendly" DeleteNode?

Thnx, Armin.

Add the nodes to an array first, like this:
Code: Pascal  [Select][+][-]
  1. var
  2.   Node: PVirtualNode;
  3.   VirtualNodes: array of PVirtualNode;
  4.   Len, I: Integer;
  5. begin
  6.   VirtualNodes := nil;
  7.   Node := VST.GetFirst;
  8.   while Assigned(Node) do
  9.   begin
  10.     if (SomeCondition) then
  11.     begin
  12.       //add node to array
  13.       Len := Length(VirtualNodes);
  14.       SetLength(VirtualNodes, Len + 1);
  15.       VirtualNodes[Len] := Node;
  16.     end;
  17.     Node := VST.GetNext(Node);
  18.   end;
  19.  
  20.   //delete the nodes
  21.   VST.BeginUpdate;
  22.   try
  23.     for I := Low(VirtualNodes) to High(VirtualNodes) do
  24.       VST.DeleteNode(VirtualNodes[I]);
  25.   finally
  26.     VST.EndUpdate;
  27.   end;
  28. end;  
Title: Re: VirtualTreeView , IterateSubtree and DeleteNode
Post by: Nimral on August 03, 2021, 02:08:42 pm
Doing it by hand is certainly an option.

What I had in mind though ... I use  IterateSubtree much, but I guess I am out of luck with deletes, since IterateSubtree relies on the tree's GetNextChild and GetNextSibling functionality, which is broken as soon as I delete a node from inside the IterateSubtree callback. What I dream of (for code readibllity's sake ...) is beeing able to do something like

Code: Pascal  [Select][+][-]
  1. for n in VST.SelectedNodes do
  2.    VST.DeleteNode(n);
  3.  
  4. ...
  5.  
  6. or VST.IterateSubtree(VST.RootNode,@DeleteIfMatches,nil);
  7.  

where DeleteIfMatches checks the Node and does the delete if applicable.

Currently I am testing this:

Code: Pascal  [Select][+][-]
  1. function VTVIterateSubtree(Sender: TBaseVirtualTree; ParentNode: PVirtualNode; Callback: TVTGetNodeProc;
  2.   Data: Pointer): PVirtualNode;
  3.  
  4. var
  5.   CurrentNode, NextNode: PVirtualNode;
  6.   abort: boolean;
  7.  
  8. begin
  9.   Result := nil;
  10.   assert(assigned(ParentNode), 'VTVIterateSubtree: Node is undefined.');
  11.   if Assigned(ParentNode) then
  12.   begin
  13.     CurrentNode := Sender.GetFirstChild(ParentNode);
  14.     while assigned(CurrentNode) do
  15.     begin
  16.       NextNode := Sender.GetNextSibling(CurrentNode);
  17.       Abort := False;
  18.       if assigned(CallBack) then Callback(Sender, CurrentNode, Data, Abort);
  19.       if abort then exit(CurrentNode);
  20.       // traverse into subtrees
  21.       result := VTVIterateSubtree(Sender, CurrentNode, Callback, Data);
  22.       CurrentNode := NextNode;
  23.     end;
  24.   end;
  25. end;
  26.  
  27.  
Title: Re: VirtualTreeView , IterateSubtree and DeleteNode
Post by: Nimral on August 04, 2021, 08:39:36 pm
Getmem,

finally I dumped all iterators, and decided to go with the "conventional" approach, like you suggested :-)

Thanks!

Armin.
TinyPortal © 2005-2018