4#include <QJsonDocument>
11#include <QLoggingCategory>
12#include "FavoriteDatabase.h"
15static Q_LOGGING_CATEGORY(log,
"App.Favorite.Db")
19 qDebug(log) << Q_FUNC_INFO;
22bool CFavoriteDatabase::OnInitializeSqliteDatabase()
24 QSqlQuery query(GetDatabase());
28 "CREATE TABLE IF NOT EXISTS favorite ("
29 " id INTEGER PRIMARY KEY AUTOINCREMENT,"
30 " name TEXT NOT NULL,"
31 " icon INTEGER DEFAULT 0,"
32 " file TEXT UNIQUE NOT NULL,"
35 bool success = query.exec(szSql);
38 SetError(
"Failed to create favorite table: " + query.lastError().text()
40 qCritical(log) << GetError();
45 success = query.exec(
"CREATE INDEX IF NOT EXISTS idx_favorite_file ON favorite(file)");
47 qWarning(log) <<
"Failed to create idx_favorite_file." << query.lastError().text();
51 if (!query.exec(
"DROP TRIGGER IF EXISTS delete_icon_after_favorite")) {
52 qDebug(log) <<
"Failed to drop trigger delete_icon_after_favorite:" << query.lastError().text();
56 CREATE TRIGGER delete_icon_after_favorite
57 AFTER DELETE ON favorite
64 SELECT 1 FROM favorite WHERE icon = OLD.icon
67 SELECT 1 FROM recent WHERE icon = OLD.icon
71 success = query.exec(szSql);
73 qWarning(log) <<
"Failed to create trigger delete_icon_after_favorite." << query.lastError().text();
75 success = CDatabaseTree::OnInitializeSqliteDatabase();
79bool CFavoriteDatabase::OnInitializeMySqlDatabase()
82 QSqlQuery query(GetDatabase());
86 "CREATE TABLE IF NOT EXISTS favorite ("
87 " id INTEGER PRIMARY KEY AUTO_INCREMENT,"
88 " name TEXT NOT NULL,"
89 " icon INTEGER DEFAULT 0,"
90 " file TEXT NOT NULL,"
92 " UNIQUE KEY uk_favorite_file (file(255))"
94 success = query.exec(szSql);
96 SetError(
"Failed to create favorite table: "
97 + query.lastError().text()
99 qCritical(log) << GetError();
104 if (!query.exec(
"DROP TRIGGER IF EXISTS delete_icon_after_favorite")) {
105 qDebug(log) <<
"Failed to drop trigger delete_icon_after_favorite:"
106 << query.lastError().text()
107 <<
"Sql:" << query.executedQuery();
111 CREATE TRIGGER delete_icon_after_favorite
112 AFTER DELETE ON favorite
115 DECLARE favorite_count INT DEFAULT 0;
116 DECLARE recent_count INT DEFAULT 0;
118 IF OLD.icon != 0 THEN
119 -- 统计favorite表中引用该icon的数量
120 SELECT COUNT(*) INTO favorite_count
122 WHERE icon = OLD.icon;
124 -- 统计recent表中引用该icon的数量
125 SELECT COUNT(*) INTO recent_count
127 WHERE icon = OLD.icon;
130 IF favorite_count = 0 AND recent_count = 0 THEN
131 DELETE FROM icon WHERE id = OLD.icon;
136 success = query.exec(szSql);
138 qWarning(log) <<
"Failed to create trigger delete_icon_after_favorite."
139 << query.lastError().text()
140 <<
"Sql:" << query.executedQuery();
143 return CDatabaseTree::OnInitializeMySqlDatabase();
150 if(!bRet)
return false;
151 bRet = m_IconDB.
SetDatabase(GetDatabase(), m_pPara);
152 if(!bRet)
return false;
153 bRet = m_FileDB.
SetDatabase(GetDatabase(), m_pPara);
157int CFavoriteDatabase::AddFavorite(
const QString &szFile,
158 const QString &szName,
const QIcon &icon,
159 const QString szDescription,
int parentId)
162 if (szName.trimmed().isEmpty()) {
163 qWarning(log) <<
"Favorite name cannot be empty";
167 if (szFile.trimmed().isEmpty()) {
168 qCritical(log) <<
"Favorite file cannot be empty";
174 if (GetNode(parentId).GetId() == 0) {
175 qWarning(log) <<
"Parent item with ID" << parentId <<
"does not exist";
180 QSqlDatabase db = GetDatabase();
181 bool success =
false;
183 if (!db.transaction()) {
184 SetError(
"Failed to start transaction: " + db.lastError().text());
185 qCritical(log) << GetError();
194 "SELECT id FROM favorite "
196 query.bindValue(
":file", szFile);
197 if(query.exec() && query.next()) {
198 key = query.value(0).toInt();
204 "INSERT INTO favorite (name, icon, file, description)"
205 "VALUES (:name, :icon, :file, :description)"
207 query.bindValue(
":name", szName);
208 query.bindValue(
":icon", m_IconDB.
GetIcon(icon));
209 query.bindValue(
":file", szFile);
210 query.bindValue(
":description", szDescription);
212 success = query.exec();
214 QString szErr =
"Failed to insert favorite table: " + query.lastError().text();
216 throw std::runtime_error(szErr.toStdString());
219 key = query.lastInsertId().toInt();
221 QString szErr =
"Failed to insert favorite table";
223 throw std::runtime_error(szErr.toStdString());
230 item.SetParentId(parentId);
233 QString szErr =
"Failed to insert favorite folder table";
235 throw std::runtime_error(szErr.toStdString());
240 QString szErr =
"Failed to commit transaction:" + db.lastError().text();
242 throw std::runtime_error(szErr.toStdString());
245 qDebug(log) <<
"Successfully added favorite:" << szName <<
"ID:" << key <<
"Parent:" << parentId;
248 }
catch (
const std::exception &e) {
249 qCritical(log) <<
"Exception in AddFavorite:" << e.what();
252 qCritical(log) <<
"Unknown exception in AddFavorite";
259bool CFavoriteDatabase::UpdateFavorite(
260 int id,
const QString& szName,
261 const QIcon &icon,
const QString szDescription)
263 QSqlQuery query(GetDatabase());
265 if(!szName.isEmpty())
266 szSql +=
"name=\"" + szName +
"\"";
270 szSql +=
"icon=" + QString::number(m_IconDB.
GetIcon(icon));
272 if(!szDescription.isEmpty()) {
275 szSql +=
"description=\"" + szDescription +
"\"";
278 szSql =
"UPDATE favorite SET " + szSql +
" WHERE id=" + QString::number(
id);
280 bool ok = query.exec(szSql);
282 SetError(
"Failed to update favorite: " + query.lastError().text()
283 +
"; Sql: " + szSql);
284 qCritical(log) << GetError();
289bool CFavoriteDatabase::UpdateFavorite(
290 const QString &szFile,
const QString &szName,
291 const QIcon &icon,
const QString szDescription)
293 QSqlQuery query(GetDatabase());
295 if(!szName.isEmpty())
296 szSql +=
"name=\"" + szName +
"\"";
300 szSql +=
"icon=" + QString::number(m_IconDB.
GetIcon(icon));
302 if(!szDescription.isEmpty()) {
305 szSql +=
"description=\"" + szDescription +
"\"";
308 szSql =
"UPDATE favorite SET " + szSql +
" WHERE file=\"" + szFile +
"\"";
310 bool ok = query.exec(szSql);
312 SetError(
"Failed to update favorite: " + query.lastError().text()
313 +
"; Sql: " + szSql);
314 qCritical(log) << GetError();
321 Item item(TreeItem::Leaf);
322 auto leaf = GetLeaf(
id);
323 if(leaf.GetId() == 0)
326 QSqlQuery query(GetDatabase());
328 "SELECT id, name, icon, file, description FROM favorite "
331 query.bindValue(
":id", leaf.GetKey());
334 bool ok = query.exec();
336 SetError(
"Failed to get favorite: " + query.lastError().text()
337 +
"; Sql: " + query.executedQuery()
338 +
"; id: " + QString::number(
id));
339 qCritical(log) << GetError();
343 item.id = leaf.GetId();
344 item.parentId = leaf.GetParentId();
345 item.szName = query.value(1).toString();
346 item.icon = m_IconDB.
GetIcon(query.value(2).toInt());
347 item.szFile = query.value(3).toString();
348 item.szDescription = query.value(4).toString();
349 item.type = TreeItem::Leaf;
354QList<CFavoriteDatabase::Item> CFavoriteDatabase::GetFavorite(
const QString &szFile)
356 QList<CFavoriteDatabase::Item> lstItems;
357 Item item(TreeItem::Leaf);
359 QSqlQuery query(GetDatabase());
361 "SELECT id, name, icon, file, description FROM favorite "
364 query.bindValue(
":file", szFile);
367 bool ok = query.exec();
369 SetError(
"Failed to get favorite: " + query.lastError().text()
370 +
"; Sql: " + query.executedQuery() +
"; szFile: " + szFile);;
371 qCritical(log) << GetError();
375 item.szName = query.value(1).toString();
376 item.icon = m_IconDB.
GetIcon(query.value(2).toInt());
377 item.szFile = query.value(3).toString();
378 item.szDescription = query.value(4).toString();
379 item.type = TreeItem::Leaf;
382 foreach(
auto l, leaf) {
384 item.parentId = l.GetParentId();
393 auto f = GetNode(
id);
394 Item item(f.GetType());
396 item.parentId = f.GetParentId();
397 item.szName = f.GetName();
401QList<CFavoriteDatabase::Item> CFavoriteDatabase::GetChildren(
int parentId)
403 QList<Item> children;
405 auto folders = GetSubNodes(parentId);
406 foreach(
auto f, folders) {
407 Item item(f.GetType());
409 item.parentId = f.GetParentId();
410 item.szName = f.GetName();
415 foreach(
auto l, leaves) {
416 Item item = GetFavorite(l.GetId());
424 QSqlQuery query(GetDatabase());
426 "DELETE FROM favorite "
429 query.bindValue(
":id", key);
432 bool ok = query.exec();
434 SetError(
"Failed to delete favorite: " + query.lastError().text()
435 +
"; Sql: " + query.executedQuery()
436 +
"; key: " + QString::number(key));
437 qCritical(log) << GetError();
443bool CFavoriteDatabase::ExportToJson(QJsonObject &obj)
447 bRet = ExportToJson(0, root);
449 obj.insert(
"favorite", root);
453bool CFavoriteDatabase::ImportFromJson(
const QJsonObject &obj)
455 QJsonArray favorites = obj[
"favorite"].toArray();
456 if(favorites.isEmpty()) {
457 SetError(tr(
"The file format is error. Json without \"favorite\""));
458 qCritical(log) << GetError();
462 return ImportFromJson(0, favorites);
465bool CFavoriteDatabase::ImportFromJson(
int parentId,
const QJsonArray &obj)
467 for(
auto it = obj.begin(); it != obj.end(); it++) {
468 QJsonObject itemObj = it->toObject();
469 if(itemObj.isEmpty())
continue;
470 if(TreeItem::Node == itemObj[
"type"].toInt()) {
471 QString szName = itemObj[
"name"].toString();
472 int id = AddNode(szName, parentId);
473 QJsonArray items = itemObj[szName].toArray();
474 if(items.isEmpty())
continue;
475 ImportFromJson(
id, items);
483 bRet = CDatabaseIcon::ImportIconFromJson(itemObj, icon);
486 AddFavorite(
CDatabaseFile::SetFile(szFile), itemObj[
"name"].toString(), icon, itemObj[
"description"].toString(), parentId);
492bool CFavoriteDatabase::ExportToJson(
int parentId, QJsonArray &obj)
494 auto items = GetChildren(parentId);
495 foreach(
auto item, items) {
497 if(item.isFolder()) {
499 bool bRet = ExportToJson(item.id, aItem);
502 oItem.insert(
"type", TreeItem::Node);
503 oItem.insert(
"name", item.szName);
504 oItem.insert(item.szName, aItem);
507 oItem.insert(
"type", item.type);
508 oItem.insert(
"name", item.szName);
515 bRet = CDatabaseIcon::ExportIconToJson(item.GetIcon(), oItem);
518 oItem.insert(
"description", item.szDescription);
bool ImportFileToDatabaseFromJson(const QJsonObject &obj, QString &szFile)
Import file to database from JSON
static bool ExportFileToJson(const QString &szFile, QJsonObject &obj)
ExportFileToJson
static QString SetFile(const QString &szFile)
Set the file with file system to the file in database
static QString GetFile(const QString &szFile)
Get the file with file system from the file in database
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 OnInitializeDatabase() override
Initialize database
bool SetDatabase(const CDatabase *db)
Share an existing database
The CFavoriteDatabase class
bool OnInitializeDatabase() override
Initialize database
virtual bool OnDeleteKey(int key) override
从 key 相关的表中删除 key