unit uInsertFolderFileNodeBPL;
//Вставка произвольного узла в DBTreeView
//Вставка папки в DBTreeView
//Вставка файла в DBTreeView

interface

uses
  System.SysUtils, System.Classes, FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Param,
  FireDAC.Stan.Error, FireDAC.DatS, FireDAC.Phys.Intf, FireDAC.DApt.Intf, FireDAC.Stan.Async,
  FireDAC.DApt, FireDAC.UI.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Phys,
  FireDAC.VCLUI.Wait, FireDAC.Phys.MySQLDef, FireDAC.Phys.MySQL, Data.DB, FireDAC.Comp.Client,
  FireDAC.Comp.DataSet,
  Vcl.ComCtrls, // Для TTreeView
  Contnrs,vcl.dialogs,
  syncobjs,vcl.Forms,
  vcl.Controls, uDBConnectionBPL,uTreeView,uSQLQueries;

type
 TInsertFolderFileNodeBPL=class(TComponent)

 private
 FSQLInsertFolderFile:string;
 FSQLinsertNode:string;

 FDBTreeView:TDBTreeView;

 function FindParentNode(Key: integer; DBTreeView: TDBTreeView): TTreeNode;

 public

 property SQLInsertFolderFile:string read FSQLInsertFolderFile
 write FSQLInsertFolderFile;

 property SQLinsertNode:string read FSQLinsertNode
 write FSQLinsertNode;

 property DBTreeView:TDBTreeView read FDBTreeView write FDBTreeView;

 //----------------Вставка произвольного узла--------------------------------

 function InsertNodeInDB(idParent: Integer; name: string;
DBTreeView: TDBTreeView): integer;

 procedure InsertNodeInTree(DBTreeView: TDBTreeView);


 //----------------Вставка папки или файла------------------------------------

 function IsFolder(Node:TTreeNode):boolean;

 function InsertFolderOrFileInDB( idParent,index: Integer;
   name: string; DBTreeView: TDBTreeView; IsFolder: boolean): integer;

 procedure InsertFolderOrFileInTree(DBTreeView: TDBTreeView; IsFolderLocalVar:boolean; name:string);

 end;

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

function TInsertFolderFileNodeBPL.FindParentNode(Key: integer; DBTreeView: TDBTreeView): TTreeNode;
//Поиск родительского узла
var i:integer;
begin

 Result:=nil; //Если родитель не будет найден, то это нулевой уровень
//Иначе, это будет какой-то конкретный узел
 for i := 0 to DBTreeView.Items.Count-1 do
  if Integer(DBTreeView.Items.Item[i].Data^)=Key then

   begin
     Result:=DBTreeView.Items.Item[i];
     Break;
   end;


end;

//---------------------------ВСТАВКА ПРОИЗВОЛЬНОГО УЗЛА В ДЕРЕВО-------------------------------

function TInsertFolderFileNodeBPL.InsertNodeInDB(idParent: Integer; name: string;
  DBTreeView: TDBTreeView): integer;

  var qInsert:TFDQuery;
      qGetKey:TFDQuery;
      DBConnectionLocal:TDBConnectionBPL;
      SQLQueries:TSQLQueries;

begin

 //Создание
 DBConnectionLocal:=TDBConnectionBPL.Create(nil);
 SQLQueries:=TSQLQueries.Create(Self);

//---------------------Создание qInsert-------------------------------
 qInsert:=TFDQuery.Create(nil);

 qInsert.Connection:=DBConnectionLocal.FDConnection;

 qInsert.SQL.Text:=SQLQueries.InsertNode.Text;

 //---------------------Создание qGetKey------------------------

 //Даст ID последней добавленной записи
 qGetKey:=TFDQuery.Create(nil);
 qGetKey.Connection:=DBConnectionLocal.FDConnection;
 qGetKey.SQL.Text:=SQLQueries.MaxID.Text;


//---------------------Основная работа по вставке узла в БД----------------
//Вставка записи
  with qInsert.Params do
   begin
     ParamValues['idParent']:=idParent;
     ParamValues['Name']:=Trim(Name);
     ParamValues['isChecked']:=false; // По умолчанию галочка не отмечена


   // Записываем уровень вставляемого узла в базу
   if  FindParentNode(idParent,DBTreeView)<>nil then
   begin
     ParamValues['Level']:=FindParentNode(idParent,DBTreeView).Level+1
   end else ParamValues['Level']:=0;

   end;
