Search code examples
delphitreeview

How to load TTreeView items from database along with its items image index


I have saved my TreeView inside my DataBase by using the next :

var
BlobField :TField;
Query:TADOQuery;
Stream:TStream;
...



 try
    Query.SQL.Text := 'Select TOP(1) * From MyTable';
    DBQueryConnect(Query); // I used this Procedure to connect the Query to the database
    try
      Query.First;
      Query.Edit;
      try
        BlobField := Query.FieldByName('MyField') as TField;
        Stream := Query.CreateBlobStream(BlobField, bmWrite);
        try
          MyTreeView.SaveToStream(Stream,TEncoding.UTF8);
        finally
          Stream.Free;
        end;
        Query.Post;
      except
        Query.Cancel;
        raise;
      end;
    finally
      Query.Close;
    end;
  finally
    Query.Free;
  end;
end;

and I loaded back the TTreeView form the DataBase by using the next :

...
var
Query:TADOQuery;
Stream:TStream;
begin

      Query:=TADOQuery.Create(Self);
      try
      Query.SQL.Add('Select * From MyTable') ;
      DBQueryConnect(Query);
      Query.First;
      Stream:=Query.CreateBlobStream(Query.FieldByName('MyField'), bmread);
      MyTreeView.LoadFromStream(Stream);
      Stream.Free;
      finally
      Query.Free;
      end;

how can I retrive the imageindex for my TreeView items from the saved data .. Thank you .


Solution

  • Perharps we can modify exsisting SaveTreeToStream and LoadTreeFromStream like this :

    function GetBufStart(Buffer,idxSeparator: string; var Level,ImageIndex: Integer): string;
    var
      Pos: Integer;
      sidx:String;
    begin
      Pos := 1;
      Level := 0;
      ImageIndex := -1;
      while (CharInSet(Buffer[Pos], [' ', #9])) do
      begin
        Inc(Pos);
        Inc(Level);
      end;
      Result := Copy(Buffer, Pos, Length(Buffer) - Pos + 1);
      //Check Image Index
      pos:=System.SysUtils.AnsiPos(idxSeparator,Result);
      if Pos>0 then begin
        sidx:=copy(result,Pos + Length(idxSeparator), length(result) - Pos + 1);
        ImageIndex := StrToIntDef(sidx,-1);
        Result := Copy(Result, 1, Pos - 1);
      end;
    end;
    
    procedure LoadTreeFromStream(Nodes:TTreeNodes; Stream:TStream; Encoding:TEncoding; idxSeparator:String='|||');
    var
      List: TStringList;
      ANode, NextNode: TTreeNode;
      ALevel, i, ImageIndex: Integer;
      CurrStr: string;
    begin
      List := TStringList.Create;
      Nodes.BeginUpdate;
      try
        try
          Nodes.Clear;
          List.LoadFromStream(Stream, Encoding);
          ANode := nil;
          for i := 0 to List.Count - 1 do
          begin
            CurrStr := GetBufStart(PChar(List[i]), idxSeparator, ALevel, ImageIndex);
    
            if ANode = nil then
              ANode := Nodes.AddChild(nil, CurrStr)
            else if ANode.Level = ALevel then
              ANode := Nodes.AddChild(ANode.Parent, CurrStr)
            else if ANode.Level = (ALevel - 1) then
              ANode := Nodes.AddChild(ANode, CurrStr)
            else if ANode.Level > ALevel then
            begin
              NextNode := ANode.Parent;
              while NextNode.Level > ALevel do
                NextNode := NextNode.Parent;
              ANode := Nodes.AddChild(NextNode.Parent, CurrStr);
            end
            else raise Exception.CreateFmt('Invalid level (%d) for item "%s"', [ALevel, CurrStr]);
            ANode.ImageIndex:=ImageIndex;
          end;
        finally
          Nodes.EndUpdate;
          List.Free;
        end;
      except
        Nodes.Owner.Invalidate;  // force repaint on exception
        raise;
      end;
    end;
    
    procedure SaveTreeToStream(Nodes:TTreeNodes; Stream:Tstream; Encoding:TEncoding; idxSeparator:String='|||');
    const
      TabChar = #9;
      EndOfLine = #13#10;
    var
      I: Integer;
      ANode: TTreeNode;
      NodeStr: TStringBuilder;
      Buffer, Preamble: TBytes;
    begin
      if Nodes.Count > 0 then
      begin
        if Encoding = nil then
          Encoding := TEncoding.Default;
        //Buffer := Encoding.GetBytes('');
        Preamble := Encoding.GetPreamble;
        if Length(Preamble) > 0 then
          Stream.WriteBuffer(Preamble{$IFNDEF CLR}[0]{$ENDIF}, Length(Preamble));
    
        NodeStr := TStringBuilder.Create(1024);
        try
          ANode := Nodes[0];
          while ANode <> nil do
          begin
            NodeStr.Length := 0;
            for I := 0 to ANode.Level - 1 do
              NodeStr.Append(TabChar);
            NodeStr.Append(ANode.Text);
            NodeStr.Append(idxSeparator);
            NodeStr.Append(ANode.ImageIndex);
            NodeStr.Append(EndOfLine);
            Buffer := Encoding.GetBytes(NodeStr.ToString);
            Stream.Write(Buffer{$IFNDEF CLR}[0]{$ENDIF}, Length(Buffer));
            ANode := ANode.GetNext;
          end;
        finally
          NodeStr.Free;
        end;
      end;
    end;
    

    You can replace MyTreeView.SaveToStream(Stream,TEncoding.UTF8); with SaveTreeToStream(MyTreeView.Items,Stream,TEncoding.UTF8); and MyTreeView.LoadFromStream(Stream); with LoadTreeFromStream(MyTreeView.Items,Stream,TEncoding.UTF8);