ShellTreeView - wie Zustand speicher/laden?

Rund um die LCL und andere Komponenten
Antworten
Lion
Beiträge: 207
Registriert: Mo 24. Mär 2014, 09:58

ShellTreeView - wie Zustand speicher/laden?

Beitrag von Lion »

Hallo Jungs,

ich bin's wieder. )) Habt ihr eine Idee wie man den Zustand der ShellTreeView speichern und laden kann? Ich meine wie die Verzeichnisstruktur aussieht, spricht welche Verzeichnisse offen und welche zu sind. Also wie man mit ini und xml umgeht weiß ich, mir geht darum was man aus der View speichert.

Danke!

Benutzeravatar
theo
Beiträge: 11325
Registriert: Mo 11. Sep 2006, 19:01

Re: ShellTreeView - wie Zustand speicher/laden?

Beitrag von theo »

Wo hakt es denn?
Du kennst ja jetzt den Treeview und die Nodes ein wenig (und falls nicht, könntest du dich ja mal damit beschäftigen) und wenn für dich xml und ini kein Problem sind, sollte das doch eigentlich nur eine Fleissübung sein. Vllt. hilft dir dieser ältere Beitrag noch ein wenig: http://www.lazarusforum.de/viewtopic.ph ... 29&p=33198

Lion
Beiträge: 207
Registriert: Mo 24. Mär 2014, 09:58

Re: ShellTreeView - wie Zustand speicher/laden?

Beitrag von Lion »

Mir fehlt einfach der Ansatzpunkt, die Idee wie ich das am besten mache. Die Items kann man ja nicht absolut identifizieren... keine Ahnung an was ich mich da richten soll. :|
Zuletzt geändert von Lion am So 15. Feb 2015, 19:21, insgesamt 1-mal geändert.

Benutzeravatar
theo
Beiträge: 11325
Registriert: Mo 11. Sep 2006, 19:01

Re: ShellTreeView - wie Zustand speicher/laden?

Beitrag von theo »

Lion hat geschrieben: Die Items kann man ja nicht absolut identifizieren...
Da stellt sich einfach die Frage, warum man so etwas will.
Ich kenne keinen FileManager o.ä. der das speichert (Vielleicht habe ich mich auch nur nie dafür interessiert.)

Michl
Beiträge: 2513
Registriert: Di 19. Jun 2012, 12:54

Re: ShellTreeView - wie Zustand speicher/laden?

Beitrag von Michl »

theo hat geschrieben:Ich kenne keinen FileManager o.ä. der das speichert
Nur am Rande: Ein für mich quasi nicht zu vermissendes Tool, der Total Commander, macht sowas. IMHO der Lazarusableger der DoubleCommander auch. Sie speichern vor dem Schließen die Position (finde ich eigentlich recht praktisch).

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

Benutzeravatar
theo
Beiträge: 11325
Registriert: Mo 11. Sep 2006, 19:01

Re: ShellTreeView - wie Zustand speicher/laden?

Beitrag von theo »

Michl hat geschrieben:Nur am Rande: Ein für mich quasi nicht zu vermissendes Tool, der Total Commander, macht sowas. IMHO der Lazarusableger der DoubleCommander auch. Sie speichern vor dem Schließen die Position (finde ich eigentlich recht praktisch).
Ist das überhaupt ein Tree? Ich sehe hier nur Listen: http://doublecmd.sourceforge.net/static_gallery_mirror/

Die Position auslesen und setzen ist bei ShellTreeView ja kein Problem, das geht über das Path Property.
Lion wollte aber den Zustand des ganzen Baumes speichern.

Lion
Beiträge: 207
Registriert: Mo 24. Mär 2014, 09:58

Re: ShellTreeView - wie Zustand speicher/laden?

Beitrag von Lion »

theo hat geschrieben:
Die Position auslesen und setzen ist bei ShellTreeView ja kein Problem, das geht über das Path Property.
Was für eine Position meint ihr?

ruewa
Beiträge: 153
Registriert: Sa 12. Apr 2014, 14:43

Re: ShellTreeView - wie Zustand speicher/laden?

Beitrag von ruewa »

So geht's, unter Linux jedenfalls:

Code: Alles auswählen

type
 
  TForm1...
    ...
    RestoreTreeButton : TButton;
    SaveTreeButton : TButton;
    ...
  private
    BackupRoot,
    BackupPath  : String;
    ExpandedTreeNodes : Array of String;
    ...
  end;
 
implementation
 
procedure TForm1.SaveTreeButtonClick(Sender : TObject);
var
  i, k : integer;
  s    : String;
