Recent

Author Topic: TShellTreeView, How to mask file extensions?  (Read 3578 times)

jamie

  • Hero Member
  • *****
  • Posts: 6090
TShellTreeView, How to mask file extensions?
« on: August 16, 2019, 03:01:58 am »
I would like to use this control because it would be nice to put this on a tabsheet and it does work that way however, I don't see any premade way to set the filter mask for the files I want to view only.

 I am interested in viewing a series of image file extensions but the way it works now it is showing all file types when I enable the object types to do so.

 Also, I see there is a Method in there "GetFilesInDir" which accepts a MASK string to specify the types I want accumulated but not for the viewing of the TreeView ? It shows all the files and I only what the files of interest to show in the branches..

 Where did I sleep?
The only true wisdom is knowing you know nothing

wp

  • Hero Member
  • *****
  • Posts: 11858
Re: TShellTreeView, How to mask file extensions?
« Reply #1 on: August 16, 2019, 11:15:10 am »
Also, I see there is a Method in there "GetFilesInDir" which accepts a MASK string to specify the types I want accumulated but not for the viewing of the TreeView ? It shows all the files and I only what the files of interest to show in the branches..

I tried to introduce a Mask property to be used by GetFilesInDir. The consequence, however, is that the Mask is applied also to directory names, and this is probably not what you want. Certainly, this can be fixed but requires some larger changes with more intense testing than I can do at the moment...

Then I tried to introduce an event OnAddingFile with a boolean var-parameter "Accept" to prevent a file from inclusion in the file list under some circumstances. But this failed too because GetFilesInDir is a class procedure which does not have access to the event... Again, this can be made, but would break the code in existing projects using GetFilesInDir without creating a class instance.

So, in total, no easy way...

Why don't you combine a folders-only ShellTreeView with ShellListView? That's way I always have been using TShellTreeView. And, in fact, it is very useful this way.
« Last Edit: August 16, 2019, 11:18:40 am by wp »

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: TShellTreeView, How to mask file extensions?
« Reply #2 on: August 16, 2019, 01:02:19 pm »
Does Delphi's TTreeView support this? If so, file a bugreport please.
I second wp's advice to use a mask for the attached TShellListView?

Bart

wp

  • Hero Member
  • *****
  • Posts: 11858
Re: TShellTreeView, How to mask file extensions?
« Reply #3 on: August 16, 2019, 01:22:56 pm »
Does Delphi's TTreeView support this?
In current Delphi XE 10.3, I don't see TShellTreeView any more, it did exist in Delphi 7, though. But even this was without a "Mask" property (there was an OnAddFolder event, though, with a "CanAdd" var-parameter - but we are talking here about files, not folders).

I remember the Delphi7 ShellTreeView as being extremely hard to use and fragile. The Lazarus ShellTreeView (and ShellListView) are much more stable and very straightforward to use.

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: TShellTreeView, How to mask file extensions?
« Reply #4 on: August 16, 2019, 03:59:43 pm »
An optional paramter could be used to declare wether the supplied mask is for both files and folders (the default behaviour) or for files only. Not very pretty, I know.
It could be done, it probably would not break any code.

But IMO TShellTreeView simply wasn't designed for this kind of thing.
Personally I don't even like that it can show files at all.

Bart

wp

  • Hero Member
  • *****
  • Posts: 11858
Re: TShellTreeView, How to mask file extensions?
« Reply #5 on: August 16, 2019, 04:43:07 pm »
But IMO TShellTreeView simply wasn't designed for this kind of thing.
Personally I don't even like that it can show files at all.
Like myself.

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: TShellTreeView, How to mask file extensions?
« Reply #6 on: August 16, 2019, 11:09:52 pm »
Your use of Pos() to determine wether the mask matches is wrong.
You could use MatchesMaskList() function for that instead ...

I don't think we will incorporate such behaviour in TShellTreeView though.

You could maybe override PopulateTreeNodeWithFiles in a derived class?

Bart

wp

  • Hero Member
  • *****
  • Posts: 11858
Re: TShellTreeView, How to mask file extensions?
« Reply #7 on: August 16, 2019, 11:29:43 pm »
I think you get more flexibility when you use an event "OnAddItem" which gets the entire SearchRec as a parameter and has a boolean var-parameter CanAdd which must be set to false to exclude the file/folder from the tree:

