Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Fragen zu VirtualTreeView (https://www.delphipraxis.net/213831-fragen-zu-virtualtreeview.html)

mytbo 5. Okt 2023 14:16

AW: Fragen zu VirtualTreeView
 
Zitat:

Zitat von H.Bothur (Beitrag 1527741)
Wie ist das denn richtig ?

Warum möchtest du die Daten auf diese Weise speichern? Wenn ich mich recht erinnere, willst du das Datenverzeichnis auf der Festplatte im Virtual TreeView abbilden. Die Verwendung der Speicher- und Ladefunktion des TreeViews macht in der Regel nur bei statischen Daten oder bei einer Trennung zwischen Daten definierter Struktur und Aufbereitung/Anordnung Sinn. Bei Ersteren ist es eher eine pragmatische Lösung. Ein Beispiel für den zweiten Fall wäre ein Fragenkatalog zur Beantwortung. Hier trennt man Fragen und/oder visuelle Präsentation von den Antworten jedes Teilnehmers. In vielen Fällen ist der Aufbau des TreeViews direkt aus den Daten, die Datenstruktur liefert Daten und Abbildung, die bessere Lösung.

Bis bald...
Thomas

H.Bothur 5. Okt 2023 15:01

AW: Fragen zu VirtualTreeView
 
Moin

das kann sein, da habe ich einfach den Code aus dem Tutorial kopiert.
Was mich irritiert ist das ich jedes Feld aus dem Record separat speichern muss.
Kann man da den Record nicht en bloc speichern?

Hans

H.Bothur 5. Okt 2023 15:28

AW: Fragen zu VirtualTreeView
 
Hallo Thomas,

mir ging es um die einfachste Methode die Datei zu speichern.
Es handelt sich um Fernsehserien, sprich

Serie
Folge
Wie oft abgespielt

Das ist relativ statisch, da werden die Daten eben nur selten geändert.
Und da suche ich halt den bequemsten Weg.

Hans

Gausi 5. Okt 2023 16:03

AW: Fragen zu VirtualTreeView
 
Wenn man "Fernsehserien" durch "Alben" ersetzt und "Folgen" durch "Lied", hat man das Grundkonzept von meinem mp3-Player. :stupid:

Da habe mir ich zum Speichern ein eigenes Dateiformat gebastelt, welches auch nicht angepasst werden muss, wenn später mal weitere Informationen gespeichert werden sollen. Zusätzlich zur Länge und den eigentlichen String-Inhalt kommt bei mir u.a. noch eine internere "ID" hinzu, die angibt, welche Art von Info nun als nächstes kommt. Z.B. 1: Name der Serie, 2: Name der Folge, 3: Dateiname der Datei, 4: Größe der Datei, etc.pp. Dann können später weitere Datenfelder hinzugefügt werden, ohne dass ich das Dateiformat ändern muss (zwecks Abwärtskompatibilität beim Update des Programms). Das Ende der Daten für ein Objekt wird bei mir über die ID "255" gekennzeichnet.

Gespeichert werden bei mir nur die Informationen zu den einzelnen Titeln (bei dir: Episoden). Die Gruppierung nach Alben (Serien) geschieht bei mir erst zur Laufzeit beim Laden der Liste. Dann ist auch leicht eine alternative Gruppierung im Treeview möglich (nach Erscheinungsjahr, Genre, Dauer, wasweißich).

Das, was dir zu kompliziert vorkommt, ist also vermutlich der sinnvollere Weg. "Problem" sind halt die Strings mit variabler Länge. ;-)

Nachteil bei meinem Ansatz ist nur, dass selbst kleinste Änderungen an einem einzelnen Objekt (Abspielzähler +1) ein Neuschreiben der gesamten Speicherdatei benötigen. Ein punktgenaues Ändern einzelner Stellen in der Datei ist nicht vorgesehen.

mytbo 5. Okt 2023 17:09

AW: Fragen zu VirtualTreeView
 
Zitat:

Zitat von H.Bothur (Beitrag 1527750)
mir ging es um die einfachste Methode die Datei zu speichern.

Wenn es ganz einfach sein soll:
Delphi-Quellcode:
uses
  mormot.core.base,
  mormot.core.json,
  mormot.core.os;
 
type
  TSeriesItem = packed record
    FileName: String;
    SeriesName: String;
    EpisodeName: String;
    PlaybackCount: Integer;
  end;

  TSeriesItems = array of TSeriesItem;

  TSeriesDB = record
    Items: TSeriesItems;
    function Load(const pmcFileName: String): Boolean;
    procedure Save(const pmcFileName: String);
  end;
 
function TSeriesDB.Load(const pmcFileName: String): Boolean;
var
  json: RawJson;
