Это продолжение статьи про копирование узлов. В прошлом посте копировали иерархические записи в БД, в данном посте – будем обновлять узел в который вставляли скопированные записи. Эти 2 части – БД и TreeView должны работать синхронно – в этом самая большая сложность при разработке DBTreeView.
Идея точно такая же как и с базами данных
-Собрать все копируемые узлы в списки IDCheckedList и IDInsertedList
-Переместить в новый узел
-При перемещении, если у ID вставлямого узла есть родитель и этот родитель в списке IDInsertedList, то переподчинить его этому родителю. Поскольку родители в дерево вставляются всегда раньше чем дети (папка состоит из файлов), то родитель найдется в дереве.
Для этого нам понадобятся следующие процедуры
1 2 3 4 |
// Поиск родителя в дереве по ID Function FindNodeInTree(ID:Integer):TTreeNode; Procedure UpdateNodeInTree; |
Вспомогательная процедура – поиск родительского узла в дереве по ID
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
//------------------------------Поиск узла в дереве по ID--------------------------------- function TCopyAndPasteThread.FindNodeInTree(ID:Integer): TTreeNode; var i:integer; TreeView:TTreeView; begin TreeView:=MainForm.TreeView1; Result:=nil; //Если родитель не будет найден, то это нулевой уровень //Иначе, это будет какой-то конкретный узел for i := 0 to TreeView.Items.Count-1 do if Integer(TreeView.Items.Item[i].Data^)=ID then begin Result:=TreeView.Items.Item[i]; Break; end; end; |
Добавление иерархической структуры в узел при копировании
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
//-------------------------Обновление одного узла--------------------------- procedure TCopyAndPasteThread.UpdateNodeInTree; var IDParent:integer; ParentNode:TTreeNode; Node:TTreeNode; i:integer; TreeView:TTreeView; qSelectAll:TFdQuery; name:string; id:^integer; begin TreeView:=MainForm.TreeView1; qSelectAll:=TFdQuery.Create(nil); qSelectAll.Connection:=DBConnection.FDConnection; qSelectAll.SQL.Text:= 'SELECT * FROM treeview_db.tree where id=:id;'; for i := 0 to IDListInserted.Count-1 do begin IDParent:=FindParentInDB(IDListInserted[i].ToInteger()); // Если родитель во вставленном списке if IDListInserted.IndexOf(IDParent.ToString())<>-1 then begin ParentNode:=FindNodeInTree(IDParent); qSelectAll.Params.ParamValues['id']:=IDListInserted[i]; qSelectAll.Open(); Name:=qSelectAll.FieldByName('name').AsString; qSelectAll.Close; new(id); id^:=IDListInserted[i].ToInteger; Node:=TreeView.Items.AddChildObject(ParentNode,Name,id); //Обновление StateIndex with qSelectAll do begin Open(); if FieldByName('IsChecked').AsBoolean=true then Node.StateIndex:=2 else Node.StateIndex:=1; Close(); end; end else begin //Если родителя нет в списке ParentNode:=TreeView.Selected; qSelectAll.Params.ParamValues['id']:=IDListInserted[i]; qSelectAll.Open(); Name:=qSelectAll.FieldByName('name').AsString; qSelectAll.Close; new(id); id^:=IDListInserted[i].ToInteger; Node:=TreeView.Items.AddChildObject(ParentNode,Name,id); //Обновление StateIndex with qSelectAll do begin Open(); if FieldByName('IsChecked').AsBoolean=true then Node.StateIndex:=2 else Node.StateIndex:=1; Close(); end; end; //for end; TreeView.Selected.Expand(false); qSelectAll.Free; end; |
Процедура Execute изменится следующим образом
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
procedure TCopyAndPasteThread.Execute; var i:integer; begin // Создание IDListChecked:=Tstringlist.Create; IDListInserted:=Tstringlist.Create; DBConnection:=TDBConnection.Create(nil); ListAllChecked; CopyAndPasteIDListCheckedInDB2; Structuring; Synchronize(UpdateNodeInTree); // Уничтожение IDListChecked.Free; IDListInserted.Free; DBConnection.Free; end; |
Ну и соответственно вызов в главном потоке
Вызов в главном потоке
1 2 3 4 5 |
// Глобальные переменные ... var CopyAndPasteThread:TCopyAndPasteThread; ... |
1 2 3 4 5 6 7 8 |
procedure TMainForm.bTestClick(Sender: TObject); begin CopyAndPasteThread:=TCopyAndPasteThread.Create(false); CopyAndPasteThread.FreeOnTerminate:=true; end; |