qInsert.ExecSQL;

 //Получение id последней записи
 with qGetKey do
 begin
   Open;

   Result:=qGetKey.FieldByName('NewKey').AsInteger;

   Close;
 end;


 //Уничтожение созданных переменных
FreeAndNil(SQLQueries);
FreeAndNil(DBConnectionLocal);
FreeAndNil(qInsert);
FreeAndNil(qGetKey);

end;

procedure TInsertFolderFileNodeBPL.InsertNodeInTree(DBTreeView: TDBTreeView);

var name:string;
    Node:TTreeNode;
    idParent,ItemIndex:integer; // Ключ и индекс узла

    ID:^Integer;
begin
    if InputQuery('Новая запись','',name)=true then
    begin

      if Assigned(DBTreeView.Selected) then

         //Назначаем родителя новому узлу
         idParent:=Integer(DBTreeView.Selected.Data^)

        else

       //Если никакой узел не выбран, владельца нет

        idParent:=-1;


       //Собственно вставка в дерево

       New(ID);
            // Вставка в БД
       ID^:=InsertNodeInDB(idParent, name, DBTreeView);

            // Вставка в само дерево
       Node:=DBTreeView.Items.AddChildObject(DBTreeView.Selected,name,ID);

          //Проверка "чекнутости" родителя в базе, чтобы
         //выставить Checked/not Checked ребенку

             if (Node.Parent<>nil) then
             begin
               if (Node.Parent.StateIndex=2) then Node.StateIndex:=2 else
               Node.StateIndex:=1;
             end else Node.StateIndex:=1;




   // Оставляем фокус на том узле, на который нажали
      if DBTreeView.Selected<>nil then
      begin
      DBTreeView.Selected.Expanded:=true;
      DBTreeView.SetFocus;
      DBTreeView.Selected.Selected:=true;
      end;




    //   Node .Selected:=true;

      //Dispose(Obj) <<Высвобождать будем при закрытии либо
      //Удалении, иначе выскакивает ошибка Invalid Pointer Operation
    end;

// InsertNodeInTree
end;


//---------------------------ВСТАВКА ПАПКИ ИЛИ ФАЙЛА В ДЕРЕВО-------------------------------

function TInsertFolderFileNodeBPL.IsFolder(Node:TTreeNode): boolean;
// Проверка папка это или нет
var qCheckIsFolder:TFDQuery; ID:^integer;
    DBConnectionLocal:TDBConnectionBPL;
    SQLQueries:TSQLQueries;

    isFolderField:string;

begin
isFolderField:=FDBTreeView.DBTreeViewTable.IsFolder;


//Создание
DBConnectionLocal:=TDBConnectionBPL.Create(Self);
SQLQueries:=TSQLQueries.Create(Self);
DBConnectionLocal.Connect; // <<< Ручное подключение
qCheckIsFolder:=TFDQuery.Create(Self);
qCheckIsFolder.Connection:=DBConnectionLocal.FDConnection;

new(ID);
if assigned(Node) then ID^:=Integer(Node.Data^);

qCheckIsFolder.SQL.Text:=SQLQueries.SelectParent.Text+ID^.ToString();
//'Select * from `treeview_db`.`tree` where id='
qCheckIsFolder.Open();

//if qCheckIsFolder.FieldByName('IsFolder').AsBoolean=true then result:=true else
if qCheckIsFolder.FieldByName(IsFolderField).AsBoolean=true then result:=true else
Result:=false;


qCheckIsFolder.Close;

// Освобождение
Dispose(Id);
FreeAndNil(qCheckIsFolder);
FreeAndNil(DBConnectionLocal);
FreeAndNil(SQLQueries);

end;


function TInsertFolderFileNodeBPL.InsertFolderOrFileInDB(idParent,index: Integer;
name: string; DBTreeView: TDBTreeView; IsFolder: boolean): integer;
// Вставка папки или файла в БД


var qInsert:TFDQuery;
    qGetKey:TFDQuery;
    DBConnectionLocal:TDBConnectionBPL;
    SQLQueries:TSQLQueries;

begin

 //Создание
 DBConnectionLocal:=TDBConnectionBPL.Create(nil);
 DBConnectionLocal.Connect;
 SQLQueries:=TSQLQueries.Create(Self);


