玉兔远程控制 0.1.0-bate6
载入中...
搜索中...
未找到
BookmarkDatabase.cpp
1// Author: Kang Lin <kl222@126.com>
2
3#include <QSqlDatabase>
4#include <QSqlQuery>
5#include <QSqlError>
6#include <QMessageBox>
7#include <QStandardPaths>
8#include <QDir>
9#include <QDebug>
10#include <QFile>
11#include <QTextStream>
12#include <QLoggingCategory>
13
14#include "BookmarkDatabase.h"
15
16static Q_LOGGING_CATEGORY(log, "WebBrowser.Bookmark.DB")
17static CBookmarkDatabase* g_pDatabase = nullptr;
18CBookmarkDatabase* CBookmarkDatabase::Instance(const QSqlDatabase &database)
19{
20 if(!g_pDatabase) {
21 g_pDatabase = new CBookmarkDatabase();
22 if(g_pDatabase) {
23 g_pDatabase->SetDatabase(database);
24 g_pDatabase->OnInitializeDatabase();
25 }
26 }
27 return g_pDatabase;
28}
29
30CBookmarkDatabase* CBookmarkDatabase::Instance(const QString &szFile)
31{
32 if(!g_pDatabase) {
33 g_pDatabase = new CBookmarkDatabase();
34 if(g_pDatabase) {
35 bool bRet = g_pDatabase->OpenSQLiteDatabase("bookmarks_connect", szFile);
36 if(!bRet) {
37 delete g_pDatabase;
38 g_pDatabase = nullptr;
39 }
40 }
41 }
42 return g_pDatabase;
43}
44
45CBookmarkDatabase::CBookmarkDatabase(QObject *parent)
46 : CDatabase(parent)
47 , m_TreeDB("bookmarks")
48{
49 qDebug(log) << Q_FUNC_INFO;
50}
51
52CBookmarkDatabase::~CBookmarkDatabase()
53{
54 qDebug(log) << Q_FUNC_INFO;
55}
56
57bool CBookmarkDatabase::OnInitializeDatabase()
58{
59 m_UrlDB.SetDatabase(GetDatabase());
60 m_UrlDB.OnInitializeDatabase();
61 m_TreeDB.SetDatabase(GetDatabase());
62 m_TreeDB.OnInitializeDatabase();
63
64 if(m_TreeDB.GetNodeCount() == 0) {
65 m_TreeDB.AddNode(tr("Bookmarks"), 0);
66 m_TreeDB.AddNode(tr("Other"), 0);
67 m_TreeDB.AddNode(tr("Favorites"), 1);
68 m_TreeDB.AddNode(tr("Frequently Used Websites"), 1);
69 }
70 return true;
71}
72
73int CBookmarkDatabase::addBookmark(const BookmarkItem &item)
74{
75 int urlId = m_UrlDB.AddUrl(item.url, item.title, item.icon);
76 auto tree = BookmarkToTree(item);
77 tree.SetKey(urlId);
78 return m_TreeDB.Add(tree);
79}
80
81bool CBookmarkDatabase::updateBookmark(const BookmarkItem &item)
82{
83 bool success = m_UrlDB.UpdateUrl(item.url, item.title, item.icon);
84 if(!success) {
85 qCritical(log) << "Failed to update bookmark" << item.url;
86 return false;
87 }
88 TreeItem tree = BookmarkToTree(item, true);
89 success = m_TreeDB.Update(tree);
90 if(!success) {
91 qCritical(log) << "Failed to update bookmark" << item.url;
92 }
93 return success;
94}
95
96bool CBookmarkDatabase::deleteBookmark(int id)
97{
98 return m_TreeDB.Delete(id);
99}
100
101bool CBookmarkDatabase::deleteBookmark(const QList<BookmarkItem> &items)
102{
103 if(items.isEmpty()) {
104 qWarning(log) << "The items is empty";
105 return false;
106 }
107 QList<int> lstItems;
108 foreach(auto item, items) {
109 lstItems.push_back(item.id);
110 }
111 return m_TreeDB.Delete(lstItems);
112}
113
114bool CBookmarkDatabase::moveBookmark(int id, int newFolderId)
115{
116 return m_TreeDB.Move(id, newFolderId);
117}
118
119int CBookmarkDatabase::addFolder(const QString &name, int parentId)
120{
121 return m_TreeDB.AddNode(name, parentId);
122}
123
124bool CBookmarkDatabase::renameFolder(int folderId, const QString &newName)
125{
126 return m_TreeDB.RenameNode(folderId, newName);
127}
128
129bool CBookmarkDatabase::deleteFolder(int folderId)
130{
131 return m_TreeDB.DeleteNode(folderId);
132}
133
134bool CBookmarkDatabase::moveFolder(int folderId, int newParentId)
135{
136 return m_TreeDB.MoveNode(folderId, newParentId);
137}
138
139BookmarkItem CBookmarkDatabase::getBookmark(int id)
140{
141 BookmarkItem item;
142
143 auto leaf = m_TreeDB.GetLeaf(id);
144 if(leaf.GetId() == 0) return item;
145 item = TreeToBookmark(leaf);
146 return item;
147}
148
149QList<BookmarkItem> CBookmarkDatabase::getBookmarkByUrl(const QString &url)
150{
151 QList<BookmarkItem> lstItems;
152 BookmarkItem item;
153
154 auto urlItem = m_UrlDB.GetItem(url);
155 auto leaves = m_TreeDB.GetLeavesByKey(urlItem.id);
156 foreach(auto leaf, leaves) {
157 item = TreeToBookmark(leaf, urlItem);
158 lstItems.push_back(item);
159 }
160 return lstItems;
161}
162
163QList<BookmarkItem> CBookmarkDatabase::getAllBookmarks(int folderId)
164{
165 QList<BookmarkItem> bookmarks;
166
167 auto leaves = m_TreeDB.GetLeaves(folderId);
168 foreach(auto leaf, leaves) {
169 auto item = TreeToBookmark(leaf);
170 bookmarks << item;
171 }
172 return bookmarks;
173}
174
175QList<BookmarkItem> CBookmarkDatabase::searchBookmarks(const QString &keyword)
176{
177 QList<BookmarkItem> bookmarks;
178
179 auto urlIds = m_UrlDB.Search(keyword);
180 foreach(auto urlItem, urlIds) {
181 if(0 == urlItem.id)
182 continue;
183 auto trees = m_TreeDB.GetLeavesByKey(urlItem.id);
184 foreach(auto t, trees) {
185 auto item = TreeToBookmark(t, urlItem);
186 if(0 == item.id)
187 continue;
188 bookmarks << item;
189 }
190 }
191
192 return bookmarks;
193}
194
195QList<BookmarkItem> CBookmarkDatabase::getAllFolders()
196{
197 QList<BookmarkItem> folders;
198
199 auto items = m_TreeDB.GetAllNodes();
200 foreach(auto it, items) {
201 auto book = TreeToBookmark(it);
202 folders << book;
203 }
204 return folders;
205}
206
207QList<BookmarkItem> CBookmarkDatabase::getSubFolders(int folderId)
208{
209 QList<BookmarkItem> folders;
210
211 auto items = m_TreeDB.GetSubNodes(folderId);
212 foreach(auto it, items) {
213 auto book = TreeToBookmark(it);
214 folders << book;
215 }
216 return folders;
217}
218
219bool CBookmarkDatabase::exportToHtml(const QString &filename)
220{
221 QFile file(filename);
222 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
223 return false;
224 }
225
226 QDomDocument doc;
227
228 // 构建完整文档
229 buildBookmarkDocument(doc);
230
231 // 写入文件
232 QTextStream out(&file);
233#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
234 out.setEncoding(QStringConverter::Utf8);
235#else
236 out.setCodec("UTF-8");
237#endif
238 out << doc.toString(4);
239
240 file.close();
241 return true;
242}
243
244void CBookmarkDatabase::buildBookmarkDocument(QDomDocument &doc)
245{
246 // XML 声明
247 QDomProcessingInstruction xmlDecl = doc.createProcessingInstruction(
248 "xml", "version=\"1.0\" encoding=\"UTF-8\""
249 );
250 doc.appendChild(xmlDecl);
251
252 // 注释
253 QDomComment comment = doc.createComment(
254 " This is an automatically generated file by Rabbit Remote Control.\n"
255 " It will be read and overwritten.\n"
256 " DO NOT EDIT! "
257 );
258 doc.appendChild(comment);
259
260 // DOCTYPE
261 QDomDocumentType doctype = doc.implementation().createDocumentType(
262 "NETSCAPE-Bookmark-file-1",
263 QString(),
264 QString()
265 );
266 doc.appendChild(doctype);
267
268 // HTML 根元素
269 QDomElement htmlElement = doc.createElement("HTML");
270 doc.appendChild(htmlElement);
271
272 // HEAD
273 QDomElement headElement = doc.createElement("HEAD");
274 htmlElement.appendChild(headElement);
275
276 // META
277 QDomElement metaElement = doc.createElement("META");
278 metaElement.setAttribute("HTTP-EQUIV", "Content-Type");
279 metaElement.setAttribute("CONTENT", "text/html; charset=UTF-8");
280 headElement.appendChild(metaElement);
281
282 // TITLE
283 QDomElement titleElement = doc.createElement("TITLE");
284 QDomText titleText = doc.createTextNode("Rabbit Remote Control - Browser: Bookmarks");
285 titleElement.appendChild(titleText);
286 headElement.appendChild(titleElement);
287
288 // BODY
289 QDomElement bodyElement = doc.createElement("BODY");
290 htmlElement.appendChild(bodyElement);
291
292 // H1
293 QDomElement h1Element = doc.createElement("H1");
294 QDomText h1Text = doc.createTextNode("Bookmarks");
295 h1Element.appendChild(h1Text);
296 bodyElement.appendChild(h1Element);
297
298 // 主 DL
299 QDomElement dlElement = doc.createElement("DL");
300 bodyElement.appendChild(dlElement);
301
302 // 构建书签树
303 buildBookmarkTree(doc, dlElement, 0);
304}
305
306void CBookmarkDatabase::buildBookmarkTree(QDomDocument &doc,
307 QDomElement &parentElement,
308 int folderId)
309{
310 // 获取该文件夹下的书签
311 QList<BookmarkItem> bookmarks = getAllBookmarks(folderId);
312
313 for (const auto &bookmark : bookmarks) {
314 QDomElement dtElement = doc.createElement("DT");
315 parentElement.appendChild(dtElement);
316
317 QDomElement aElement = createBookmarkDomElement(doc, bookmark);
318 dtElement.appendChild(aElement);
319 }
320
321 // 获取子文件夹
322 QList<BookmarkItem> subFolders = getSubFolders(folderId);
323
324 for (const auto &folder : subFolders) {
325 // 创建文件夹
326 QDomElement dtElement = doc.createElement("DT");
327 parentElement.appendChild(dtElement);
328
329 // 文件夹标题
330 QDomElement h3Element = doc.createElement("H3");
331
332 // 文件夹属性
333 if (folder.createdTime.isValid()) {
334 qint64 timestamp = folder.createdTime.toSecsSinceEpoch();
335 h3Element.setAttribute("ADD_DATE", QString::number(timestamp));
336 } else {
337 h3Element.setAttribute("ADD_DATE", "0");
338 }
339
340 // 文件夹名称
341 QDomText folderNameText = doc.createTextNode(folder.title);
342 h3Element.appendChild(folderNameText);
343
344 dtElement.appendChild(h3Element);
345
346 // 创建子 DL
347 QDomElement childDlElement = doc.createElement("DL");
348 dtElement.appendChild(childDlElement);
349
350 // 递归处理子文件夹
351 buildBookmarkTree(doc, childDlElement, folder.id);
352 }
353}
354
355QDomElement CBookmarkDatabase::createBookmarkDomElement(
356 QDomDocument &doc, const BookmarkItem &bookmark)
357{
358 QDomElement aElement = doc.createElement("A");
359
360 // 必需属性
361 aElement.setAttribute("HREF", bookmark.url);
362
363 // 时间属性
364 QDateTime defaultTime = QDateTime::currentDateTime();
365
366 qint64 addDate = bookmark.createdTime.isValid() ?
367 bookmark.createdTime.toSecsSinceEpoch() :
368 defaultTime.toSecsSinceEpoch();
369 qint64 lastVisit = bookmark.lastVisitTime.isValid() ?
370 bookmark.lastVisitTime.toSecsSinceEpoch() : 0;
371 qint64 lastModified = bookmark.modifiedTime.isValid() ?
372 bookmark.modifiedTime.toSecsSinceEpoch() :
373 addDate;
374
375 aElement.setAttribute("ADD_DATE", QString::number(addDate));
376 aElement.setAttribute("LAST_VISIT_TIME", QString::number(lastVisit));
377 aElement.setAttribute("MODIFIED_TIME", QString::number(lastModified));
378
379 // 标题
380 QString displayTitle = bookmark.title.isEmpty() ? bookmark.url : bookmark.title;
381 QDomText titleText = doc.createTextNode(displayTitle);
382 aElement.appendChild(titleText);
383
384 return aElement;
385}
386
387bool CBookmarkDatabase::importFromHtml(const QString &filename)
388{
389 QFile file(filename);
390 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
391 qWarning() << "Failed to open file for import:" << filename;
392 return false;
393 }
394
395 QTextStream in(&file);
396#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
397 in.setEncoding(QStringConverter::Utf8);
398#else
399 in.setCodec("UTF-8");
400#endif
401
402 QString content = in.readAll();
403 file.close();
404
405 qDebug(log) << "Importing HTML file:" << filename
406 << "File size:" << content.size() << "bytes";
407
408 // 检查文件格式
409 if (!content.contains("<!DOCTYPE", Qt::CaseInsensitive) ||
410 !content.contains("NETSCAPE-Bookmark-file-1", Qt::CaseInsensitive)) {
411 qWarning() << "Not a valid Netscape bookmark file:" << filename;
412 QMessageBox::warning(nullptr, tr("Format error"),
413 tr("This is not a valid bookmark file format.\n"
414 "Please select the HTML bookmark file exported from your browser."));
415 return false;
416 }
417
418 // 开始事务
419 GetDatabase().transaction();
420
421 try {
422 int importedCount = parseHtmlBookmarks(content);
423
424 if (!GetDatabase().commit()) {
425 throw QString("Failed to commit transaction: %1").arg(GetDatabase().lastError().text());
426 }
427
428 emit bookmarksChanged();
429
430 qDebug(log) << "Successfully imported" << importedCount << "bookmarks";
431 return true;
432
433 } catch (const QString &error) {
434 GetDatabase().rollback();
435 qWarning(log) << "Import failed:" << error;
436 return false;
437 }
438}
439
440int CBookmarkDatabase::parseHtmlBookmarks(const QString &htmlContent)
441{
442 int importedCount = 0;
443
444 // 解析 HTML 书签文件
445 QDomDocument doc;
446 if (!doc.setContent(htmlContent)) {
447 throw QString("Invalid HTML format");
448 }
449
450 // 查找根节点
451 QDomElement root = doc.documentElement();
452 if (root.isNull()) {
453 throw QString("No root element found");
454 }
455
456 // 查找 BODY 标签(书签列表)
457 QDomElement bodyElement = findFirstElement(root, "BODY");
458 if (bodyElement.isNull()) {
459 throw QString("No body node found");
460 }
461
462 // 查找 DL 标签(书签列表)
463 QDomElement dlElement = findFirstElement(bodyElement, "DL");
464 if (dlElement.isNull()) {
465 throw QString("No bookmarks list found");
466 }
467
468 // 递归解析书签
469 QMap<QString, int> folderMap; // 文件夹路径 -> 文件夹ID
470 folderMap["/"] = 0; // 根目录
471
472 importedCount = parseBookmarkList(dlElement, "/", folderMap);
473
474 return importedCount;
475}
476
477int CBookmarkDatabase::parseBookmarkList(const QDomElement &dlElement,
478 const QString &currentPath,
479 QMap<QString, int> &folderMap)
480{
481 int importedCount = 0;
482 QDomNode child = dlElement.firstChild();
483
484 while (!child.isNull()) {
485 QDomElement element = child.toElement();
486
487 if (!element.isNull()) {
488 QString tagName = element.tagName().toUpper();
489
490 if (tagName == "DT") {
491 // 处理 DT 节点
492 importedCount += parseDtElement(element, currentPath, folderMap);
493 } else if (tagName == "DL") {
494 // 嵌套的 DL 标签,继续解析
495 importedCount += parseBookmarkList(element, currentPath, folderMap);
496 }
497 }
498
499 child = child.nextSibling();
500 }
501
502 return importedCount;
503}
504
505int CBookmarkDatabase::parseDtElement(const QDomElement &dtElement,
506 const QString &currentPath,
507 QMap<QString, int> &folderMap)
508{
509 int importedCount = 0;
510
511 QString parentPath = currentPath;
512
513 // 查找子节点
514 QDomNode child = dtElement.firstChild();
515 while (!child.isNull()) {
516 QDomElement element = child.toElement();
517
518 if (!element.isNull()) {
519 QString tagName = element.tagName().toUpper();
520
521 if (tagName == "A") {
522 // 书签链接
523 importedCount += importBookmark(element, currentPath, folderMap);
524 } else if (tagName == "H3") {
525 // 文件夹
526 parentPath = importFolder(element, currentPath, folderMap);
527 } else if (tagName == "DL") {
528 // 嵌套的书签列表
529 importedCount += parseBookmarkList(element, parentPath, folderMap);
530 }
531 }
532
533 child = child.nextSibling();
534 }
535
536 return importedCount;
537}
538
539int CBookmarkDatabase::importBookmark(const QDomElement &aElement,
540 const QString &folderPath,
541 QMap<QString, int> &folderMap)
542{
543 // 获取链接属性
544 QString url = aElement.attribute("HREF");
545 QString title = aElement.text();
546
547 if (url.isEmpty() || title.isEmpty()) {
548 return 0;
549 }
550
551 // 获取时间戳
552 QString addDateStr = aElement.attribute("ADD_DATE");
553 QString lastVisitStr = aElement.attribute("LAST_VISIT");
554 QString lastModifiedStr = aElement.attribute("LAST_MODIFIED");
555
556 QDateTime addDate = parseTimestamp(addDateStr);
557 QDateTime lastVisit = parseTimestamp(lastVisitStr);
558 QDateTime lastModified = parseTimestamp(lastModifiedStr);
559
560 // 创建书签对象
561 BookmarkItem item;
562 item.url = url;
563 item.title = title;
564 item.createdTime = addDate.isValid() ? addDate : QDateTime::currentDateTime();
565 item.lastVisitTime = lastVisit;
566 item.modifiedTime = lastModified.isValid() ? lastModified : item.createdTime;
567
568 // 查找或创建文件夹
569 int folderId = getOrCreateFolder(folderPath, folderMap);
570 item.folderId = folderId;
571
572 // 检查是否已存在
573 auto lstExisting = getBookmarkByUrl(url);
574 if (lstExisting.isEmpty()) {
575 // 插入新书签
576 if (addBookmark(item)) {
577 qDebug(log) << "Imported bookmark:" << title << folderPath << "parentID:" << folderId;
578 return 1;
579 }
580 } else {
581 foreach(auto exist, lstExisting) {
582 // 更新现有书签
583 exist.title = item.title;
584 exist.folderId = item.folderId;
585 exist.lastVisitTime = item.lastVisitTime;
586 exist.modifiedTime = QDateTime::currentDateTime();
587
588 if (updateBookmark(exist)) {
589 qDebug(log) << "Updated existing bookmark:" << title << folderPath << "parentID:" << folderId;
590 }
591 }
592
593 return lstExisting.count();
594 }
595
596 return 0;
597}
598
599QString CBookmarkDatabase::importFolder(const QDomElement &h3Element,
600 const QString &parentPath,
601 QMap<QString, int> &folderMap)
602{
603 QString folderName = h3Element.text();
604 if (folderName.isEmpty()) {
605 return 0;
606 }
607
608 // 构建完整路径
609 QString folderPath = parentPath;
610 if (!parentPath.endsWith("/")) {
611 folderPath += "/";
612 }
613 folderPath += folderName;
614
615 // 查找父文件夹ID
616 int parentFolderId = folderMap.value(parentPath, 0);
617
618 // 创建文件夹
619 int folderId = getOrCreateFolder(folderPath, parentFolderId);
620 folderMap[folderPath] = folderId;
621
622 qDebug(log) << "Imported folder:" << folderName << "Path:" << folderPath << "ID:" << folderId;
623
624 return folderPath;
625}
626
627int CBookmarkDatabase::getOrCreateFolder(const QString &folderPath, int parentFolderId)
628{
629 if (folderPath.isEmpty() || folderPath == "/") {
630 return 0; // 根目录
631 }
632
633 // 分割路径
634 QStringList pathParts = folderPath.split("/", Qt::SkipEmptyParts);
635 if (pathParts.isEmpty()) {
636 return 0;
637 }
638
639 QString folderName = pathParts.last();
640
641 // 检查文件夹是否已存在
642 QSqlQuery query(GetDatabase());
643 query.prepare("SELECT id FROM bookmark_folders WHERE name = :name AND parent_id = :parent_id");
644 query.bindValue(":name", folderName);
645 query.bindValue(":parent_id", parentFolderId);
646
647 if (query.exec() && query.next()) {
648 return query.value(0).toInt();
649 }
650
651 // 创建新文件夹
652 query.prepare(
653 "INSERT INTO bookmark_folders (name, parent_id, created_time) "
654 "VALUES (:name, :parent_id, :created_time)"
655 );
656 query.bindValue(":name", folderName);
657 query.bindValue(":parent_id", parentFolderId);
658 query.bindValue(":created_time", QDateTime::currentDateTime());
659
660 if (query.exec()) {
661 return query.lastInsertId().toInt();
662 }
663
664 qCritical(log) << "Failed to create folder:" << folderName << query.lastError().text();
665 return 0; // 失败时返回根目录
666}
667
668int CBookmarkDatabase::getOrCreateFolder(const QString &folderPath,
669 QMap<QString, int> &folderMap)
670{
671 if (folderPath.isEmpty() || folderPath == "/") {
672 return 0;
673 }
674
675 if(folderMap.contains(folderPath))
676 return folderMap[folderPath];
677
678 QStringList pathParts = folderPath.split("/", Qt::SkipEmptyParts);
679 int currentParentId = 0;
680
681 // 逐级创建文件夹
682 for (const QString &part : pathParts) {
683 if (part.isEmpty()) continue;
684
685 currentParentId = getOrCreateFolder(part, currentParentId);
686 }
687
688 return currentParentId;
689}
690
691QDateTime CBookmarkDatabase::parseTimestamp(const QString &timestampStr)
692{
693 if (timestampStr.isEmpty()) {
694 return QDateTime();
695 }
696
697 bool ok;
698 qint64 timestamp = timestampStr.toLongLong(&ok);
699
700 if (!ok) {
701 return QDateTime();
702 }
703
704 // 处理不同精度的时间戳
705 if (timestamp > 10000000000) {
706 // 毫秒时间戳
707 return QDateTime::fromMSecsSinceEpoch(timestamp);
708 } else {
709 // 秒时间戳
710 return QDateTime::fromSecsSinceEpoch(timestamp);
711 }
712}
713
714QDomElement CBookmarkDatabase::findFirstElement(const QDomElement &parent, const QString &tagName)
715{
716 QDomNode child = parent.firstChild();
717
718 while (!child.isNull()) {
719 QDomElement element = child.toElement();
720
721 if (!element.isNull() && element.tagName().toUpper() == tagName.toUpper()) {
722 return element;
723 }
724
725 child = child.nextSibling();
726 }
727
728 return QDomElement();
729}
730
731TreeItem CBookmarkDatabase::BookmarkToTree(const BookmarkItem& tree, bool setKey)
732{
733 TreeItem item;
734 TreeItem::TYPE type;
735 type = tree.type == BookmarkType_Folder ? TreeItem::Node: TreeItem::Leaf;
736 item.SetType(type);
737 item.SetId(tree.id);
738 item.SetParentId(tree.folderId);
739 item.SetCreateTime(tree.createdTime);
740 item.SetModifyTime(tree.modifiedTime);
741 item.SetLastVisitTime(tree.lastVisitTime);
742 if(setKey && BookmarkType_Bookmark == tree.type && !tree.url.isEmpty()) {
743 int id = m_UrlDB.GetId(tree.url);
744 item.SetKey(id);
745 }
746 return item;
747}
748
749BookmarkItem CBookmarkDatabase::TreeToBookmark(const TreeItem& tree)
750{
751 BookmarkItem item;
752 CDatabaseUrl::UrlItem url = m_UrlDB.GetItem(tree.GetKey());
753 item = TreeToBookmark(tree, url);
754 return item;
755}
756
757BookmarkItem CBookmarkDatabase::TreeToBookmark(
758 const TreeItem& tree, const CDatabaseUrl::UrlItem& url)
759{
760 BookmarkItem item;
761 item.id = tree.GetId();
762 item.folderId = tree.GetParentId();
763 item.createdTime = tree.GetCreateTime();
764 item.modifiedTime = tree.GetModifyTime();
765 item.lastVisitTime = tree.GetLastVisitTime();
766
767 if(tree.IsNode()) {
768 item.type = BookmarkType_Folder;
769 item.title = tree.GetName();
770 } else {
771 item.type = BookmarkType_Bookmark;
772 item.title = url.szTitle;
773 item.url = url.szUrl;
774 item.icon = url.icon;
775 }
776 return item;
777}
778
779
780bool CBookmarkDatabase::ExportToJson(QJsonObject &obj)
781{
782 return true;
783}
784
785bool CBookmarkDatabase::ImportFromJson(const QJsonObject &obj)
786{
787 return true;
788}
virtual int Add(const TreeItem &item)
Add item
QList< TreeItem > GetLeavesByKey(int key)
Get leaves
QList< TreeItem > GetLeaves(int nodeId)
Get the leaves under nodeId