玉兔远程控制 0.1.0-bate6
载入中...
搜索中...
未找到
RecentDatabase.cpp
1// Author: Kang Lin <kl222@126.com>
2
3#include <QSettings>
4#include <QFile>
5#include <QFileInfo>
6#include <QIcon>
7#include <QSqlQuery>
8#include <QSqlError>
9#include <QDateTime>
10#include <QJsonArray>
11#include <QJsonObject>
12#include <QLoggingCategory>
13#include "RecentDatabase.h"
14#include "IconUtils.h"
15#include "RabbitCommonDir.h"
16
17static Q_LOGGING_CATEGORY(log, "App.Recent.Db")
18CRecentDatabase::CRecentDatabase(QObject *parent)
19 : CDatabase{parent}
20{
21 qDebug(log) << Q_FUNC_INFO;
22}
23
24CRecentDatabase::~CRecentDatabase()
25{
26 qDebug(log) << Q_FUNC_INFO;
27 CloseDatabase();
28}
29
30bool CRecentDatabase::OnInitializeDatabase()
31{
32 bool bRet = false;
33 bRet = CDatabase::OnInitializeDatabase();
34 if(!bRet) return false;
35
36 // Create icon table
37 m_IconDB.SetDatabase(GetDatabase(), m_pPara);
38 bRet = m_IconDB.OnInitializeDatabase();
39 if(!bRet) return bRet;
40 m_FileDB.SetDatabase(GetDatabase(), m_pPara);
41 bRet = m_FileDB.OnInitializeDatabase();
42 return bRet;
43}
44
45bool CRecentDatabase::OnInitializeSqliteDatabase()
46{
47 QSqlQuery query(GetDatabase());
48
49 // Create recent table
50 bool success = query.exec(
51 "CREATE TABLE IF NOT EXISTS recent ("
52 " id INTEGER PRIMARY KEY AUTOINCREMENT,"
53 " operate_id TEXT NOT NULL,"
54 " icon INTEGER DEFAULT 0,"
55 " name TEXT NOT NULL,"
56 " protocol TEXT,"
57 " operate_type TEXT,"
58 " file TEXT UNIQUE NOT NULL,"
59 " time DATETIME DEFAULT CURRENT_TIMESTAMP,"
60 " description TEXT"
61 ")"
62 );
63
64 if (!success) {
65 qCritical(log) << "Failed to create recent table:" << query.lastError().text();
66 return false;
67 }
68
69 // Create index
70 success = query.exec("CREATE INDEX IF NOT EXISTS idx_recent_file ON recent(file)");
71 if(!success) {
72 qWarning(log) << "Failed to drop index idx_recent_file:"
73 << query.lastError().text()
74 << "Sql:" << query.executedQuery();
75 }
76
77 if (!query.exec("DROP TRIGGER IF EXISTS delete_icon_after_recent")) {
78 qDebug(log) << "Failed to drop trigger delete_icon_after_recent:"
79 << query.lastError().text()
80 << "Sql:" << query.executedQuery();
81 }
82
83 QString szSql = R"(
84 CREATE TRIGGER delete_icon_after_recent
85 AFTER DELETE ON recent
86 FOR EACH ROW
87 BEGIN
88 DELETE FROM icon
89 WHERE id = OLD.icon
90 AND OLD.icon != 0
91 AND NOT EXISTS (
92 SELECT 1 FROM favorite WHERE icon = OLD.icon
93 )
94 AND NOT EXISTS (
95 SELECT 1 FROM recent WHERE icon = OLD.icon
96 );
97 END;
98 )";
99 success = query.exec(szSql);
100 if (!success) {
101 qWarning(log) << "Failed to create trigger delete_icon_after_recent."
102 << query.lastError().text()
103 << "Sql:" << query.executedQuery();
104 }
105
106 return true;
107}
108
109bool CRecentDatabase::OnInitializeMySqlDatabase()
110{
111 bool success = false;
112 QSqlQuery query(GetDatabase());
113
114 // Create recent table
115 success = query.exec(
116 "CREATE TABLE IF NOT EXISTS recent ("
117 " id INTEGER PRIMARY KEY AUTO_INCREMENT,"
118 " operate_id TEXT NOT NULL,"
119 " icon INTEGER DEFAULT 0,"
120 " name TEXT NOT NULL,"
121 " protocol TEXT,"
122 " operate_type TEXT,"
123 " file TEXT NOT NULL,"
124 " time DATETIME DEFAULT CURRENT_TIMESTAMP,"
125 " description TEXT,"
126 " UNIQUE KEY uk_recent_file (file(255))"
127 ")"
128 );
129 if (!success) {
130 qCritical(log) << "Failed to create recent table:"
131 << query.lastError().text()
132 << "Sql:" << query.executedQuery();
133 return false;
134 }
135
136 // Create trigger
137 if (!query.exec("DROP TRIGGER IF EXISTS delete_icon_after_recent")) {
138 qDebug(log) << "Failed to drop trigger delete_icon_after_recent:"
139 << query.lastError().text()
140 << "Sql:" << query.executedQuery();
141 }
142
143 QString szSql = R"(
144 CREATE TRIGGER delete_icon_after_recent
145 AFTER DELETE ON recent
146 FOR EACH ROW
147 BEGIN
148 DECLARE favorite_count INT DEFAULT 0;
149 DECLARE recent_count INT DEFAULT 0;
150
151 IF OLD.icon != 0 THEN
152 -- 统计favorite表中引用该icon的数量
153 SELECT COUNT(*) INTO favorite_count
154 FROM favorite
155 WHERE icon = OLD.icon;
156
157 -- 统计recent表中引用该icon的数量
158 SELECT COUNT(*) INTO recent_count
159 FROM recent
160 WHERE icon = OLD.icon;
161
162 -- 如果都没有引用,则删除icon
163 IF favorite_count = 0 AND recent_count = 0 THEN
164 DELETE FROM icon WHERE id = OLD.icon;
165 END IF;
166 END IF;
167 END
168 )";
169 success = query.exec(szSql);
170 if (!success) {
171 qWarning(log) << "Failed to create trigger delete_icon_after_recent."
172 << query.lastError().text()
173 << "Sql:" << query.executedQuery();
174 }
175
176 return true;
177}
178
179int CRecentDatabase::AddRecent(const RecentItem &item)
180{
181 QSqlQuery query(GetDatabase());
182 if(item.szFile.isEmpty())
183 return -1;
184 query.prepare(
185 "SELECT id FROM recent "
186 "WHERE file=:file"
187 );
188 query.bindValue(":file", item.szFile);
189 if (query.exec() && query.next()) {
190 // 更新现有记录
191 int id = query.value(0).toInt();
192
193 query.prepare(
194 "UPDATE recent SET "
195 "name=:name, "
196 "time=:time, "
197 "description=:description "
198 "WHERE id=:id"
199 );
200 query.bindValue(":name", item.szName);
201 query.bindValue(":time", item.time);
202 query.bindValue(":description", item.szDescription);
203 query.bindValue(":id", id);
204 } else {
205 query.prepare(
206 "INSERT INTO recent (operate_id, icon, name, protocol, operate_type, file, time, description)"
207 "VALUES (:operate_id, :icon, :name, :protocol, :type, :file, :time, :description)"
208 );
209 query.bindValue(":operate_id", item.szOperateId);
210 query.bindValue(":icon", m_IconDB.GetIcon(item.icon));
211 query.bindValue(":name", item.szName);
212 query.bindValue(":protocol", item.szProtocol);
213 query.bindValue(":type", item.szType);
214 query.bindValue(":file", item.szFile);
215 query.bindValue(":time", item.time);
216 query.bindValue(":description", item.szDescription);
217 }
218 bool success = query.exec();
219 if (!success) {
220 qCritical(log) << "Failed to add recent:" << query.lastError().text();
221 return 0;
222 }
223
224 qDebug(log) << "Insert recent id:" << query.lastInsertId().toInt();
225 emit sigChanged();
226 return query.lastInsertId().toInt();
227}
228
229bool CRecentDatabase::UpdateRecent(
230 const QString &szFile, const QString& szName, const QString& szDescription)
231{
232 QSqlQuery query(GetDatabase());
233
234 query.prepare(
235 "UPDATE recent SET "
236 "name=:name, "
237 "description=:description "
238 "WHERE file=:file"
239 );
240 query.bindValue(":name", szName);
241 query.bindValue(":file", szFile);
242 query.bindValue(":description", szDescription);
243
244 bool success = query.exec();
245 if (!success) {
246 qCritical(log) << "Failed to update recent:" << query.lastError().text();
247 }
248 emit sigChanged();
249 return success;
250}
251
252bool CRecentDatabase::DeleteRecent(int id)
253{
254 if(0 >= id) return false;
255 QSqlQuery query(GetDatabase());
256 query.prepare("DELETE FROM recent WHERE id=:id");
257 query.bindValue(":id", id);
258 bool success = query.exec();
259 if (!success) {
260 qCritical(log) << "Failed to delete recent id:"
261 << id << query.lastError().text();
262 }
263 return success;
264}
265
266QList<CRecentDatabase::RecentItem> CRecentDatabase::GetRecents(int limit, int offset)
267{
268 QList<RecentItem> items;
269
270 QSqlQuery query(GetDatabase());
271 if(0 > limit) {
272 query.prepare(
273 "SELECT id, operate_id, icon, name, protocol, operate_type, file, time, description "
274 "FROM recent "
275 "ORDER BY time DESC "
276 );
277 } else {
278 query.prepare(
279 "SELECT id, operate_id, icon, name, protocol, operate_type, file, time, description "
280 "FROM recent "
281 "ORDER BY time DESC "
282 "LIMIT :limit OFFSET :offset"
283 );
284 query.bindValue(":limit", limit);
285 query.bindValue(":offset", offset);
286 }
287 if (query.exec()) {
288 while (query.next()) {
289 RecentItem item;
290 item.id = query.value(0).toInt();
291 item.szOperateId = query.value(1).toString();
292 item.icon = m_IconDB.GetIcon(query.value(2).toInt());
293 item.szName = query.value(3).toString();
294 item.szProtocol = query.value(4).toString();
295 item.szType = query.value(5).toString();
296 item.szFile = query.value(6).toString();
297 item.time = query.value(7).toDateTime();
298 item.szDescription = query.value(8).toString();
299 items.append(item);
300 }
301 } else {
302 qCritical(log) << "Failed to get recents:" << query.lastError().text();
303 }
304
305 return items;
306}
307
308bool CRecentDatabase::ExportToJson(QJsonObject &obj)
309{
310 QJsonArray recents;
311 auto items = GetRecents();
312 foreach(auto it, items) {
313 QJsonObject itemObj;
314
315 bool bRet = CDatabaseFile::ExportFileToJson(it.szFile, itemObj);
316 if(!bRet) continue;
317
318 itemObj.insert("OperateId", it.szOperateId);
319
320 bRet = CDatabaseIcon::ExportIconToJson(it.icon, itemObj);
321 if(!bRet) continue;
322
323 itemObj.insert("Name", it.szName);
324 itemObj.insert("Protocol", it.szProtocol);
325 itemObj.insert("Type", it.szType);
326 itemObj.insert("Time", it.time.toString());
327 itemObj.insert("Description", it.szDescription);
328
329 recents.append(itemObj);
330 }
331 if(recents.isEmpty())
332 return false;
333 obj.insert("Recent", recents);
334 return true;
335}
336
337bool CRecentDatabase::ImportFromJson(const QJsonObject &obj)
338{
339 QJsonArray recents = obj["Recent"].toArray();
340 if(recents.isEmpty()){
341 qCritical(log) << "The file format is error. Don't find recents";
342 return false;
343 }
344
345 for(auto it = recents.begin(); it != recents.end(); it++) {
346 QJsonObject itemObj = it->toObject();
347 RecentItem item;
348
349 bool bRet = m_FileDB.ImportFileToDatabaseFromJson(itemObj, item.szFile);
350 if(!bRet) continue;
351
352 // Check if is exist in recent
353 QSqlQuery query(GetDatabase());
354 query.prepare(
355 "SELECT id FROM recent "
356 "WHERE file=:file"
357 );
358 query.bindValue(":file", item.szFile);
359 if (query.exec() && query.next()) {
360 continue;
361 }
362
363 bRet = CDatabaseIcon::ImportIconFromJson(itemObj, item.icon);
364 if(!bRet) continue;
365
366 item.szOperateId = itemObj["OperateId"].toString();
367 item.szName = itemObj["Name"].toString();
368 item.szProtocol = itemObj["Protocol"].toString();
369 item.szType = itemObj["Type"].toString();
370
371 item.time = QDateTime::fromString(itemObj["Time"].toString());
372 if(!item.time.isValid())
373 item.time = QDateTime::currentDateTime();
374
375 item.szDescription = itemObj["Description"].toString();
376 AddRecent(item);
377 }
378 return true;
379}
int GetIcon(const QIcon &icon)
Get icon id
Definition Database.cpp:392