玉兔远程控制 0.1.0-bate6
载入中...
搜索中...
未找到
DatabaseTree.cpp
1// Author: Kang Lin <kl222@126.com>
2
3#include <QSqlDatabase>
4#include <QSqlQuery>
5#include <QSqlError>
6#include <QJsonArray>
7#include <QJsonObject>
8#include <QLoggingCategory>
9
10#include "DatabaseTree.h"
11
12static Q_LOGGING_CATEGORY(log, "DB.Tree")
14 : m_Type(Node)
15 , m_id(0)
16 , m_nKey(0)
17 , m_ParentId(0)
18 , m_SortOrder(0)
19{}
20
21TreeItem::TreeItem(const TreeItem &item)
22{
23 m_Type = item.m_Type;
24 m_id = item.m_id;
25 m_szName = item.m_szName;
26 m_nKey = item.m_nKey;
27 m_ParentId = item.m_ParentId;
28 m_SortOrder = item.m_SortOrder;
29 m_CreateTime = item.m_CreateTime;
30 m_ModifyTime = item.m_ModifyTime;
31 m_LastVisitTime = item.m_LastVisitTime;
32}
33
34bool TreeItem::IsNode() const
35{
36 return Node == GetType();
37}
38
39bool TreeItem::IsLeaf() const
40{
41 return Leaf == GetType();
42}
43
44TreeItem::TYPE TreeItem::GetType() const
45{
46 return m_Type;
47}
48
49void TreeItem::SetType(TYPE type)
50{
51 m_Type = type;
52}
53
54int TreeItem::GetId() const
55{
56 return m_id;
57}
58
59void TreeItem::SetId(int newId)
60{
61 m_id = newId;
62}
63
64QString TreeItem::GetName() const
65{
66 return m_szName;
67}
68
69void TreeItem::SetName(const QString &newName)
70{
71 m_szName = newName;
72}
73
74int TreeItem::GetParentId() const
75{
76 return m_ParentId;
77}
78
79void TreeItem::SetParentId(int newParentId)
80{
81 m_ParentId = newParentId;
82}
83
84int TreeItem::GetSortOrder() const
85{
86 return m_SortOrder;
87}
88
89void TreeItem::SetSortOrder(int newSortOrder)
90{
91 m_SortOrder = newSortOrder;
92}
93
94int TreeItem::GetKey() const
95{
96 return m_nKey;
97}
98
99void TreeItem::SetKey(int newNKey)
100{
101 m_nKey = newNKey;
102}
103
104QDateTime TreeItem::GetCreateTime() const
105{
106 return m_CreateTime;
107}
108
109void TreeItem::SetCreateTime(const QDateTime &newCreateTime)
110{
111 m_CreateTime = newCreateTime;
112}
113
114// QIcon TreeItem::GetIcon() const
115// {
116// if (!m_Icon.isNull()) {
117// return m_Icon;
118// }
119
120// QString url = m_Value;
121// if (url.startsWith("https://")) {
122// return QIcon::fromTheme("security-high");
123// } else if (url.startsWith("http://")) {
124// return QIcon::fromTheme("security-low");
125// }
126
127// if (IsNode()) {
128// return QIcon::fromTheme("folder");
129// }
130
131// return QIcon::fromTheme("file");
132// }
133
134// void TreeItem::SetIcon(const QIcon &newIcon)
135// {
136// m_Icon = newIcon;
137// }
138
139QDateTime TreeItem::GetModifyTime() const
140{
141 return m_ModifyTime;
142}
143
144void TreeItem::SetModifyTime(const QDateTime &newModifyTime)
145{
146 m_ModifyTime = newModifyTime;
147}
148
149QDateTime TreeItem::GetLastVisitTime() const
150{
151 return m_LastVisitTime;
152}
153
154void TreeItem::SetLastVisitTime(const QDateTime &newLastVisitTime)
155{
156 m_LastVisitTime = newLastVisitTime;
157}
158
159CDatabaseFolder::CDatabaseFolder(QObject *parent)
160 : CDatabase(parent)
161{
162 m_szConnectName = "folder_connect";
163 m_szTableName = "folders";
164}
165
166CDatabaseFolder::CDatabaseFolder(const QString &szPrefix, QObject *parent)
167 : CDatabaseFolder(parent)
168{
169 if(!szPrefix.isEmpty())
170 m_szTableName = szPrefix + "_" + m_szTableName;
171}
172
173bool CDatabaseFolder::OnInitializeSqliteDatabase()
174{
175 QSqlQuery query(GetDatabase());
176
177 // 启用外键约束
178 query.exec("PRAGMA foreign_keys = ON");
179
180 // 创建文件夹表
181 bool success = query.exec(
182 "CREATE TABLE IF NOT EXISTS "
183 + m_szTableName +
184 " ("
185 " id INTEGER PRIMARY KEY AUTOINCREMENT,"
186 " name TEXT NOT NULL,"
187 " parent_id INTEGER DEFAULT 0,"
188 " sort_order INTEGER DEFAULT 0,"
189 " created_time DATETIME DEFAULT CURRENT_TIMESTAMP"
190 ")"
191 );
192
193 if (!success) {
194 qCritical(log) << "Failed to create folders sqlite table:"
195 << m_szTableName << query.lastError().text()
196 << "Sql:" << query.executedQuery();
197 return false;
198 }
199
200 // 创建索引
201 query.exec("CREATE INDEX IF NOT EXISTS idx_" + m_szTableName + "_parent ON " + m_szTableName + "(parent_id)");
202
203 return true;
204}
205
206bool CDatabaseFolder::OnInitializeMySqlDatabase()
207{
208 QSqlQuery query(GetDatabase());
209
210 // 启用外键约束
211 query.exec("PRAGMA foreign_keys = ON");
212
213 // 创建文件夹表
214 bool success = query.exec(
215 "CREATE TABLE IF NOT EXISTS "
216 + m_szTableName +
217 " ("
218 " id INTEGER PRIMARY KEY AUTO_INCREMENT,"
219 " name TEXT NOT NULL,"
220 " parent_id INTEGER DEFAULT 0,"
221 " sort_order INTEGER DEFAULT 0,"
222 " created_time DATETIME DEFAULT CURRENT_TIMESTAMP,"
223 " INDEX idx_parent (parent_id),"
224 " INDEX idx_parent_sort (parent_id, sort_order)"
225 ")"
226 );
227 if (!success) {
228 qCritical(log) << "Failed to create folders mysql table:"
229 << m_szTableName << query.lastError().text()
230 << "Sql:" << query.executedQuery();
231 return false;
232 }
233
234 return true;
235}
236
237int CDatabaseFolder::AddFolder(const QString &name, int parentId)
238{
239 bool ok = false;
240 QSqlQuery query(GetDatabase());
241
242 // Check if it already exists
243 query.prepare("SELECT id FROM " + m_szTableName
244 + " WHERE parent_id = :parent_id "
245 + " AND name=:name"
246 );
247 query.bindValue(":parent_id", parentId);
248 query.bindValue(":name", name);
249 ok = query.exec();
250 if(!ok) {
251 qCritical(log) << "Failed to add folders:" << query.lastError().text()
252 << "Sql:" << query.executedQuery();
253 return 0;
254 }
255 if(query.next()) {
256 return query.value(0).toInt();
257 }
258
259 // 获取最大排序值
260 query.prepare("SELECT MAX(sort_order) FROM " + m_szTableName
261 + " WHERE parent_id = :parent_id");
262 query.bindValue(":parent_id", parentId);
263 query.exec();
264
265 int maxOrder = 0;
266 if (query.next()) {
267 maxOrder = query.value(0).toInt() + 1;
268 }
269
270 query.prepare(
271 "INSERT INTO " + m_szTableName +
272 " (name, parent_id, sort_order) "
273 " VALUES (:name, :parent_id, :sort_order) "
274 );
275 query.bindValue(":name", name);
276 query.bindValue(":parent_id", parentId);
277 query.bindValue(":sort_order", maxOrder);
278
279 int id = 0;
280 bool success = query.exec();
281 if (success) {
282 id = query.lastInsertId().toInt();
283 if(id > 0) {
284 emit sigAddFolder(id, parentId);
285 emit sigChanged();
286 }
287 } else
288 qCritical(log) << "Failed to add folders:" << query.lastError().text()
289 << "Sql:" << query.executedQuery();
290
291 return id;
292}
293
294bool CDatabaseFolder::RenameFolder(int id, const QString &newName)
295{
296 QSqlQuery query(GetDatabase());
297 query.prepare("UPDATE " + m_szTableName +
298 " SET name = :name WHERE id = :id");
299 query.bindValue(":id", id);
300 query.bindValue(":name", newName);
301
302 bool success = query.exec();
303
304 if (success)
305 emit sigChanged();
306 else
307 qCritical(log) << "Failed to rename folders:"
308 << query.lastError().text()
309 << "Sql:" << query.executedQuery();
310
311 return success;
312}
313
314bool CDatabaseFolder::DeleteFolder(int id, std::function<int (int parentId)> cbDeleteLeaf)
315{
316 // 删除子目录
317 auto folders = GetSubFolders(id);
318 foreach(auto f, folders) {
319 DeleteFolder(f.GetId(), cbDeleteLeaf);
320 }
321
322 // 删除其下面的所有条目
323 if(cbDeleteLeaf)
324 cbDeleteLeaf(id);
325
326 OnDeleteLeafs(id);
327
328 // 删除文件夹
329 QSqlQuery query(GetDatabase());
330 query.prepare("DELETE FROM " + m_szTableName + " WHERE id = :id");
331 query.bindValue(":id", id);
332
333 bool success = query.exec();
334
335 if (success)
336 emit sigChanged();
337 else
338 qCritical(log) << "Failed to delete folders:"
339 << query.lastError().text()
340 << "Sql:" << query.executedQuery();
341
342 return success;
343}
344
345bool CDatabaseFolder::OnDeleteLeafs(int id)
346{
347 return true;
348}
349
350QString CDatabaseFolder::GetTableName() const
351{
352 return m_szTableName;
353}
354
355void CDatabaseFolder::SetTableName(const QString &newSzTableName)
356{
357 m_szTableName = newSzTableName;
358}
359
360bool CDatabaseFolder::MoveFolder(int id, int newParentId)
361{
362 QSqlQuery query(GetDatabase());
363 query.prepare("UPDATE " + m_szTableName + " SET parent_id = :parent_id WHERE id = :id");
364 query.bindValue(":id", id);
365 query.bindValue(":parent_id", newParentId);
366
367 bool success = query.exec();
368
369 if (success)
370 emit sigChanged();
371 else
372 qCritical(log) << "Failed to move folders:" << query.lastError().text()
373 << "Sql:" << query.executedQuery();
374
375 return success;
376}
377
378TreeItem CDatabaseFolder::GetFolder(int id)
379{
380 TreeItem folder;
381 if(0 >= id) return folder;
382 QSqlQuery query(GetDatabase());
383 query.prepare(
384 "SELECT id, name, parent_id, sort_order, created_time "
385 "FROM " + m_szTableName + " "
386 "WHERE id=:id"
387 );
388 query.bindValue(":id", id);
389 if (query.exec()) {
390 if(query.next()) {
391 folder.SetType(TreeItem::Node);
392 folder.SetId(query.value(0).toInt());
393 folder.SetName(query.value(1).toString());
394 folder.SetParentId(query.value(2).toInt());
395 folder.SetSortOrder(query.value(3).toInt());
396 folder.SetCreateTime(query.value(4).toDateTime());
397 }
398 } else
399 qCritical(log) << "Failed to get folder:"
400 << id << query.lastError().text()
401 << "Sql:" << query.executedQuery();
402
403 return folder;
404}
405
406QList<TreeItem> CDatabaseFolder::GetAllFolders()
407{
408 QList<TreeItem> folders;
409
410 QSqlQuery query(GetDatabase());
411 query.prepare(
412 "SELECT id, name, parent_id, sort_order, created_time "
413 "FROM " + m_szTableName + " "
414 "ORDER BY parent_id, sort_order, name"
415 );
416
417 if (query.exec()) {
418 while (query.next()) {
419 TreeItem folder;
420 folder.SetType(TreeItem::Node);
421 folder.SetId(query.value(0).toInt());
422 folder.SetName(query.value(1).toString());
423 folder.SetParentId(query.value(2).toInt());
424 folder.SetSortOrder(query.value(3).toInt());
425 folder.SetCreateTime(query.value(4).toDateTime());
426
427 folders.append(folder);
428 }
429 }
430
431 return folders;
432}
433
434QList<TreeItem> CDatabaseFolder::GetSubFolders(int parentId)
435{
436 QList<TreeItem> folders;
437
438 QSqlQuery query(GetDatabase());
439 query.prepare(
440 "SELECT id, name, parent_id, sort_order, created_time "
441 "FROM " + m_szTableName + " "
442 "WHERE parent_id = :parent_id "
443 "ORDER BY sort_order, name"
444 );
445 query.bindValue(":parent_id", parentId);
446
447 if (query.exec()) {
448 while (query.next()) {
449 TreeItem folder;
450 folder.SetType(TreeItem::Node);
451 folder.SetId(query.value(0).toInt());
452 folder.SetName(query.value(1).toString());
453 folder.SetParentId(query.value(2).toInt());
454 folder.SetSortOrder(query.value(3).toInt());
455 folder.SetCreateTime(query.value(4).toDateTime());
456
457 folders.append(folder);
458 }
459 }
460
461 return folders;
462}
463
465{
466 QSqlQuery query(GetDatabase());
467 if(0 == parentId) {
468 query.prepare("SELECT COUNT(*) FROM " + m_szTableName);
469 } else {
470 query.prepare("SELECT COUNT(*) FROM " + m_szTableName + " WHERE parent_id=:id");
471 query.bindValue(":id", parentId);
472 }
473 if (query.exec() && query.next())
474 return query.value(0).toInt();
475 return 0;
476}
477
478bool CDatabaseFolder::ExportToJson(QJsonObject& obj)
479{
480 QSqlQuery query(GetDatabase());
481 query.prepare(
482 "SELECT id, name, parent_id, sort_order, created_time "
483 "FROM " + m_szTableName + " "
484 );
485 bool success = query.exec();
486 if (!success) {
487 qCritical(log) << "Failed to export folder to json:"
488 << m_szTableName << query.lastError().text()
489 << "Sql:" << query.executedQuery();
490 return false;
491 }
492 QJsonArray folder;
493 while(query.next()) {
494 QJsonObject f;
495 f.insert("id", query.value(0).toInt());
496 f.insert("name", query.value(1).toString());
497 f.insert("parent_id", query.value(2).toInt());
498 f.insert("sort_order", query.value(3).toInt());
499 f.insert("created_time", query.value(4).toDateTime().toString());
500 folder.append(f);
501 }
502 if(!folder.isEmpty())
503 obj.insert("folder", folder);
504 return true;
505}
506
507bool CDatabaseFolder::ImportFromJson(const QJsonObject& obj)
508{
509 return true;
510}
511
512CDatabaseTree::CDatabaseTree(QObject *parent)
513 : CDatabase(parent)
514{
515 m_szTableName = "tree";
516 m_szConnectName = "tree_connect";
517}
518
519CDatabaseTree::CDatabaseTree(const QString &szPrefix, QObject *parent)
520 : CDatabaseTree(parent)
521{
522 if(!szPrefix.isEmpty())
523 m_szTableName = szPrefix + "_" + m_szTableName;
524 m_FolderDB.SetTableName(szPrefix + "_" + m_FolderDB.GetTableName());
525}
526
527bool CDatabaseTree::OnInitializeDatabase()
528{
529 bool bRet = false;
530 bRet = CDatabase::OnInitializeDatabase();
531
532 if(!bRet) return false;
533 m_FolderDB.SetDatabase(GetDatabase(), m_pPara);
534 bRet = m_FolderDB.OnInitializeDatabase();
535 if(!bRet) return false;
536 bRet = connect(&m_FolderDB, &CDatabaseFolder::sigAddFolder,
537 this, &CDatabaseTree::sigAddFolder);
538 Q_ASSERT(bRet);
539
540 return bRet;
541}
542
543bool CDatabaseTree::OnInitializeSqliteDatabase()
544{
545 QSqlQuery query(GetDatabase());
546
547 // 启用外键约束
548 query.exec("PRAGMA foreign_keys = ON");
549
550 // 创建书签表
551 bool success = query.exec(
552 "CREATE TABLE IF NOT EXISTS " + m_szTableName + " ("
553 " id INTEGER PRIMARY KEY AUTOINCREMENT,"
554 " parent_id INTEGER DEFAULT 0,"
555 " name TEXT,"
556 " value INTEGER DEFAULT 0,"
557 " created_time DATETIME DEFAULT CURRENT_TIMESTAMP,"
558 " modified_time DATETIME DEFAULT CURRENT_TIMESTAMP,"
559 " last_visit_time DATETIME"
560 ")"
561 );
562
563 if (!success) {
564 qCritical(log) << "Failed to create tree table:"
565 << m_szTableName << query.lastError().text()
566 << "Sql:" << query.executedQuery();
567 return false;
568 }
569
570 // 创建索引
571 query.exec("CREATE INDEX IF NOT EXISTS idx_" + m_szTableName + "_value ON " + m_szTableName + "(value)");
572 query.exec("CREATE INDEX IF NOT EXISTS idx_" + m_szTableName + "_parent_id ON " + m_szTableName + "(parent_id)");
573
574 return true;
575}
576
577bool CDatabaseTree::OnInitializeMySqlDatabase()
578{
579 QSqlQuery query(GetDatabase());
580
581 // 启用外键约束
582 query.exec("PRAGMA foreign_keys = ON");
583
584 // 创建书签表
585 bool success = query.exec(
586 "CREATE TABLE IF NOT EXISTS " + m_szTableName + " ("
587 " id INTEGER PRIMARY KEY AUTO_INCREMENT,"
588 " parent_id INTEGER DEFAULT 0,"
589 " name TEXT,"
590 " value INTEGER DEFAULT 0,"
591 " created_time DATETIME DEFAULT CURRENT_TIMESTAMP,"
592 " modified_time DATETIME DEFAULT CURRENT_TIMESTAMP,"
593 " last_visit_time DATETIME,"
594 " INDEX idx_value (value),"
595 " INDEX idx_parent_id (parent_id)"
596 ")"
597 );
598
599 if (!success) {
600 qCritical(log) << "Failed to create tree table:"
601 << m_szTableName << query.lastError().text()
602 << "Sql:" << query.executedQuery();
603 return false;
604 }
605
606 return true;
607}
608
610{
611 bool ok = false;
612 QSqlQuery query(GetDatabase());
613
614 // Check if it already exists
615 query.prepare(
616 "SELECT id FROM " + m_szTableName +
617 " WHERE value=:key AND parent_id=:parent_id"
618 );
619 query.bindValue(":key", item.GetKey());
620 query.bindValue(":parent_id", item.GetParentId());
621 ok = query.exec();
622 if(!ok) {
623 qCritical(log) << "Failed to add tree:" << query.lastError().text()
624 << "Sql:" << query.executedQuery();
625 return 0;
626 }
627 if(query.next()) {
628 return query.value(0).toInt();
629 }
630
631 // Insert
632 query.prepare(
633 "INSERT INTO " + m_szTableName + " (name, value, "
634 "created_time, modified_time, last_visit_time, parent_id) "
635 "VALUES (:name, :key, "
636 ":created_time, :modified_time, :last_visit_time, :parent_id)"
637 );
638
639 query.bindValue(":name", item.GetName());
640 query.bindValue(":key", item.GetKey());
641 QDateTime time = QDateTime::currentDateTime();
642 query.bindValue(":created_time", time);
643 query.bindValue(":modified_time", time);
644 query.bindValue(":last_visit_time", time);
645 query.bindValue(":parent_id", item.GetParentId());
646
647 bool success = query.exec();
648
649 if (!success) {
650 qCritical(log) << "Failed to add tree item:"
651 << query.lastError().text()
652 << "Sql:" << query.executedQuery();
653 return 0;
654 }
655
656 int id = query.lastInsertId().toInt();
657 if(0 < id)
658 emit sigAdd(id, item.GetParentId());
659 return id;
660}
661
662bool CDatabaseTree::Update(const TreeItem &item)
663{
664 QSqlQuery query(GetDatabase());
665 query.prepare(
666 "UPDATE " + m_szTableName + " SET "
667 "name = :name, "
668 "value = :key, "
669 "created_time = :created_time, "
670 "modified_time = :modified_time, "
671 "last_visit_time = :last_visit_time, "
672 "parent_id = :parent_id "
673 "WHERE id = :id"
674 );
675 query.bindValue(":name", item.GetName());
676 query.bindValue(":key", item.GetKey());
677 query.bindValue(":created_time", item.GetCreateTime());
678 query.bindValue(":modified_time", QDateTime::currentDateTime());
679 query.bindValue(":last_visit_time", item.GetLastVisitTime());
680 query.bindValue(":parent_id", item.GetParentId());
681 query.bindValue(":id", item.GetId());
682 qDebug(log) << "Sql:" << query.executedQuery();
683 qDebug(log) << "Bound value:" << query.boundValues();
684 bool success = query.exec();
685 if (!success) {
686 qCritical(log) << "Failed to update tree item:"
687 << m_szTableName << query.lastError().text()
688 << "Sql:" << query.executedQuery();
689 }
690 return success;
691}
692
693bool CDatabaseTree::Delete(int id, bool delKey)
694{
695 // 如果是最后的一个,则从 key 相关表中删除 key
696 if(delKey) {
697 auto leaf = GetLeaf(id);
698 if(leaf.GetKey() > 0) {
699 auto leaves = GetLeavesByKey(leaf.GetKey());
700 if(leaves.count() == 1) {
701 bool ok = OnDeleteKey(leaf.GetKey());
702 if(!ok)
703 return ok;
704 }
705 }
706 }
707 QSqlQuery query(GetDatabase());
708 query.prepare("DELETE FROM " + m_szTableName + " WHERE id = :id");
709 query.bindValue(":id", id);
710
711 bool success = query.exec();
712 if (!success) {
713 qCritical(log) << "Failed to delete item:"
714 << m_szTableName << query.lastError().text()
715 << "Sql:" << query.executedQuery();
716 }
717
718 return success;
719}
720
721bool CDatabaseTree::Delete(QList<int> items, bool delKey)
722{
723 if(items.isEmpty()) return false;
724
725 if(delKey) {
726 foreach(auto id, items) {
727 // 如果是最后的一个,则从 key 相关表中删除 key
728 auto leaf = GetLeaf(id);
729 if(leaf.GetKey() > 0) {
730 auto leaves = GetLeavesByKey(leaf.GetKey());
731 if(leaves.count() == 1) {
732 bool ok = OnDeleteKey(leaf.GetKey());
733 if(!ok)
734 return ok;
735 }
736 }
737 }
738 }
739
740 QSqlQuery query(GetDatabase());
741 QString szSql = "DELETE FROM " + m_szTableName + " WHERE ";
742 int i = 0;
743 foreach(auto id, items) {
744 if(0 == i) {
745 i++;
746 szSql += " id = " + QString::number(id);
747 } else {
748 szSql += " OR id = " + QString::number(id);
749 }
750 }
751 bool success = query.exec(szSql);
752 if (!success) {
753 qCritical(log) << "Failed to delete item:"
754 << m_szTableName << query.lastError().text()
755 << "Sql:" << query.executedQuery();
756 }
757
758 return success;
759}
760
761bool CDatabaseTree::DeleteChild(int parentId, bool delKey)
762{
763 if(delKey) {
764 auto leaves = GetLeaves(parentId);
765 foreach(auto leaf, leaves) {
766 if(!Delete(leaf.GetId(), delKey))
767 return false;
768 }
769 return true;
770 }
771
772 QSqlQuery query(GetDatabase());
773 query.prepare("DELETE FROM " + m_szTableName + " WHERE parent_id = :parent_id");
774 query.bindValue(":parent_id", parentId);
775
776 bool success = query.exec();
777 if (!success) {
778 qCritical(log) << "Failed to delete child item:"
779 << m_szTableName << query.lastError().text()
780 << "Sql:" << query.executedQuery();
781 }
782
783 return success;
784}
785
786bool CDatabaseTree::Move(int id, int newParent)
787{
788 QSqlQuery query(GetDatabase());
789 query.prepare(
790 "UPDATE " + m_szTableName + " SET "
791 "parent_id = :parent_id WHERE id = :id");
792 query.bindValue(":parent_id", newParent);
793 query.bindValue(":id", id);
794
795 bool success = query.exec();
796 if (!success) {
797 qCritical(log) << "Failed to add tree item:"
798 << m_szTableName << query.lastError().text()
799 << "Sql:" << query.executedQuery();
800 }
801
802 return success;
803}
804
805TreeItem CDatabaseTree::GetLeaf(int id)
806{
807 TreeItem item;
808 item.SetType(TreeItem::Leaf);
809
810 QSqlQuery query(GetDatabase());
811 query.prepare(
812 "SELECT name, value, "
813 "created_time, modified_time, last_visit_time, parent_id FROM " + m_szTableName +
814 " WHERE id = :id");
815 query.bindValue(":id", id);
816
817 bool success = query.exec();
818 if (!success) {
819 qCritical(log) << "Failed to get leaf:"
820 << m_szTableName << query.lastError().text()
821 << "Sql:" << query.executedQuery();
822 return item;
823 }
824
825 if(query.next()) {
826 item.SetId(id);
827 item.SetName(query.value(0).toString());
828 item.SetKey(query.value(1).toInt());
829 item.SetCreateTime(query.value(2).toDateTime());
830 item.SetModifyTime(query.value(3).toDateTime());
831 item.SetLastVisitTime(query.value(4).toDateTime());
832 item.SetParentId(query.value(5).toInt());
833 }
834 return item;
835}
836
837QList<TreeItem> CDatabaseTree::GetLeaves(int nodeId)
838{
839 QList<TreeItem> items;
840 QSqlQuery query(GetDatabase());
841 QString szSql;
842 szSql = "SELECT id, name, value, "
843 "created_time, modified_time, last_visit_time, parent_id "
844 "FROM " + m_szTableName;
845 if(0 <= nodeId)
846 szSql += " WHERE parent_id = :parent_id";
847 query.prepare(szSql);
848 query.bindValue(":parent_id", nodeId);
849 bool success = query.exec();
850 if (!success) {
851 qCritical(log) << "Failed to get leaves:"
852 << m_szTableName << query.lastError().text()
853 << "Sql:" << query.executedQuery();
854 return items;
855 }
856
857 while(query.next()) {
858 TreeItem item;
859 item.SetType(TreeItem::Leaf);
860 item.SetId(query.value(0).toInt());
861 item.SetName(query.value(1).toString());
862 item.SetKey(query.value(2).toInt());
863 item.SetCreateTime(query.value(3).toDateTime());
864 item.SetModifyTime(query.value(4).toDateTime());
865 item.SetLastVisitTime(query.value(5).toDateTime());
866 item.SetParentId(query.value(6).toInt());
867
868 items.append(item);
869 }
870 return items;
871}
872
873QList<TreeItem> CDatabaseTree::GetLeavesByKey(int key)
874{
875 QList<TreeItem> items;
876
877 QSqlQuery query(GetDatabase());
878 QString szSql;
879 szSql = "SELECT id, name, "
880 "created_time, modified_time, last_visit_time, parent_id "
881 "FROM " + m_szTableName +
882 " WHERE value = :key";
883 query.prepare(szSql);
884 query.bindValue(":key", key);
885 bool success = query.exec();
886 if (!success) {
887 qCritical(log) << "Failed to get leaves by key:"
888 << m_szTableName << query.lastError().text()
889 << "Sql:" << query.executedQuery();
890 return items;
891 }
892
893 while(query.next()) {
894 TreeItem item;
895 item.SetType(TreeItem::Leaf);
896 item.SetId(query.value(0).toInt());
897 item.SetName(query.value(1).toString());
898 item.SetKey(key);
899 item.SetCreateTime(query.value(2).toDateTime());
900 item.SetModifyTime(query.value(3).toDateTime());
901 item.SetLastVisitTime(query.value(4).toDateTime());
902 item.SetParentId(query.value(5).toInt());
903
904 items.append(item);
905 }
906 return items;
907}
908
909QList<TreeItem> CDatabaseTree::GetLeavesByKey(QList<int> key)
910{
911 QList<TreeItem> items;
912 if(key.isEmpty()) return items;
913
914 QSqlQuery query(GetDatabase());
915 QString szSql;
916 szSql = "SELECT id, name, value, "
917 "created_time, modified_time, last_visit_time, parent_id "
918 "FROM " + m_szTableName +
919 " WHERE ";
920 int i = 0;
921 foreach(auto KeyId, key) {
922 if(0 == i++) {
923 szSql += " value = " + QString::number(KeyId);
924 continue;
925 }
926 szSql += " OR value = " + QString::number(KeyId);
927 }
928 bool success = query.exec(szSql);
929 if (!success) {
930 qCritical(log) << "Failed to get leaves by key:"
931 << m_szTableName << query.lastError().text()
932 << "Sql:" << query.executedQuery();
933 return items;
934 }
935
936 while(query.next()) {
937 TreeItem item;
938 item.SetType(TreeItem::Leaf);
939 item.SetId(query.value(0).toInt());
940 item.SetName(query.value(1).toString());
941 item.SetKey(query.value(2).toInt());
942 item.SetCreateTime(query.value(3).toDateTime());
943 item.SetModifyTime(query.value(4).toDateTime());
944 item.SetLastVisitTime(query.value(5).toDateTime());
945 item.SetParentId(query.value(6).toInt());
946
947 items.append(item);
948 }
949 return items;
950}
951
952int CDatabaseTree::GetLeafCount(int parentId)
953{
954 QSqlQuery query(GetDatabase());
955 if(0 == parentId) {
956 query.prepare("SELECT COUNT(*) FROM " + m_szTableName);
957 } else {
958 query.prepare("SELECT COUNT(*) FROM " + m_szTableName + " WHERE parent_id=:id");
959 query.bindValue(":id", parentId);
960 }
961 if (query.exec() && query.next())
962 return query.value(0).toInt();
963 return 0;
964}
965
966int CDatabaseTree::AddNode(const QString &name, int parentId)
967{
968 return m_FolderDB.AddFolder(name, parentId);
969}
970
971bool CDatabaseTree::RenameNode(int id, const QString &newName)
972{
973 return m_FolderDB.RenameFolder(id, newName);
974}
975
976bool CDatabaseTree::DeleteNode(int id, bool delKey)
977{
978 return m_FolderDB.DeleteFolder(id, [&, delKey](int parentId)->int {
979 return DeleteChild(parentId, delKey);
980 });
981}
982
983bool CDatabaseTree::MoveNode(int id, int newParentId)
984{
985 return m_FolderDB.MoveFolder(id, newParentId);
986}
987
988TreeItem CDatabaseTree::GetNode(int id)
989{
990 return m_FolderDB.GetFolder(id);
991}
992
993QList<TreeItem> CDatabaseTree::GetAllNodes()
994{
995 return m_FolderDB.GetAllFolders();
996}
997
998QList<TreeItem> CDatabaseTree::GetSubNodes(int parentId)
999{
1000 return m_FolderDB.GetSubFolders(parentId);
1001}
1002
1003int CDatabaseTree::GetNodeCount(int nParentId)
1004{
1005 return m_FolderDB.GetCount(nParentId);
1006}
1007
1009{
1010 return GetNodeCount(parentId) + GetLeafCount(parentId);
1011}
1012
1014{
1015 return 0;
1016}
1017
1018bool CDatabaseTree::ExportToJson(QJsonObject& obj)
1019{
1020 bool bRet = true;
1021
1022 QSqlQuery query(GetDatabase());
1023 query.prepare(
1024 "SELECT id, parent_id, name, value, "
1025 "created_time, modified_time, last_visit_time FROM " + m_szTableName);
1026 bool success = query.exec();
1027 if (!success) {
1028 qCritical(log) << "Failed to export tree to json:"
1029 << m_szTableName << query.lastError().text()
1030 << "Sql:" << query.executedQuery();
1031 return false;
1032 }
1033
1034 QJsonArray tree;
1035 while(query.next()) {
1036 QJsonObject t;
1037 t.insert("id", query.value(0).toInt());
1038 t.insert("parent_id", query.value(1).toInt());
1039 t.insert("name", query.value(2).toString());
1040 t.insert("key", query.value(3).toInt());
1041 t.insert("created_time", query.value(4).toDateTime().toString());
1042 t.insert("modified_time", query.value(5).toDateTime().toString());
1043 t.insert("last_visit_time", query.value(6).toDateTime().toString());
1044 tree.append(t);
1045 }
1046 if(!tree.isEmpty())
1047 obj.insert("tree", tree);
1048
1049 bRet = m_FolderDB.ExportToJson(obj);
1050 return bRet;
1051}
1052
1053bool CDatabaseTree::ImportFromJson(const QJsonObject& obj)
1054{
1055 bool bRet = true;
1056 bRet = m_FolderDB.ImportFromJson(obj);
1057 return bRet;
1058}
int GetCount(int parentId=0)
Get count
virtual int Add(const TreeItem &item)
Add item
QList< TreeItem > GetLeavesByKey(int key)
Get leaves
virtual bool OnDeleteKey(int key)
从 key 相关的表中删除 key
int GetCount(int parentId=0)
得到指定id节点下的所有节点和叶子数。不递归。
QList< TreeItem > GetLeaves(int nodeId)
Get the leaves under nodeId