begin
  Result := False;
  json := StringFromFile(pmcFileName);
  if json <> '' then
    Result := (DynArrayLoadJson(Items, Pointer(json), TypeInfo(TSeriesItems)) <> Nil);
end;

procedure TSeriesDB.Save(const pmcFileName: String);
var
  json: RawJson;
begin
  json := DynArraySaveJson(Items, TypeInfo(TSeriesItems));
  if json <> '' then
    FileFromString(json, pmcFileName);
end;
Im TreeView Knoten "Data" auf ein TSeriesItem zeigen lassen oder den Daten-Index speichern. JSON als DB-Format. Das Serialisieren mit mORMot ist tolerant. Du kannst jeder Zeit dem Daten-Record TSeriesItem Felder hinzufügen oder sie wieder entfernen.

Oder klassisch mit Hilfe von TDynArray umgesetzt:
Delphi-Quellcode:
type
  TSeriesDB = class(TObject)
  private
    FList: TDynArray;
    FItems: TSeriesItems;
    FItemCount: Integer;
    function GetItem(pmIndex: Integer): PSeriesItem;
  public
    constructor Create;
    destructor Destroy; override;
    function Add(const pmcFileName: String; const pmcSeriesName, pmcEpisodeName: String; pmPlaybackCount: Integer = 0): Integer;
    function Delete(pmIndex: Integer): Boolean;
    function LoadFromJsonFile(const pmcFileName: String): Boolean;
    function SaveToJsonFile(const pmcFileName: String): Boolean;
    property Item[pmIndex: Integer]: PSeriesItem
      read GetItem;
    property ItemCount: Integer
      read FItemCount;
  end;

constructor TSeriesDB.Create;
begin
  inherited Create;
  FList.Init(TypeInfo(TSeriesItems), FItems, @FItemCount);
end;

destructor TSeriesDB.Destroy;
begin
  FList.Clear;
  inherited Destroy;
end;

function TSeriesDB.GetItem(pmIndex: Integer): PSeriesItem;
begin
  if (pmIndex >= 0)
    and (pmIndex < FItemCount) then
  begin
    Result := @FItems[pmIndex];
  end
  else
    Result := Nil;
end;

function TSeriesDB.Add(const pmcFileName, pmcSeriesName, pmcEpisodeName: String; pmPlaybackCount: Integer): Integer;
var
  item: PSeriesItem;
begin
  item := FList.NewPtr;
  item.FileName := pmcFileName;
  item.SeriesName := pmcSeriesName;
  item.EpisodeName := pmcEpisodeName;
  item.PlaybackCount := pmPlaybackCount;
  Result := FItemCount - 1;
end;

function TSeriesDB.Delete(pmIndex: Integer): Boolean;
begin
  Result := FList.Delete(pmIndex);
end;

function TSeriesDB.LoadFromJsonFile(const pmcFileName: String): Boolean;
var
  json: RawJson;
begin
  json := StringFromFile(pmcFileName);
  if json <> '' then
    Result := (FList.LoadFromJson(Pointer(json), Nil, Nil, True) <> Nil)
  else
    Result := False;
end;

function TSeriesDB.SaveToJsonFile(const pmcFileName: String): Boolean;
var
  json: RawJson;
begin
  json := FList.SaveToJson(True, jsonHumanReadable);
  if json <> '' then
    Result := FileFromString(json, pmcFileName)
  else
    Result := False;
end;
Anwendung so:
Delphi-Quellcode:
procedure ...DoGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
var
  item: PSeriesItem;
begin
  item := FSeriesDB.Item[Node.Index];
  if item <> Nil then
  begin
    case Column of
      0: CellText := item.FileName;
      1: CellText := item.SeriesName;
      2: CellText := item.EpisodeName;
      3: Celltext := item.PlaybackCount.ToString;
    end;
  end;
end;

begin
  FSeriesDB := TSeriesDB.Create;
  FSeriesDB.Add('X.mp4', 'X-Men', 'Folge 2');
  FSeriesDB.Add('Y.mp4', 'Akte-Y', 'Folge 456');
  VirtualStringTree.OnGetText := DoGetText;
  VirtualStringTree.RootNodeCount := FSeriesDB.ItemCount;
Bei Verwendung als Grid ohne filternde Funktionen reicht der Zugriff über Node Index auf die Daten aus.

Bis bald...
Thomas

DieDolly 5. Okt 2023 17:38

AW: Fragen zu VirtualTreeView
 
Zitat:

Ich habe noch nie mit Streams gearbeitet, deswegen stehe ich da ein bisschen auf dem Schlauch.
Deswegen lass das mit dem AddStructure oder was du da machst sein.

Speichere deine Daten in einer Klassenstruktur und einer generischen Liste, dann brauchst du keine Streams.


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:04 Uhr.
Seite 2 von 2     12   

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz