unit uCopyAndPasteThread2;

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
  TCopyAndPasteThread2 = class(TThread)
  private

  // Сбор списка отмеченных узлов
  Procedure ListParentAndAllChildren(NodeID:Integer);
  Procedure ListAllChecked;


  // Поиск родителя в базе
  Function FindParentInDB(ID:integer):integer;

  // Проверка на папку или файл по базе
  function IsFolderByID(NodeID:integer):boolean;

  //Вставка в базу
  Function  InsertFolderOrFileInDB(idParent, index: Integer;
    name: string; TreeView: TTreeView; IsFolder: boolean): integer;
  procedure InsertThatFolderOrFileInDB(TreeView: TTreeView; IsFolderLocalVar:boolean; name:string);

  Procedure PasteIDListCheckedInDB;

  //Структурирование нового списка, восстановление иерархии в БД
  Procedure Structuring;


  protected
    procedure Execute; override;
  end;

 var IDListChecked:Tstringlist;
     IDListInserted:Tstringlist;

     DBConnection:TDBConnection;

implementation

uses MainUnit;

//---------------------------Execute потока --------------------------------

procedure TCopyAndPasteThread2.Execute;
var i:integer;
begin
// Создание
IDListChecked:=Tstringlist.Create;
IDListInserted:=Tstringlist.Create;

DBConnection:=TDBConnection.Create(nil);

ListAllChecked;
//showmessage(IDListChecked.Count.ToString);

PasteIDListCheckedInDB;
Structuring;

// Уничтожение
IDListChecked.Free;
IDListInserted.Free;
DBConnection.Free;

end;


//--------------------------ФОРМИРУЕМ IDList--------------------------------

procedure TCopyAndPasteThread2.ListParentAndAllChildren(NodeID: Integer);

var qSelectAllChildren:TFDQuery;

begin

   qSelectAllChildren:=TFDQuery.Create(nil);
   qSelectAllChildren.Connection:=DBConnection.FDConnection;

   //Если ID не был добавлен ранее, тогда добавляем
   if IDListChecked.IndexOf(NodeID.Tostring)=-1 then
   IDListChecked.Add(NodeID.Tostring); // Записываем родителя и всех детей


   //Ищем всех детей
   with qSelectAllChildren do
   begin

    SQL.Text:='SELECT * FROM treeview_db.tree where IdParent='+NodeID.ToString;

    Open();

     while not eof do
     begin
     // Для каждого ребенка вызываем рекурсивно
     ListParentAndAllChildren(FieldByName('id').AsInteger);

     Next;
     end;

    Close();
   end;

   qSelectAllChildren.Free;

end;

//------------------------------Формируем IDList---------------------------------------

procedure TCopyAndPasteThread2.ListAllChecked;
var i:integer; Node:TTreeNode; NodeID:integer;
    TreeView:TTreeView;
begin

 TreeView:=MainForm.TreeView1;

 if TreeView.Items.GetFirstNode=nil then exit else

    Node:=TreeView.Items.GetFirstNode;

    repeat

    if (Node.StateIndex=2) then
     begin
      NodeID:=Integer(Node.Data^);
      ListParentAndAllChildren(NodeID); // Добавляем в ListID
     end;


    Node:=Node.GetNext;
    until not Assigned(Node) ;


end;
//--------------------------------Формируем ID LIST---------------------------------


//-------------------------------Поиск родителя в БД по ID--------------------------------

function TCopyAndPasteThread2.FindParentInDB(ID: integer): integer;
var qSelectParent:TFDQuery;
begin

 qSelectParent:=TFDQuery.Create(nil);
 qSelectParent.Connection:=DBConnection.FDConnection;

 with qSelectParent do
 begin

   SQL.Text:='Select * from `treeview_db`.`tree` where id='+ID.ToString;
   Open;
   Result:=FieldByName('idParent').AsInteger;
   Close;

 end;


 qSelectParent.Free;
end;
//----------------------------------------------------------------------------------------

//-------------------------------Проверка на файл или папку по ID-------------------------

function TCopyAndPasteThread2.IsFolderByID(NodeID: integer): boolean;

var qCheckIsFolder:TFDQuery;
begin
qCheckIsFolder:=TFDQuery.Create(nil);
qCheckIsFolder.Connection:=DBConnection.FDConnection;

qCheckIsFolder.SQL.Text:='Select * from `treeview_db`.`tree` where id='+NodeID.ToString;

qCheckIsFolder.Open();

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



qCheckIsFolder.Close;
qCheckIsFolder.Free;
//
end;

//-------------------Вспомогательная функция вставки папки или файла в базу-------------------------

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

var qInsert:TFDQuery;
    qGetKey:TFDQuery;

begin


 qInsert:=TFDQuery.Create(nil);
 qInsert.Connection:=DBConnection.FDConnection;

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


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

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


           if IsFolder then ParamValues['IsFolder']:=true else
           ParamValues['IsFolder']:=false

   end;

 qInsert.ExecSQL;

//----------Получение ID последней вставленной записи

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

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


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

qGetKey.Free;
qInsert.Free;


end;
//------------------------------------------------------------------------------------------


//--------------------Непосредственная вставка папки или файла в базу данных---------------------------

procedure TCopyAndPasteThread2.InsertThatFolderOrFileInDB(TreeView: TTreeView;
  IsFolderLocalVar: boolean; name: string);

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

    LastInsertedID:^Integer;

    ParentNameInIDList:string;
    ParentIDInDB:integer;

begin
                 {Назначаем родителя новому узлу - TreeView.Selected}

                 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(LastInsertedID);

 if IsFolderLocalVar then
LastInsertedID^:=InsertFolderOrFileInDB(idParent, Itemindex, name, TreeView, true)
 else
LastInsertedID^:=InsertFolderOrFileInDB(idParent, Itemindex, name, TreeView, false);

                             {Ищем родителя в базе}

IDListInserted.Add(LastInsertedID^.ToString());




Dispose(LastInsertedID);
end;


//-------------------------------Вставка папки или файла в дерево---------------------------


//------------------------------Вставка всех узлов из IDList------------------

procedure TCopyAndPasteThread2.PasteIDListCheckedInDB;

var i:integer; TreeView:TTreeView;

begin

 TreeView:=MainForm.TreeView1;

for i := 0 to IDListChecked.Count-1 do
 begin


    if IsFolderByID(IDListChecked[i].ToInteger()) then

  InsertThatFolderOrFileInDB(TreeView,true,'CuttedFolder') else
  InsertThatFolderOrFileInDB(TreeView,false,'CuttedFile');

 end;


end;

//------------------------Востановление иерархии в записях из списка IDListInserted---------------

procedure TCopyAndPasteThread2.Structuring;
var
  i: Integer; IDParent:Integer; ParentIndexInIDListChecked:integer;
  qUpdateIdParent:TFDQuery;

begin

//Готовим qUpdateIDParent

qUpdateIdParent:=TFDQuery.Create(nil);
qUpdateIdParent.Connection:=DBConnection.FDConnection;
qUpdateIdParent.SQL.Text:='UPDATE `treeview_db`.`tree` SET `IdParent`=:idParent WHERE `id`=:id;';
//----------------------------------------

// Цикл
for i := 0 to IDListChecked.Count-1 do
 begin
  IDParent:=FindParentInDB(IDListChecked[i].ToInteger()); // <<< Ищем ID родителя по базе

  if IDListChecked.IndexOf(IDParent.ToString())<>-1 then // Если родитель в списке IDListChecked
//   showmessage('Родитель в списке IDListChecked ');
        begin
        ParentIndexInIDListChecked:=IDListChecked.IndexOf(IDParent.ToString());

//        showmessage(ParentIndexInIDListChecked.ToString());

        // i - индекс конкретного ребенка для которого найден родитель;

        with qUpdateIdParent.Params

            do begin

            showmessage(IDListInserted[ParentIndexInIDListChecked]);

            ParamValues['idParent']:=(IDListInserted[ParentIndexInIDListChecked]);
            ParamValues['id']:=IDListInserted[i];   //<<< Так работает


            end;

             qUpdateIdParent.ExecSQL;

        end;

 end;




qUpdateIdParent.Free;

end;

end.
