Recent

Author Topic: VirtualTreeView , IterateSubtree and DeleteNode  (Read 2414 times)

Nimral

  • Full Member
  • ***
  • Posts: 186
  • Keep it simple.
VirtualTreeView , IterateSubtree and DeleteNode
« 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.




Lazarus 2.0.12 & 2.3.0  (trunk) on Windows 10, Raspberry Pi OS "Buster", macOS Catalina, macOS BigSur, VMWare Workstation 15

GetMem

  • Hero Member
  • *****
  • Posts: 3452
Re: VirtualTreeView , IterateSubtree and DeleteNode
« Reply #1 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;  

Nimral

  • Full Member
  • ***
  • Posts: 186
  • Keep it simple.
Re: VirtualTreeView , IterateSubtree and DeleteNode
« Reply #2 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.  
Lazarus 2.0.12 & 2.3.0  (trunk) on Windows 10, Raspberry Pi OS "Buster", macOS Catalina, macOS BigSur, VMWare Workstation 15

Nimral

  • Full Member
  • ***
  • Posts: 186
  • Keep it simple.
Re: VirtualTreeView , IterateSubtree and DeleteNode
« Reply #3 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.
Lazarus 2.0.12 & 2.3.0  (trunk) on Windows 10, Raspberry Pi OS "Buster", macOS Catalina, macOS BigSur, VMWare Workstation 15

 

TinyPortal © 2005-2018