//---------------------Создание qInsert-------------------------------
 qInsert:=TFDQuery.Create(nil);

 qInsert.Connection:=DBConnectionLocal.FDConnection;

 qInsert.SQL.Text:=SQLQueries.InsertFolderFile.Text;

 //---------------------Создание qGetKey------------------------

 qGetKey:=TFDQuery.Create(nil);
 qGetKey.Connection:=DBConnectionLocal.FDConnection;
 qGetKey.SQL.Text:=SQLQueries.MaxID.Text; //
 //qGetKey.SQL.Text:='SELECT Max(id) as newkey FROM treeview_db.tree;';

//---------------------Основная работа по вставке узла в БД----------------

//Вставка записи
  with qInsert.Params do
   begin

     if IsFolder then

     begin

       ParamValues['idParent']:=idParent;
       ParamValues['Index']:=Index;
       ParamValues['Name']:=Trim(Name);
       ParamValues['isChecked']:=false; // По умолчанию галочка не отмечена
       ParamValues['IsFolder']:=true;

     end else

      begin

       ParamValues['idParent']:=idParent;
       ParamValues['Index']:=Index;
       ParamValues['Name']:=Trim(Name);
       ParamValues['isChecked']:=false; // По умолчанию галочка не отмечена
       ParamValues['IsFolder']:=false;

      end;



   // Записываем уровень вставляемого узла в базу
   if  FindParentNode(idParent,DBTreeView)<>nil then
   begin
     ParamValues['Level']:=FindParentNode(idParent,DBTreeView).Level+1
   end else ParamValues['Level']:=0;

   end;

qInsert.ExecSQL;

 //Получение id последней записи
 with qGetKey do
 begin
   Open;
   Result:=qGetKey.FieldByName('NewKey').AsInteger;
   Close;
 end;


 //Освобождение
FreeAndNil(qGetKey);
FreeAndNil(qInsert);
FreeAndNil(DBConnectionLocal);
FreeAndNil(SQLQueries)

end;

procedure TInsertFolderFileNodeBPL.InsertFolderOrFileInTree(DBTreeView: TDBTreeView; IsFolderLocalVar: boolean;
  name: string);
// Вставка папки или файла в дерево и БД
var
    Node:TTreeNode;
    idParent,ItemIndex:integer; // Ключ и индекс узла
    ID:^Integer;

begin
//---------------------------------------
                              {Определяем родителя}
      if Assigned(DBTreeView.Selected) then

          begin
          idParent:=Integer(DBTreeView.Selected.Data^);
          ItemIndex:=DBTreeView.Items.Count+1;
          end

       else

          begin
          ItemIndex:=0;
          idParent:=-1;
          end;

//----------------------------------

                                {Вставляем в базу и в дерево}

       New(ID);

       if IsFolderLocalVar then // Если папка
       begin
                        //Вставка в базу
           ID^:=InsertFolderOrFileInDB(idParent,ItemIndex, name, DBTreeView, true);
                       // Вставка в само дерево
           Node:=DBTreeView.Items.AddChildObject(DBTreeView.Selected,name,ID);

             // Ставим "чек" как у родителя
                 if (Node.Parent<>nil) {and Assigned(DBTreeView.StateImages)} then
                 begin
                   if (Node.Parent.StateIndex=2) then Node.StateIndex:=2 else
                   Node.StateIndex:=1;
                 end else Node.StateIndex:=1;

       end else
        // Если файл...
       begin

           ID^:=InsertFolderOrFileInDB(idParent,ItemIndex, name, DBTreeView, false);

           Node:=DBTreeView.Items.AddChildObject(DBTreeView.Selected,name,ID);


             // Ставим "чек" как у родителя
                 if (Node.Parent<>nil) {and Assigned(DBTreeView.StateImages)} then
                 begin
                   if (Node.Parent.StateIndex=2) then Node.StateIndex:=2 else
                   Node.StateIndex:=1;
                 end else Node.StateIndex:=1;

       end;


               // Оставляем фокус на том узле, на который нажали
                  if DBTreeView.Selected<>nil then
                  begin
                  DBTreeView.Selected.Expanded:=true;
                  DBTreeView.SetFocus;
                  DBTreeView.Selected.Selected:=true;
                  end;


      //Dispose(ID) <<Высвобождать будем при закрытии либо
      //Удалении, иначе выскакивает ошибка Invalid Pointer Operation
      // В памяти под указателями находятся id записей в базе


// InsertNodeInTree
end;


end.
