Recent

Author Topic: [Solved] ShellTreeView, manual NodeAdd, basically rubbish idea?  (Read 551 times)

d7_2_laz

  • Hero Member
  • *****
  • Posts: 511
[Solved] ShellTreeView, manual NodeAdd, basically rubbish idea?
« on: December 08, 2022, 06:29:28 pm »
Win x64; laz-main (2.3.0) . Not 2.2.4 due to changes

No, i don't want to open the 'box of Pandora' (a term from a similar topic). But maybe a simple piece of information s missing for to make this happen. If not possible by principle, i'll forget it. - It's Not an issue! Simply an idea.
I post it in General, not LCL, because i'd think it's rather a basic question rather than specific for ShellCtrls stuff.

Imagine for a moment xou have a file change monitor around a shelltreeview who detects that an external usb drive had been attached. I asked my self if it isn't possible to show it up, and indeed that was easily. Because not really an provided "FileInfo" searchrec would be needed. For added folders a correct FileInfo structure  would be needed, but here i failed with a SIGSEV.

Code: Pascal  [Select][+][-]
  1. === This procedure placed simply for test within ShellCtrls would work:
  2.  
  3. // Soemhow similar as parts of TCustomShellTreeView.PopulateWithBaseFiles;
  4. procedure TCustomShellTreeView.test_ShAddTreeNode(parNode: TTreeNode; fullpath: String);
  5. var NewNode: TTreeNode; capt: String;
  6.     FI: TFileItem; SR: TSearchRec; FindResult: Integer;
  7. begin
  8.   if parNode = Nil then
  9.        capt := ExcludeTrailingBackslash(fullpath)
  10.   else capt := ExcludeTrailingBackslash(ExtractFileName(fullpath));
  11.   SR.Name := fullpath;   // Really fille SearchRec would be next
  12.   FI := TFileItem.Create(SR, '');
  13.   // This one here is only for test with add a drive
  14.   NewNode := TShellTreeNode(Items.AddChildObject(nil, capt, PChar(capt)));
  15.   TShellTreeNode(NewNode).FFileInfo := TFileItem(FI).FileInfo;    //  Not really needed here, but would work
  16.   NewNode.HasChildren:= True;
  17. end;

I'm aware: TCustomShellTreeView.PopulateTreeNodeWithFiles does not really create a SerachRec record.  But to apply and assign one as mentioned above is possible. Simply as a pre-exercise for folders, where FileInfo surely is needed-

=== When trying to access the FFileInfo structure within an unit using a helper type, it compiles, but at runtime it throws a SIGSEV.
The debug call stack does show an error at funciton "fpc_ansistr_decr_ref".

Code: Pascal  [Select][+][-]
  1. Type
  2.   TShellTreeNodeEx = class(TShellTreeNode)
  3.   private
  4.     FFileInfo: TSearchRec;
  5.     FBasePath: String;
  6.   protected
  7.   public
  8.     //function ShortFilename: String;
  9.     //function FullFilename: String;
  10.     property FileInfo: TSearchRec read FFileInfo write FFileInfo;   // Make the property public accessible
  11.     //function IsDirectory: Boolean;
  12.     property BasePath: String read FBasePath;
  13.   end;
  14.  
  15. procedure TExtShellTreeView.yShAddTreeNode(parNode: TTreeNode; fullpath: String);
  16. var NewNode: TShellTreeNode;  // or NewNode: TShellTreeNodeEx
  17.     capt: String; FI: TFileItem; SR: TSearchRec; FindResult: Integer;
  18. begin
  19.   if parNode = Nil then
  20.        capt := ExcludeTrailingBackslash(fullpath)
  21.   else capt := ExcludeTrailingBackslash(ExtractFileName(fullpath));
  22.   SR.Name := fullpath;   // Really fille SearchRec would be next
  23.   FI := TFileItem.Create(SR, '');
  24.   // This one here is only for test via add a drive
  25.  
  26.   //NewNode := TShellTreeNode(Items.AddChildObject(nil, capt, PChar(capt)));
  27.   //TShellTreeNode(NewNode).FFileInfo := TFileItem(FI).FileInfo;    //  Not really needed here, but would work
  28.  
  29.   // This one woould be sufficient to work (the node appear and is expandable):
  30.   NewNode := TShellTreeNodeEx(Items.AddChildObject(nil, capt, PChar(capt)));
  31.  
  32.   // THIS COMPILES, BUT SIGSEV'S:
  33.   TShellTreeNodeEx(NewNode).FileInfo := TFileItem(FI).FileInfo;    /// This line is the problematic one
  34.  
  35.   NewNode.HasChildren:= True;
  36. end;

