Recent

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

ArminLinder

  • Sr. Member
  • ****
  • Posts: 314
  • 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 3.3.2 on Windows 7,10,11, Debian 10.8 "Buster", macOS Catalina, macOS BigSur, VMWare Workstation 15, Raspberry Pi

balazsszekely

  • Guest
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;  

ArminLinder

  • Sr. Member
  • ****
  • Posts: 314
  • 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 3.3.2 on Windows 7,10,11, Debian 10.8 "Buster", macOS Catalina, macOS BigSur, VMWare Workstation 15, Raspberry Pi

ArminLinder

  • Sr. Member
  • ****
  • Posts: 314
  • 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 3.3.2 on Windows 7,10,11, Debian 10.8 "Buster", macOS Catalina, macOS BigSur, VMWare Workstation 15, Raspberry Pi

 

TinyPortal © 2005-2018