3#include <QJsonDocument>
10#include <QLoggingCategory>
11#include "FavoriteDatabase.h"
14static Q_LOGGING_CATEGORY(log,
"App.Favorite.Db")
18 qDebug(log) << Q_FUNC_INFO;
21bool CFavoriteDatabase::OnInitializeSqliteDatabase()
23 QSqlQuery query(GetDatabase());
26 bool success = query.exec(
27 "CREATE TABLE IF NOT EXISTS favorite ("
28 " id INTEGER PRIMARY KEY AUTOINCREMENT,"
29 " name TEXT NOT NULL,"
30 " icon INTEGER DEFAULT 0,"
31 " file TEXT UNIQUE NOT NULL,"
37 qCritical(log) <<
"Failed to create favorite table:" << query.lastError().text();
42 success = query.exec(
"CREATE INDEX IF NOT EXISTS idx_favorite_file ON favorite(file)");
44 qWarning(log) <<
"Failed to create idx_favorite_file." << query.lastError().text();
48 if (!query.exec(
"DROP TRIGGER IF EXISTS delete_icon_after_favorite")) {
49 qDebug(log) <<
"Failed to drop trigger delete_icon_after_favorite:" << query.lastError().text();
53 CREATE TRIGGER delete_icon_after_favorite
54 AFTER DELETE ON favorite
61 SELECT 1 FROM favorite WHERE icon = OLD.icon
64 SELECT 1 FROM recent WHERE icon = OLD.icon
68 success = query.exec(szSql);
70 qWarning(log) <<
"Failed to create trigger delete_icon_after_favorite." << query.lastError().text();
72 success = CDatabaseTree::OnInitializeSqliteDatabase();
76bool CFavoriteDatabase::OnInitializeMySqlDatabase()
79 QSqlQuery query(GetDatabase());
83 "CREATE TABLE IF NOT EXISTS favorite ("
84 " id INTEGER PRIMARY KEY AUTO_INCREMENT,"
85 " name TEXT NOT NULL,"
86 " icon INTEGER DEFAULT 0,"
87 " file TEXT NOT NULL,"
89 " UNIQUE KEY uk_favorite_file (file(255))"
93 qCritical(log) <<
"Failed to create favorite table:"
94 << query.lastError().text()
95 <<
"Sql:" << query.executedQuery();
100 if (!query.exec(
"DROP TRIGGER IF EXISTS delete_icon_after_favorite")) {
101 qDebug(log) <<
"Failed to drop trigger delete_icon_after_favorite:"
102 << query.lastError().text()
103 <<
"Sql:" << query.executedQuery();
107 CREATE TRIGGER delete_icon_after_favorite
108 AFTER DELETE ON favorite
111 DECLARE favorite_count INT DEFAULT 0;
112 DECLARE recent_count INT DEFAULT 0;
114 IF OLD.icon != 0 THEN
115 -- 统计favorite表中引用该icon的数量
116 SELECT COUNT(*) INTO favorite_count
118 WHERE icon = OLD.icon;
120 -- 统计recent表中引用该icon的数量
121 SELECT COUNT(*) INTO recent_count
123 WHERE icon = OLD.icon;
126 IF favorite_count = 0 AND recent_count = 0 THEN
127 DELETE FROM icon WHERE id = OLD.icon;
132 success = query.exec(szSql);
134 qWarning(log) <<
"Failed to create trigger delete_icon_after_favorite."
135 << query.lastError().text()
136 <<
"Sql:" << query.executedQuery();
139 return CDatabaseTree::OnInitializeMySqlDatabase();
142bool CFavoriteDatabase::OnInitializeDatabase()
145 bRet = CDatabaseTree::OnInitializeDatabase();
146 if(!bRet)
return false;
148 m_IconDB.SetDatabase(GetDatabase(), m_pPara);
149 bRet = m_IconDB.OnInitializeDatabase();
150 if(!bRet)
return false;
151 m_FileDB.SetDatabase(GetDatabase(), m_pPara);
152 bRet = m_FileDB.OnInitializeDatabase();
156int CFavoriteDatabase::AddFavorite(
const QString &szFile,
157 const QString &szName,
const QIcon &icon,
158 const QString szDescription,
int parentId)
161 if (szName.trimmed().isEmpty()) {
162 qWarning(log) <<
"Favorite name cannot be empty";
166 if (szFile.trimmed().isEmpty()) {
167 qCritical(log) <<
"Favorite file cannot be empty";
173 if (GetNode(parentId).GetId() == 0) {
174 qWarning(log) <<
"Parent item with ID" << parentId <<
"does not exist";
179 QSqlDatabase db = GetDatabase();
180 bool success =
false;
182 if (!db.transaction()) {
183 qCritical(log) <<
"Failed to start transaction:" << db.lastError().text();
192 "SELECT id FROM favorite "
194 query.bindValue(
":file", szFile);
195 if(query.exec() && query.next()) {
196 key = query.value(0).toInt();
202 "INSERT INTO favorite (name, icon, file, description)"
203 "VALUES (:name, :icon, :file, :description)"
205 query.bindValue(
":name", szName);
206 query.bindValue(
":icon", m_IconDB.
GetIcon(icon));
207 query.bindValue(
":file", szFile);
208 query.bindValue(
":description", szDescription);
210 success = query.exec();
212 QString szErr =
"Failed to insert favorite table: " + query.lastError().text();
213 qCritical(log) << szErr;
214 throw std::runtime_error(szErr.toStdString());
217 key = query.lastInsertId().toInt();
219 QString szErr =
"Failed to insert favorite table";
220 throw std::runtime_error(szErr.toStdString());
227 item.SetParentId(parentId);
230 QString szErr =
"Failed to insert favorite folder table";
231 throw std::runtime_error(szErr.toStdString());
236 QString szErr =
"Failed to commit transaction:" + db.lastError().text();
237 throw std::runtime_error(szErr.toStdString());
240 qDebug(log) <<
"Successfully added favorite:" << szName <<
"ID:" << key <<
"Parent:" << parentId;
243 }
catch (
const std::exception &e) {
244 qCritical(log) <<
"Exception in AddFavorite:" << e.what();
247 qCritical(log) <<
"Unknown exception in AddFavorite";
254bool CFavoriteDatabase::UpdateFavorite(
255 int id,
const QString& szName,
256 const QIcon &icon,
const QString szDescription)
258 QSqlQuery query(GetDatabase());
260 if(!szName.isEmpty())
261 szSql +=
"name=\"" + szName +
"\"";
265 szSql +=
"icon=" + QString::number(m_IconDB.
GetIcon(icon));
267 if(!szDescription.isEmpty()) {
270 szSql +=
"description=\"" + szDescription +
"\"";
273 szSql =
"UPDATE favorite SET " + szSql +
" WHERE id=" + QString::number(
id);
275 bool ok = query.exec(szSql);
277 qCritical(log) <<
"Failed to update favorite:"
278 <<
id << query.lastError().text()
283bool CFavoriteDatabase::UpdateFavorite(
284 const QString &szFile,
const QString &szName,
285 const QIcon &icon,
const QString szDescription)
287 QSqlQuery query(GetDatabase());
289 if(!szName.isEmpty())
290 szSql +=
"name=\"" + szName +
"\"";
294 szSql +=
"icon=" + QString::number(m_IconDB.
GetIcon(icon));
296 if(!szDescription.isEmpty()) {
299 szSql +=
"description=\"" + szDescription +
"\"";
302 szSql =
"UPDATE favorite SET " + szSql +
" WHERE file=\"" + szFile +
"\"";
304 bool ok = query.exec(szSql);
306 qCritical(log) <<
"Failed to update favorite:"
307 << szFile << query.lastError().text()
315 item.type = TreeItem::Leaf;
316 auto leaf = GetLeaf(
id);
317 if(leaf.GetId() == 0)
320 QSqlQuery query(GetDatabase());
322 "SELECT id, name, icon, file, description FROM favorite "
325 query.bindValue(
":id", leaf.GetKey());
328 bool ok = query.exec();
330 qCritical(log) <<
"Failed to get favorite:"
331 <<
id << query.lastError().text()
332 <<
"Sql:" << query.executedQuery();
336 item.id = leaf.GetId();
337 item.parentId = leaf.GetParentId();
338 item.szName = query.value(1).toString();
339 item.icon = m_IconDB.
GetIcon(query.value(2).toInt());
340 item.szFile = query.value(3).toString();
341 item.szDescription = query.value(4).toString();
342 item.type = TreeItem::Leaf;
347QList<CFavoriteDatabase::Item> CFavoriteDatabase::GetFavorite(
const QString &szFile)
349 QList<CFavoriteDatabase::Item> lstItems;
351 item.type = TreeItem::Leaf;
353 QSqlQuery query(GetDatabase());
355 "SELECT id, name, icon, file, description FROM favorite "
358 query.bindValue(
":file", szFile);
361 bool ok = query.exec();
363 qCritical(log) <<
"Failed to get favorite:"
364 << szFile << query.lastError().text()
365 <<
"Sql:" << query.executedQuery();
369 item.szName = query.value(1).toString();
370 item.icon = m_IconDB.
GetIcon(query.value(2).toInt());
371 item.szFile = query.value(3).toString();
372 item.szDescription = query.value(4).toString();
373 item.type = TreeItem::Leaf;
376 foreach(
auto l, leaf) {
378 item.parentId = l.GetParentId();
387 auto f = GetNode(
id);
390 item.parentId = f.GetParentId();
391 item.szName = f.GetName();
392 item.type = f.GetType();
396QList<CFavoriteDatabase::Item> CFavoriteDatabase::GetChildren(
int parentId)
398 QList<Item> children;
400 auto folders = GetSubNodes(parentId);
401 foreach(
auto f, folders) {
404 item.parentId = f.GetParentId();
405 item.szName = f.GetName();
406 item.type = f.GetType();
411 foreach(
auto l, leaves) {
412 Item item = GetFavorite(l.GetId());
420 QSqlQuery query(GetDatabase());
422 "DELETE FROM favorite "
425 query.bindValue(
":id", key);
428 bool ok = query.exec();
430 qCritical(log) <<
"Failed to delete favorite:"
431 << key << query.lastError().text()
432 <<
"Sql:" << query.executedQuery();
438bool CFavoriteDatabase::ExportToJson(QJsonObject &obj)
442 bRet = ExportToJson(0, root);
444 obj.insert(
"favorite", root);
448bool CFavoriteDatabase::ImportFromJson(
const QJsonObject &obj)
450 QJsonArray favorites = obj[
"favorite"].toArray();
451 if(favorites.isEmpty()) {
452 qCritical(log) <<
"The file format is error. Json without favorite";
456 return ImportFromJson(0, favorites);
459bool CFavoriteDatabase::ImportFromJson(
int parentId,
const QJsonArray &obj)
461 for(
auto it = obj.begin(); it != obj.end(); it++) {
462 QJsonObject itemObj = it->toObject();
463 if(itemObj.isEmpty())
continue;
464 if(TreeItem::Node == itemObj[
"type"].toInt()) {
465 QString szName = itemObj[
"name"].toString();
466 int id = AddNode(szName, parentId);
467 QJsonArray items = itemObj[szName].toArray();
468 if(items.isEmpty())
continue;
469 ImportFromJson(
id, items);
474 bool bRet = m_FileDB.ImportFileToDatabaseFromJson(itemObj, szFile);
477 bRet = CDatabaseIcon::ImportIconFromJson(itemObj, icon);
480 AddFavorite(szFile, itemObj[
"name"].toString(), icon, itemObj[
"description"].toString(), parentId);
486bool CFavoriteDatabase::ExportToJson(
int parentId, QJsonArray &obj)
488 auto items = GetChildren(parentId);
489 foreach(
auto item, items) {
491 if(item.isFolder()) {
493 bool bRet = ExportToJson(item.id, aItem);
496 oItem.insert(
"type", TreeItem::Node);
497 oItem.insert(
"name", item.szName);
498 oItem.insert(item.szName, aItem);
501 oItem.insert(
"type", item.type);
502 oItem.insert(
"name", item.szName);
505 bool bRet = CDatabaseFile::ExportFileToJson(item.szFile, oItem);
509 bRet = CDatabaseIcon::ExportIconToJson(item.GetIcon(), oItem);
512 oItem.insert(
"description", item.szDescription);
int GetIcon(const QIcon &icon)
Get icon id
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
virtual bool OnDeleteKey(int key) override
从 key 相关的表中删除 key