Code: Pascal  [Select][+][-]
  1. type
  2.   TAddItemEvent = procedure(Sender: TObject; const ABasePath: String;
  3.     const AFileInfo: TSearchRec; var CanAdd: Boolean) of object;
  4.  
  5.   TCustomShellTreeView = class(TCustomTreeView)
  6.   private
  7.     ...
  8.     FOnAddItem: TAddItemEvent;
  9.   protected
  10.     ...
  11.     property OnAddItem: TAddItemEvent read FOnAddItem write FOnAddItem;
  12.   end;
  13.  
  14.   TShellTreeView = class(TCustomShellTreeView)
  15.   ...
  16.   published
  17.     property OnAddItem;
  18. ...
  19.  
  20. function TCustomShellTreeView.PopulateTreeNodeWithFiles(
  21.   ANode: TTreeNode; ANodePath: string): Boolean;
  22. var
  23.   i: Integer;
  24.   Files: TStringList;
  25.   NewNode: TTreeNode;
  26.   canAdd: Boolean;   // <<< new
  27. ...
  28. begin
  29. ...
  30.   Files := TStringList.Create;
  31.   try
  32.     Files.OwnsObjects := True;
  33.     GetFilesInDir(ANodePath, AllFilesMask, FObjectTypes, Files, FFileSortType);
  34.     Result := Files.Count > 0;
  35.  
  36.     for i := 0 to Files.Count - 1 do
  37.     begin
  38.       // <<<<<<<<< new from here....
  39.       canAdd := true;
  40.       if Assigned(FOnAddItem) then
  41.         with TFileItem(Files.Objects[i]) do
  42.           FOnAddItem(Self, FBasePath, FileInfo, canAdd);
  43.       if not canAdd then
  44.         Continue;
  45.     // ... to here >>>>>>>>>>>>>>
  46.  
  47.       NewNode := Items.AddChildObject(ANode, Files.Strings[i], nil);
  48.       ....
  49.  

The following event handler, for example, filters all files with extensions ".pas" and ".pp" which were created this year:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.ShellTreeView1AddItem(Sender: TObject;
  2.   const ABasePath: String; const AFileInfo: TSearchRec; var CanAdd: Boolean);
  3. var
  4.   ext: String;
  5. begin
  6.   ext := Lowercase(ExtractFileExt(AFileInfo.Name));
  7.   CanAdd := (AFileInfo.Attr and faDirectory <> 0) or (
  8.     (YearOf(FileDateToDateTime(AFileInfo.Time)) = 2019) and ((ext = '.pas') or (ext = '.pp'))
  9.   );
  10. end;

Delphi 7 has an OnAddFolder event handler for the same purpose; it is not compatible though because it has a TShellObj parameter instead of the TSearchRec.

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: TShellTreeView, How to mask file extensions?
« Reply #8 on: August 16, 2019, 11:50:16 pm »
That would probably make a sensible addition.

W.r.t. coding style I prefer
Code: Pascal  [Select][+][-]
  1.   if canAdd then
  2.   begin
  3.    //rest of original code
  4.   end;

over:
Code: Pascal  [Select][+][-]
  1. if not canAdd then
  2.         Continue;

Since Lazarus TShellTreeView is not really compatible with Delphi's one anyway, IMO such a thing could be implemented.

Bart

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: TShellTreeView, How to mask file extensions?
« Reply #9 on: August 17, 2019, 12:04:16 pm »
I want something that works with the OI and I am not writing a new control just for this little nitch.

Hack the system then.

You only override the method in question.
You give the control the same classname:
Code: Pascal  [Select][+][-]
  1. unit MyShellTree;
  2. ...
  3. type
  4.   TShellTreeView = class(ShellCtrls.TShellTreeView)
  5.   ...
  6.   end;
  7.  

Then in your project simply use MyShellTree after ShellCtrls.
Drop a regular TShellTreeView on the form.
At runtime this will now become an instance of MyShellTree.TShellTreeView.
It will stream (=load) OK, because you did not alter any published property.

Bart

wp

  • Hero Member
  • *****
  • Posts: 11858
Re: TShellTreeView, How to mask file extensions?
« Reply #10 on: August 17, 2019, 12:23:39 pm »
Bart, I think it is required that the method PopulateTreeNodeWithFiles() is virtual, otherwise it will not be called.

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: TShellTreeView, How to mask file extensions?
« Reply #11 on: August 17, 2019, 01:38:30 pm »
It can be made virtual if so requested.
We've done that before.

Bart

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: TShellTreeView, How to mask file extensions?
« Reply #12 on: August 17, 2019, 10:27:09 pm »
I get the feeling that I have disrupted someone's holy grail of code and there just isn't going to be any changing it, even when all it does is improves it with no crutches of current support.

Well, excuse me for having an opinion about this (and having done work on TShellTreeView).
I'll refrain from any further comment in this topic.
I'll remind myself not to reply to anything you say on this forum.

Bart

 

TinyPortal © 2005-2018