Is there possibly an easy explanation that this basically wont't work?
If not, i'll forget it...

Attached a simplified test project that triggers the NodeAdd manually (without FileWatcher).

« Last Edit: December 09, 2022, 04:00:35 pm by d7_2_laz »
Lazarus 3.2  FPC 3.2.2 Win10 64bit

wp

  • Hero Member
  • *****
  • Posts: 11858
Re: Q, ShellTreeView, manual NodeAdd, basically rubbish idea?
« Reply #1 on: December 08, 2022, 07:36:03 pm »
I have the feeling that the declaration of TShellTreeNodeEx is wrong: it duplicates the FFileInfo field. It exists on the ancestor TShellTreeNode, and you reclare it again in the TShellTreeNodeEx. Since the node is created as TShellTreeNode the FFileInfo of that class is used by the entire ShellTreeView. But you assign the FileItem's FileInfo to the new class's FileInfo leaving the inherited one alone.

You could move the FFileInfo declaration in the original TShellTreeNode to the protected section; this way the field is accessible from descendant classes.
Code: Pascal  [Select][+][-]
  1. // in shellctrls:
  2. type
  3.   TShellTreeNode = class(TTreeNode)
  4.   private
  5. //    FFileInfo: TSearchRec;
  6.     FBasePath: String;
  7.   protected
  8.     FFileInfo: TSearchRec;
  9.     ...
  10.   end;
  11.  
  12. // in your main unit:
  13.   TShellTreeNodeEx = class(TShellTreeNode);
Doing this I can run your failing step 2 without crashing.



d7_2_laz

  • Hero Member
  • *****
  • Posts: 511
Re: Q, ShellTreeView, manual NodeAdd, basically rubbish idea?
« Reply #2 on: December 08, 2022, 08:33:52 pm »
Oh, yes. The first topic (leaving the inherited one alone) was just because the inherited FFileInfo was not seen from within the unit at all and, so, it should be made accessible.

The second topic (move the FFileInfo declaration in the original TShellTreeNode to the protected section): that does work fine. For this use case. But it was just so that i really didn't intend to aski for changes of ShellCrls.pas.

With this change it appears to me that the ShellTreeView (something similar might happen for the ShellTreeView) would work smoothly together with an app-level placed folder change monitor (whatever this is coded).
May there be reasons against moving the FFileInfo declaration from private to protected,  regarding  that does allow such a use case?

Lazarus 3.2  FPC 3.2.2 Win10 64bit

wp

  • Hero Member
  • *****
  • Posts: 11858
Re: Q, ShellTreeView, manual NodeAdd, basically rubbish idea?
« Reply #3 on: December 08, 2022, 10:15:17 pm »
Committed a new version of ShellCtrls to main in which TShellTreeNode.FFileInfo is protected rather than private. Can't imagine that this change should be harmful in any way, however, extends the usability of the class.

d7_2_laz

  • Hero Member
  • *****
  • Posts: 511
Re: Q, ShellTreeView, manual NodeAdd, basically rubbish idea?
« Reply #4 on: December 08, 2022, 10:48:33 pm »
Hello wp, this is really great, it makes it possible to work on it !
I will be very happy to report back if the proof of concept succeeds and if i detect any side-effects.

Many thanks for having given this opportunity!
Lazarus 3.2  FPC 3.2.2 Win10 64bit

d7_2_laz

  • Hero Member
  • *****
  • Posts: 511
Re: Q, ShellTreeView, manual NodeAdd, basically rubbish idea?
« Reply #5 on: December 09, 2022, 03:59:37 pm »
Adding nodes for folders triggered from app level just work fine  :)

Attached a simplified test project (foused on folders).
Lazarus 3.2  FPC 3.2.2 Win10 64bit

 

TinyPortal © 2005-2018