unit uInsertNodeThread;

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, uDBConnection;

type
  TInsertNodeThread = class(TThread)
  private
    function FindParentNode(Key: integer; TreeView: TTreeView): TTreeNode;

    function InsertNodeInDB(const idParent, index: Integer; const name: string;
      const TreeView: TTreeView): integer;

    procedure InsertNodeInTree(TreeView: TTreeView);


//--------------------Вставка папки или файла в дерево
    function InsertFolderOrFileInDB(const idParent, index: Integer; const name: string;
      const TreeView: TTreeView; IsFolder:boolean): integer;

    procedure InsertFolderOrFileInTree(TreeView: TTreeView; IsFolder:boolean; name:string);

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

    { Private declarations }
  protected
    procedure Execute; override;
  end;

implementation

uses MainUnit;


procedure TInsertNodeThread.Execute;
begin

InsertNodeInTree(MainForm.TreeView1);

  { Place thread code here }
end;

//--------------------------------Поиск родительского узла

function TInsertNodeThread.FindParentNode(Key: integer;TreeView:TTreeView): TTreeNode;

var i:integer;
begin

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

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


end;

//-------------------------------Вставка узла в базу данных-------------------------


function TInsertNodeThread.InsertNodeInDB(

const idParent: Integer;
const index: Integer;
const name: string;
const TreeView: TTreeView

): integer;

var qInsert:TFDQuery;
    qGetKey:TFDQuery;
    DBConnection:TDBConnection;


begin

 //Создание
 DBConnection:=TDBConnection.Create(nil);

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

 qInsert.Connection:=DBConnection.FDConnection;

 qInsert.SQL.Text:=
'INSERT INTO `treeview_db`.`tree` (`IdParent`, `Name`, `Index`,`isChecked`,`Level`)'+
 'VALUES (:idParent, :name, :index,:isChecked,:Level);';

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

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

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

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


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

   end;

qInsert.ExecSQL;

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


 //Уничтожение созданных переменных
 DBConnection.Free;
 qInsert.Free;
 qGetKey.Free;

end;

//-----------------------------Вставка узла в дерево-----------------------

procedure TInsertNodeThread.InsertNodeInTree(TreeView: TTreeView);

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

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

      if Assigned(TreeView.Selected) then
       begin
         //Назначаем родителя новому узлу
         idParent:=Integer(TreeView.Selected.Data^);
         ItemIndex:=TreeView.Items.Count+1;

       end else
       //Если никакой узел не выбран, владельца нет
       begin
        idParent:=-1;
        ItemIndex:=0;
       end;


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

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

            // Вставка в само дерево
       Node:=TreeView.Items.AddChildObject(TreeView.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 TreeView.Selected<>nil then
      begin
      TreeView.Selected.Expanded:=true;
      TreeView.SetFocus;
      TreeView.Selected.Selected:=true;
      end;




    //   Node .Selected:=true;

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

// InsertNodeInTree
end;

//-----------------------ВСТАВКА ПАПКИ ИЛИ ФАЙЛА В БАЗУ ДАННЫХ--------------------

function TInsertNodeThread.InsertFolderOrFileInDB(const idParent, index: Integer;
  const name: string; const TreeView: TTreeView; IsFolder: boolean): integer;



var qInsert:TFDQuery;
    qGetKey:TFDQuery;
    DBConnection:TDBConnection;


begin

 //Создание
 DBConnection:=TDBConnection.Create(nil);

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

 qInsert.Connection:=DBConnection.FDConnection;

 qInsert.SQL.Text:=
'INSERT INTO `treeview_db`.`tree` (`IdParent`, `Name`, `Index`,`isChecked`,`Level`)'+
 'VALUES (:idParent, :name, :index,:isChecked,:Level);';

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

 qGetKey:=TFDQuery.Create(nil);
 qGetKey.Connection:=DBConnection.FDConnection;
 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,TreeView)<>nil then
   begin
     ParamValues['Level']:=FindParentNode(idParent,TreeView).Level+1
   end else ParamValues['Level']:=0;

   end;

qInsert.ExecSQL;

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


 //Уничтожение созданных переменных
 DBConnection.Free;
 qInsert.Free;
 qGetKey.Free;

end;











procedure TInsertNodeThread.InsertFolderOrFileInTree(TreeView: TTreeView; IsFolder: boolean; name:string);
var
    Node:TTreeNode;
    idParent,ItemIndex:integer; // Ключ и индекс узла

    ID:^Integer;
begin


      if Assigned(TreeView.Selected) then
       begin
         //Назначаем родителя новому узлу
         idParent:=Integer(TreeView.Selected.Data^);
         ItemIndex:=TreeView.Items.Count+1;

       end else
       //Если никакой узел не выбран, владельца нет
       begin
        idParent:=-1;
        ItemIndex:=0;
       end;


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

       New(ID);
            // Вставка в БД

       if IsFolder then
       begin
                        //Вставка в базу
           ID^:=InsertFolderOrFileInDB(idParent, Itemindex, name, TreeView, true);
                       // Вставка в само дерево
           Node:=TreeView.Items.AddChildObject(TreeView.Selected,name,ID);


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


            //Ставим иконку папки
                Node.ImageIndex:=4;


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

           //Вставка в базу
           ID^:=InsertFolderOrFileInDB(idParent, Itemindex, name, TreeView, false);
                       // Вставка в само дерево
           Node:=TreeView.Items.AddChildObject(TreeView.Selected,name,ID);


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


            //Ставим иконку папки
                Node.ImageIndex:=3;



       end;





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




    //   Node .Selected:=true;

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


// InsertNodeInTree
end;


end.
