Recent

Author Topic: TTreeView: an example and a question  (Read 9424 times)

moit

  • New member
  • *
  • Posts: 7
TTreeView: an example and a question
« on: June 15, 2010, 06:09:29 pm »
I've been trying to come grips with populating a TTreeView with directories and came up with the following example based on the example here.

As a testcase, it recursively lists out the dirs in my Music folder. I'm on Ubuntu 9.04 using Lazarus v0.9.26.2-2beta. I wanted to include the example here because I wasn't able to find a Linux-friendly example elsewhere.

Code: [Select]
unit Unit1;

{ based on http://stackoverflow.com/questions/1967359/populate-a-ttreeview-with-directory-tree-and-filtering }

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
  StdCtrls, ComCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    populateButton: TButton;
    closeButton: TButton;
    dirTree: TTreeView;
    procedure closeButtonClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure populateButtonClick(Sender: TObject);
  private
    { private declarations }
    procedure PopulateDirTree();
    procedure AddDirectories(theNode: TTreeNode; inPath: String);
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{ TForm1 }

procedure TForm1.closeButtonClick(Sender: TObject);
begin
  Close();
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  //self.PopulateDirTree();
end;

procedure TForm1.populateButtonClick(Sender: TObject);
begin
  self.PopulateDirTree();
end;

procedure TForm1.PopulateDirTree();
var
  searchRec : TSearchRec;
  FileAttrs : Integer;
  theRootDir : String;
  theRootNode : TTreeNode;
  aNode : TTreeNode;
begin
  FileAttrs := faDirectory;     // Only care about directories
  theRootDir:=GetUserDir()+'Music';
  // TODO: catch dir-not-found
  DirTree.Items.Clear;
  theRootNode := DirTree.Items.AddFirst(nil,theRootDir);
  if FindFirst(theRootDir + DirectorySeparator + '*', FileAttrs, searchRec) = 0 then
  begin
    repeat
      if (searchRec.Name = '.') or (searchRec.Name = '..') then
        continue;
      if (searchRec.Attr and faVolumeID) = faVolumeID then
        continue; // nothing useful to do with volume IDs
      if (searchRec.Attr and faHidden) = faHidden then
        continue; // honor the OS "hidden" setting ... doesn't seem to work in Linux
      {$IFDEF UNIX}
      { kludge to filter out hidden files on UNIXy systems }
      if searchRec.Name[1] = '.' then
        continue;
      {$ENDIF}
      if (searchRec.Attr and FileAttrs) = FileAttrs then              { we've found a directory! }
      begin
        aNode := dirTree.Items.AddChild(theRootNode,searchRec.name);  { add it as a node to the tree }
        AddDirectories(aNode,theRootDir+DirectorySeparator+searchRec.Name);  { and add its subdirs as children }
      end;
    until FindNext(searchRec) <> 0;
    FindClose(searchRec);
  end;
  dirTree.FullExpand();
end;

procedure TForm1.AddDirectories(theNode: TTreeNode; inPath: String);
var
  searchRec : TSearchRec;
  FileAttrs : Integer;
  theNewNode : TTreeNode;
begin
  FileAttrs := faDirectory;     // Only care about directories
  if FindFirst(inPath + DirectorySeparator + '*', FileAttrs, searchRec) = 0 then
  begin
    repeat
      //if  ((searchRec.Attr and FileAttrs) = searchRec.Attr) and (copy(searchRec.Name,1,1) <> '.') then
      if (searchRec.Name = '.') or (searchRec.Name = '..') then
        continue;
      if (searchRec.Attr and faHidden) = faHidden then
        continue; // honor the OS "hidden" setting ... doesn't seem to work in Linux
      {$IFDEF UNIX}
      { kludge to filter out hidden files on UNIX-y systems }
      if searchRec.Name[1] = '.' then
        continue;
      {$ENDIF}
      if  ((searchRec.Attr and FileAttrs) = FileAttrs) then            { we've found a directory! }
      begin
        theNewNode := dirTree.Items.AddChild(theNode,searchRec.name);  { add it as a node to the tree }
        self.AddDirectories(theNewNode,inPath+DirectorySeparator+searchRec.Name);  { and add its subdirs as children }
      end;
    until FindNext(searchRec) <> 0;
    FindClose(searchRec);
  end;
end;

initialization
  {$I unit1.lrs}

end.

I've only been using Lazarus for a few weeks, so please be gentle.

My question regards sorting. What is magical incantation required to get TTreeViews to give sorted results? I've tried setting the dirView's sorted property to all the available options in the Options Inspector, but none of them seem to make any difference. Is this a bug, or am I just not getting it?

-M
« Last Edit: June 15, 2010, 06:57:50 pm by moit »

moit

  • New member
  • *
  • Posts: 7
Re: TTreeView: an example and a question
« Reply #1 on: June 16, 2010, 01:53:39 am »
What is magical incantation required to get TTreeViews to give sorted results?

I think I answered my own question:

Code: [Select]
dirTree.AlphaSort();
Apparently, TTreeViews are not automatically sorted -- I suspect because of performance concerns.

theo

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1927
Re: TTreeView: an example and a question
« Reply #2 on: June 16, 2010, 03:20:03 am »
There is also a TShellTreeView in the Misc tab.

moit

  • New member
  • *
  • Posts: 7
Re: TTreeView: an example and a question
« Reply #3 on: June 16, 2010, 05:45:20 pm »
There is also a TShellTreeView in the Misc tab.

So there is! I'll give that a go next.

moit

  • New member
  • *
  • Posts: 7
Re: TTreeView: an example and a question
« Reply #4 on: June 17, 2010, 06:53:45 am »
Please pardon my stupid, but how do you set the root of a TShellTreeView? I can't seem to find documentation on it and the autocompletion isn't suggesting anything useful.

-M

theo

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1927
Re: TTreeView: an example and a question
« Reply #5 on: June 17, 2010, 07:39:08 am »
Afaik you can't hide the file system, but I have written some code to select a certain folder:

Code: [Select]
procedure ShellTreeViewSetTextPath(STV: TShelltreeview; Path: string);
var Str: TStringList;
  ANode: TTreeNode;
  i: integer;
begin
  if not DirectoryExistsUTF8(Path) then Exit;

  Str := TStringList.Create;
  Str.Delimiter := PathDelim;
  Str.DelimitedText := Path;

  for i := Str.Count - 1 downto 0 do
    if Str[i] = '' then Str.Delete(i);

{$IFDEF windows}
//  Str[0] := Str[0] + PathDelim; //Depends on version
{$ENDIF}

  STV.BeginUpdate;
  ANode := STV.TopItem;

  for i := 0 to Str.Count - 1 do
  begin
    while (ANode <> nil) and (ANode.Text <> Str[i]) do
    begin
      ANode := ANode.GetNextSibling;
    end;
    if Anode <> nil then
    begin
      Anode.Expanded := True;
      ANode.Selected := True;
      Anode := ANode.GetFirstChild;
    end
    else
    begin
      str.free;
      STV.EndUpdate;
      Exit;
    end;
  end;
  str.free;
  STV.EndUpdate;
end;

 

TinyPortal © 2005-2018