unit uUpdateTree;

interface

uses

  System.SysUtils, System.Classes,vcl.dialogs, FireDAC.Stan.Intf, FireDAC.Stan.Option,
  FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool,
  FireDAC.Stan.Async, FireDAC.Phys, FireDAC.Phys.MySQLDef, FireDAC.VCLUI.Wait, FireDAC.Comp.UI,
  FireDAC.Phys.MySQL, Data.DB, FireDAC.Comp.Client,uTreeView,Vcl.ComCtrls,uDBConnectionBPL,uSQLQueries;


type TUpdateTree=class(TComponent)

 private

 procedure GhostNodeDelete(Node: TTreeNode; DBTreeView: TDBTreeView);

 public

 procedure ExpandingUpdate(Node: TTreeNode; DBTreeView: TDBTreeView);



end;



//--------------------------------------------------------------------------------------------------
                                      IMPLEMENTATION
//--------------------------------------------------------------------------------------------------


                                    { TUpdateTree }

//----------------------------ExpandingUpdate-------------------------------------------------------

procedure TUpdateTree.ExpandingUpdate(Node: TTreeNode; DBTreeView: TDBTreeView);

var Buffer:string;
    id,
    Obj,
    TrashPointer:^integer; // Указатели для вставки узлов, см. код

    ChildNode:TTreeNode;  // Добавляемый узел

    GhostNode:TTreeNode; // Чтобы у последнего узла, если у него есть дети, был плюсик

    qSelect,qSelectChildren:TFDQuery;

    DBConnectionBPL:TDBConnectionBPL;

    SQLQueries:TSQLQueries;

    idField,NameField:string;
    IsCheckedField:string;



begin


  idField:=DBTreeViewGlobal.DBTreeViewTable.id;
  NameField:=DBTreeViewGlobal.DBTreeViewTable.NodeName;
  IsCheckedField:=DBTreeViewGlobal.DBTreeViewTable.IsChecked;



 //Создание
 qSelect:=TFDQuery.Create(Self);
 qSelectChildren:=TFDQuery.Create(Self);

 SQLQueries:=TSQLQueries.Create(Self);

 DBConnectionBPL:=TDBConnectionBPL.Create(Self);
 qSelect.Connection:=DBConnectionBPL.FDConnection;
 qSelectChildren.Connection:=DBConnectionBPL.FDConnection;

 GhostNodeDelete(Node, DBTreeView);


//--------------------------------РАБОТА С QSELECT--------------------------------------------------
Buffer:=qSelect.SQL.Text;

    new(id);
    if Node<>nil then begin   id^:=integer(Node.Data^); end
    else id^:=-1;


  //Выбираем из базы всех детей узла

  qSelect.SQL.Text:=SQLQueries.SelectAllChildren.Text+id^.ToString+
  ' order by '+'`'+DBTreeViewGlobal.DBTreeViewTable.IndexField+'`';

 // 'SELECT * FROM treeview_db.tree where IdParent='+id^.ToString
 // +' order by `index`';




     dispose(id);



// Предотвращаем повторное добавление в узел (наблюдал за программой - выявил повторное добавление)
if Node<>nil then if Node.Count<>0 then exit;


  with qSelect do
  begin
     Open();


     while eof<>true do // Начинаем перебирать все записи
     begin

           //Добавление дочернего узла из текущей записи к Node

           New(Obj);
           Obj^:=FieldByName(idField).AsInteger;
           ChildNode:=DBTreeView.Items.AddChildObject(Node,FieldByName(NameField).AsString,Obj);


             //--------------------Добавление GhostNode------------------------
            // Проверяем есть ли дети у узла, чтобы добавить Ghost, если нужно
            qSelectChildren.SQL.Text:=SQLQueries.SelectAllChildren.Text+Integer(Obj^).ToString;

            // 'SELECT * FROM treeview_db.tree where idParent='+Integer(Obj^).ToString;

            qSelectChildren.Open();

            // Добавлем Ghost, если у узла есть дети, чтобы у последнего узла был плюсик
            //И его можно было раскрыть. Этот Ghost при раскрытии будет удаляться
            if not qSelectChildren.IsEmpty  then
             begin
             new(TrashPointer);

             GhostNode:=DBTreeView.Items.AddChildObject(ChildNode,'GhostNode',TrashPointer);
             GhostNode.Parent.Collapse(false); // <<Прячем его
             end;

            qSelectChildren.Close();
          //--------------------Добавление GhostNode----------------------------


         //Расставляем галочки согласно базе
         if FieldByName(IsCheckedField).AsBoolean=true then
          ChildNode.StateIndex:=2 else
          ChildNode.StateIndex:=1;

       Next;
     end;


     Close; // qSelect

//  DBTreeView.Items.EndUpdate;

  qSelect.SQL.Text:=Buffer; // Возвращаем запрос на место
  end;


  //Освобождение

  FreeAndNil(DBConnectionBPL);
  FreeAndNil(qSelect);
  FreeAndNil(SQLQueries);


// end Expanding Update
end;
//--------------------------------------------------------------------------------------------------


//---------------------Вспомогательная процедура удаления Ghost узла

procedure TUpdateTree.GhostNodeDelete(Node: TTreeNode; DBTreeView: TDBTreeView);
begin
  if Node <> nil then
  begin
    // Удаляем Ghost - вспомогательный узел для динамической подгрузки
    if (Node.HasChildren) and (Node.Item[0].Text = 'GhostNode') then
    begin
      Dispose(Node.Item[0].Data); // << Вот так работает верно
      DBTreeView.Items.Delete(Node.Item[0]);
    end;
  end;
end;

end.