begin
  BackupRoot := ShellTreeView1.Root;
  BackupPath := ShellTreeView1.Path;
  SetLength(ExpandedTreeNodes, 0);
  k := -1;
  for i := 0 to ShellTreeView1.Items.Count - 1 do
    if ShellTreeView1.Items[i].Expanded then
    begin
      inc(k);
      SetLength(ExpandedTreeNodes, k + 1);
      s := ShellTreeView1.Items[i].GetTextPath;
      { Da ist unter Linux ein Wurm drin in TTreeNodes.GetTextPath: Wenn Root = '/',
        werden alle weiteren Unterverzeichnisse als '//xyz' zurückgegeben, das findet
        dann TTreeNodes.FindNodeWithTextPath nicht mehr. Deshalb die folgende Zeile: }
      if (Length(s) > 1) and (s[1] = s[2]) and (s[1] = '/') then Delete(s, 1, 1);
      ExpandedTreeNodes[k] := s;
    end;
end;
 
procedure TForm1.RestoreTreeButtonClick(Sender : TObject);
var
  i : integer;
  ANode : TTreeNode;
begin
  ShellTreeView1.Root := BackupRoot;
  for i := 0 to High(ExpandedTreeNodes) do
    begin
      ANode := ShellTreeView1.Items.FindNodeWithTextPath(ExpandedTreeNodes[i]);
      if ANode <> nil then ANode.Expand(false);
    end;
  ShellTreeView1.Path := BackupPath;
end;
Du must nur noch Dein Stringarray abspeichern / einlesen / aufräumen, dann auch absichern mit try...except / finally und halt all die übliche Folklore. Läßt sich bestimmt auch noch verfeinern. Oder Du kannst statt eines dynamischen Arrays eine Stringliste nehmen, das vereinfacht das Abspeichern, falls Du das Ganze in eine Datei schreiben willst. Aber das ist grob skizziert der Weg.

Gruß Rüdiger

Edit: Fehler beseitigt: ShellTreeView1.Items.Clear löscht den Baum, und wenn Root = BackupRoot, findet kein Neuaufbau statt. Clear ist ohnehin unnötig.
Zuletzt geändert von ruewa am Mi 18. Feb 2015, 14:06, insgesamt 1-mal geändert.

Michl
Beiträge: 2513
Registriert: Di 19. Jun 2012, 12:54

Re: ShellTreeView - wie Zustand speicher/laden?

Beitrag von Michl »

theo hat geschrieben:Ist das überhaupt ein Tree? Ich sehe hier nur Listen: http://doublecmd.sourceforge.net/static_gallery_mirror/
Nein nein, alles gut, daher nur als Randbemerkung, dass es manchmal schön ist, Positionen von geöffneten Verzeichnissen zu speichern (ob als Liste oder Tree). Bei einem Verzeichnis-Tree, würde ich auch nur die letzte geöffnete Position, also nur einen Zweig, geöffnet darstellen (falls es eine Position zum Speichern oder Ähnlichem sein soll) - ist aber nur mein persönlicher Geschmack.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

Lion
Beiträge: 207
Registriert: Mo 24. Mär 2014, 09:58

Re: ShellTreeView - wie Zustand speicher/laden?

Beitrag von Lion »

Danke Euch, meine Lösung sieht vorübergehend so aus...

Code: Alles auswählen

 
procedure TMainForm.BackupClick(Sender: TObject);
var
  i: Integer;
  ExpandedTreeNodes: TStringList;
begin
  ExpandedTreeNodes := TStringList.Create;
  try
    for i := 0 to ShellTreeView1.Items.Count - 1 do
    begin
      if ShellTreeView1.Items[i].Expanded then
        ExpandedTreeNodes.Add(ShellTreeView1.Items[i].GetTextPath);
    end;
    ExpandedTreeNodes.SaveToFile('TStringList.txt');
  finally
    ExpandedTreeNodes.Free;
  end;
end;
 
procedure TMainForm.RestoreClick(Sender: TObject);
var
  i: Integer;
  ANode : TTreeNode;
  ExpandedTreeNodes: TStringList;
begin
  ExpandedTreeNodes := TStringList.Create;
  try
    ExpandedTreeNodes.LoadFromFile('TStringList.txt');
    for i := 0 to ExpandedTreeNodes.Count - 1 do
    begin
      ANode := ShellTreeView1.Items.FindNodeWithTextPath(ExpandedTreeNodes[i]);
      if ANode <> nil then ANode.Expand(False);
    end;
  finally
    ExpandedTreeNodes.Free;
  end;
end; 
 

Das klappt auch soweit gut, nur die Icons werden nicht angezeigt. :(
Wie kann ich beim Restore diese Procedure zum Zeichnen der Icons aufrufen?

Code: Alles auswählen

 
procedure TMainForm.ShellTreeView1CustomDrawItem(Sender: TCustomTreeView;
  Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
var
  lvSL: TStringList;
begin
  try
    if Node.Expanded or (not Node.HasChildren) then Exit;
    lvSL := FindAllDirectories(TShellTreeView(Sender).GetPathFromNode(Node), False);
    Node.HasChildren := lvSL.Count > 0;
 
    if Node.HasChildren then
    begin
      Node.ImageIndex := 1;
      Node.SelectedIndex := 4;
    end else
    begin
      Node.ImageIndex := 0;
      Node.SelectedIndex := 3;
    end;
 
  finally
    lvSL.Free;
  end;
end;
 
Vielen, vielen Dank!

Antworten