add a queue to process all insert&update&delete operations of database and use dbus to encapsulate them.

This commit is contained in:
JunjieBai 2022-07-12 11:26:03 +08:00
parent 6a9ee98a84
commit d3b6fcf844
11 changed files with 972 additions and 474 deletions

View File

@ -16,14 +16,15 @@ public:
AppInfoTablePrivate(AppInfoTablePrivate &) = delete;
AppInfoTablePrivate &operator =(const AppInfoTablePrivate &) = delete;
bool setAppFavoritesState(QString &desktopfp, size_t num);
bool setAppTopState(QString &desktopfp, size_t num);
//设置应用的置顶和收藏
void setAppFavoritesState(QString &desktopfp, int num);
void setAppTopState(QString &desktopfp, int num);
//拖动改变置顶和收藏应用位置
bool changeFavoriteAppPos(const QString &desktopfp, size_t pos);
bool changeTopAppPos(const QString &desktopfp, size_t pos);
//改变置顶和收藏应用位置
bool changeFavoriteAppPos(const QString &desktopfp, int pos);
bool changeTopAppPos(const QString &desktopfp, int pos);
//获取所有应用信息并存到一个结构体中
//获取所有应用信息
bool getAppInfoResults(QVector<AppInfoResult> &appInfoResults);
//获取单个应用的某个状态(锁定,置顶,打开状态,收藏)
@ -62,7 +63,8 @@ private:
bool openDataBase();
void closeDataBase();
QDBusInterface *m_interface = nullptr;
QDBusInterface *m_signalTransInterface = nullptr;
QDBusInterface *m_appDBInterface = nullptr;
AppInfoTable *q = nullptr;
QSqlDatabase m_database;

View File

@ -1,5 +1,6 @@
#include "app-info-table.h"
#include "app-info-table-private.h"
#include "app-info-dbus-argument.h"
#include <QDebug>
#include <QtGlobal>
@ -8,6 +9,7 @@
#include <QProcess>
#include <QDBusInterface>
#include <QDBusReply>
#include <QDBusMetaType>
#include <QFileInfo>
#include <QTime>
#include <QSqlQuery>
@ -19,18 +21,31 @@ using namespace UkuiSearch;
AppInfoTablePrivate::AppInfoTablePrivate(AppInfoTable *parent) : QObject(parent), q(parent), m_database(QSqlDatabase())
{
m_interface = new QDBusInterface("com.ukui.search.appdb.service",
"/org/ukui/search/appDataBase",
"org.ukui.search.appdb");
//dbus接收数据库信号
if (!m_interface->isValid()) {
qRegisterMetaType<AppInfoResult>("AppInfoResult");
qRegisterMetaType<QVector<AppInfoResult>>("QVector<AppInfoResult>");
qDBusRegisterMetaType<AppInfoResult>();
qDBusRegisterMetaType<QVector<AppInfoResult>>();
m_signalTransInterface = new QDBusInterface("com.ukui.search.appdb.service",
"/org/ukui/search/appDataBase/signalTransformer",
"org.ukui.search.signalTransformer");
if (!m_signalTransInterface->isValid()) {
qCritical() << "Create privateDirWatcher Interface Failed Because: " << QDBusConnection::sessionBus().lastError();
return;
} else {
connect(m_interface, SIGNAL(appDBItemsAdd(QVector<AppInfoResult>)), this, SLOT(sendAppDBItemsAdd(QVector<AppInfoResult>)));
connect(m_interface, SIGNAL(appDBItemsUpdate(QVector<AppInfoResult>)), this, SLOT(sendAppDBItemsUpdate(QVector<AppInfoResult>)));
connect(m_interface, SIGNAL(appDBItemsDelete(QStringList)), this, SLOT(sendAppDBItemsDelete(QStringList)));
connect(m_signalTransInterface, SIGNAL(appDBItemsAdd(QVector<AppInfoResult>)), this, SLOT(sendAppDBItemsAdd(QVector<AppInfoResult>)));
connect(m_signalTransInterface, SIGNAL(appDBItemsUpdate(QVector<AppInfoResult>)), this, SLOT(sendAppDBItemsUpdate(QVector<AppInfoResult>)));
connect(m_signalTransInterface, SIGNAL(appDBItemsDelete(QStringList)), this, SLOT(sendAppDBItemsDelete(QStringList)));
}
//使用dbus操作数据库获取数据
m_appDBInterface = new QDBusInterface("com.ukui.search.appdb.service",
"/org/ukui/search/appDataBase/dbManager",
"org.ukui.search.appDBManager");
while(1) {
srand(QTime(0,0,0).secsTo(QTime::currentTime()));
m_ConnectionName = QString::fromStdString(std::to_string(rand()));//随机生产链接
@ -44,388 +59,123 @@ AppInfoTablePrivate::AppInfoTablePrivate(AppInfoTable *parent) : QObject(parent)
}
}
bool AppInfoTablePrivate::setAppFavoritesState(QString &desktopfp, size_t num)
void AppInfoTablePrivate::setAppFavoritesState(QString &desktopfp, int num)
{
bool res(true);
if (m_database.transaction()) {
QSqlQuery sql(m_database);
QString cmd = QString("UPDATE appInfo SET MODIFYED_TIME='%0', FAVORITES=%1 WHERE DESKTOP_FILE_PATH='%2'")
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
.arg(num)
.arg(desktopfp);
if (!sql.exec(cmd)) {
qWarning() << "Set app favorites state failed!" << m_database.lastError();
res = false;
}
if (!m_database.commit()) {
qWarning() << "Failed to commit !" << cmd;
m_database.rollback();
res = false;
} else {
QVector<AppInfoResult> results;
AppInfoResult info;
info.desktopPath = desktopfp;
info.favorite = num;
results.append(std::move(info));
Q_EMIT q->appDBItems2BUpdate(results);
}
} else {
qWarning() << "Failed to start transaction mode!!!";
res = false;
}
return res;
m_appDBInterface->call("updateFavoritesState", desktopfp, num);
}
bool AppInfoTablePrivate::setAppTopState(QString &desktopfp, size_t num)
void AppInfoTablePrivate::setAppTopState(QString &desktopfp, int num)
{
bool res(true);
if (m_database.transaction()) {
QSqlQuery sql(m_database);
QString cmd = QString("UPDATE appInfo SET MODIFYED_TIME='%0', TOP=%1 WHERE DESKTOP_FILE_PATH='%2'")
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
.arg(num)
.arg(desktopfp);
if (!sql.exec(cmd)) {
qWarning() << "Set app favorites state failed!" << m_database.lastError();
res = false;
}
if (!m_database.commit()) {
qWarning() << "Failed to commit !" << cmd;
m_database.rollback();
res = false;
} else {
QVector<AppInfoResult> results;
AppInfoResult info;
info.desktopPath = desktopfp;
info.top = num;
results.append(std::move(info));
Q_EMIT q->appDBItems2BUpdate(results);
}
} else {
qWarning() << "Failed to start transaction mode!!!";
res = false;
}
return res;
m_appDBInterface->call("updateTopState", desktopfp, num);
}
bool AppInfoTablePrivate::changeFavoriteAppPos(const QString &desktopfp, size_t pos)
bool AppInfoTablePrivate::changeFavoriteAppPos(const QString &desktopfp, int pos)
{
bool res(true);
if (m_database.transaction()) {
QSqlQuery sql(m_database);
QString cmd = QString("SELECT FAVORITES FROM appInfo WHERE DESKTOP_FILE_PATH = %0").arg(desktopfp);
int previousPos = 0;
//记录应用原位置
if (!sql.exec(cmd)) {
qWarning() << "Fail to change favorite-app pos, because: " << m_database.lastError() << " when exec :" << cmd;
res = false;
QDBusReply<bool> reply = m_appDBInterface->call("changeFavoriteAppPos", desktopfp, pos);
if (reply.isValid()) {
return reply.value();
} else {
if (sql.next()) {
previousPos = sql.value(0).toInt();
cmd = QString("UPDATE appInfo SET FAVORITES = FAVORITES + 1 WHRER FAVORITES > %1 AND FAVORITES < %2")
.arg(previousPos)
.arg(pos);
} else {
qWarning() << "Fail to change favorite-app pos when exec next, because: " << m_database.lastError();
}
}
//更新范围内的应用的位置(原位置和新位置之间)
if (!sql.exec(cmd)) {
qWarning() << "Fail to change favorite-app pos, because: " << m_database.lastError() << " when exec :" << cmd;
res = false;
} else {
cmd = QString("UPDATE appInfo SET FAVORITES = %1 WHERE DESKTOP_FILE_PATH = %2")
.arg(pos)
.arg(desktopfp);
}
//更新应用位置
if (!sql.exec(cmd)) {
qWarning() << "Fail to change favorite-app pos, because: " << m_database.lastError() << " when exec :" << cmd;
res = false;
}
if (!m_database.commit()) {
qWarning() << "Failed to commit when exec: " << cmd;
m_database.rollback();
res = false;
} else {
cmd = QString("SELECT DESKTOP_FILE_PATH, FAVORITES FROM appInfo WHERE FAVORITES > %1 AND FAVORITES < %2")
.arg(previousPos)
.arg(pos);
if (!sql.exec(cmd)) {
qWarning() << "I'm going to send update favorites signal but fail to exec" << cmd;
} else {
QVector<AppInfoResult> results;
while (sql.next()) {
AppInfoResult info;
info.desktopPath = sql.value("DESKTOP_FILE_PATH").toString();
info.favorite = sql.value("FAVORITES").toInt();
results.append(std::move(info));
}
Q_EMIT q->appDBItems2BUpdate(results);
qDebug() << m_appDBInterface->lastError();
return false;
}
}
} else {
qWarning() << "Failed to start transaction mode!!!";
res = false;
}
return res;
}
bool AppInfoTablePrivate::changeTopAppPos(const QString &desktopfp, size_t pos)
bool AppInfoTablePrivate::changeTopAppPos(const QString &desktopfp, int pos)
{
bool res(true);
if (m_database.transaction()) {
QSqlQuery sql(m_database);
QString cmd = QString("SELECT TOP FROM appInfo WHERE DESKTOP_FILE_PATH = %0").arg(desktopfp);
int previousPos = 0;
//记录应用原位置
if (!sql.exec(cmd)) {
qWarning() << "Fail to change top-app pos, because: " << m_database.lastError() << " when exec :" << cmd;
res = false;
QDBusReply<bool> reply = m_appDBInterface->call("changeTopAppPos", desktopfp, pos);
if (reply.isValid()) {
return reply.value();
} else {
if (sql.next()) {
previousPos = sql.value(0).toInt();
cmd = QString("UPDATE appInfo SET TOP = TOP + 1 WHRER TOP > %1 AND TOP < %2")
.arg(previousPos)
.arg(pos);
} else {
qWarning() << "Fail to change top-app pos when exec next, because: " << m_database.lastError();
qDebug() << m_appDBInterface->lastError();
return false;
}
}
//更新范围内的应用的位置(原位置和新位置之间)
if (!sql.exec(cmd)) {
qWarning() << "Fail to change top-app pos, because: " << m_database.lastError() << " when exec :" << cmd;
res = false;
} else {
cmd = QString("UPDATE appInfo SET TOP = %1 WHERE DESKTOP_FILE_PATH = %2")
.arg(pos)
.arg(desktopfp);
}
//更新应用位置
if (!sql.exec(cmd)) {
qWarning() << "Fail to change top-app pos, because: " << m_database.lastError() << " when exec :" << cmd;
res = false;
}
if (!m_database.commit()) {
qWarning() << "Failed to commit when exec: " << cmd;
m_database.rollback();
res = false;
} else {
cmd = QString("SELECT DESKTOP_FILE_PATH, TOP FROM appInfo WHERE TOP > %1 AND TOP < %2")
.arg(previousPos)
.arg(pos);
if (!sql.exec(cmd)) {
qWarning() << "I'm going to send update top signal but fail to exec" << cmd;
} else {
QVector<AppInfoResult> results;
while (sql.next()) {
AppInfoResult info;
info.desktopPath = sql.value("DESKTOP_FILE_PATH").toString();
info.favorite = sql.value("TOP").toInt();
results.append(std::move(info));
}
Q_EMIT q->appDBItems2BUpdate(results);
}
}
} else {
qWarning() << "Failed to start transaction mode!!!";
res = false;
}
return res;
}
bool AppInfoTablePrivate::getAppCategory(QString &desktopfp, QString &category)
{
bool res(true);
if (m_database.transaction()) {
QSqlQuery sql(m_database);
QString cmd = QString("SELECT CATEGORY FROM appInfo WHERE DESKTOP_FILE_PATH='%0'")
.arg(desktopfp);
if (sql.exec(cmd)) {
if (sql.next()) {
category = sql.value(0).toString();
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database.lastError();
res = false;
}
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database.lastError();
res = false;
}
if (!m_database.commit()) {
qWarning() << "Failed to commit !" << cmd;
m_database.rollback();
res = false;
}
} else {
qWarning() << "Failed to start transaction mode!!!";
res = false;
}
return res;
}
bool AppInfoTablePrivate::getAppInfoResults(QVector<AppInfoResult> &appInfoResults)
{
bool res(true);
if (m_database.transaction()) {
QSqlQuery sql(m_database);
QString cmd = QString("SELECT DESKTOP_FILE_PATH,LOCAL_NAME,ICON,CATEGORY,TOP,FAVORITES,LAUNCH_TIMES,LOCK,FIRST_LETTER_ALL FROM appInfo");
if (sql.exec(cmd)) {
while (sql.next()) {
AppInfoResult result;
result.desktopPath = sql.value(0).toString();
result.appLocalName = sql.value(1).toString();
result.iconName = sql.value(2).toString();
result.category = sql.value(3).toString();
result.top = sql.value(4).toInt();
result.favorite = sql.value(5).toInt();
result.launchTimes = sql.value(6).toInt();
result.lock = sql.value(7).toInt();
result.firstLetter = sql.value(8).toString();
appInfoResults.append(std::move(result));
}
QDBusReply<QVector<AppInfoResult>> reply = m_appDBInterface->call("getAppInfoResults");
if (reply.isValid()) {
appInfoResults = reply.value();
return true;
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database.lastError();
res = false;
return false;
}
if (!m_database.commit()) {
qWarning() << "Failed to commit !" << cmd;
m_database.rollback();
res = false;
}
} else {
qWarning() << "Failed to start transaction mode!!!";
res = false;
}
return res;
}
bool AppInfoTablePrivate::getAppLockState(QString &desktopfp, size_t &num)
{
bool res(true);
if (m_database.transaction()) {
QSqlQuery sql(m_database);
QString cmd = QString("SELECT LOCK FROM appInfo WHERE DESKTOP_FILE_PATH='%0'")
.arg(desktopfp);
if (sql.exec(cmd)) {
if (sql.next()) {
num = sql.value(0).toInt();
QDBusReply<int> reply = m_appDBInterface->call("getAppLockState", desktopfp);
if (!reply.isValid()) {
qWarning() << m_appDBInterface->lastError();
return false;
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database.lastError();
res = false;
num = reply.value();
if (num == -1) {
qWarning() << "There's something wrong while using database";
return false;
}
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database.lastError();
res = false;
return true;
}
if (!m_database.commit()) {
qWarning() << "Failed to commit !" << cmd;
m_database.rollback();
res = false;
}
} else {
qWarning() << "Failed to start transaction mode!!!";
res = false;
}
return res;
}
bool AppInfoTablePrivate::getAppTopState(QString &desktopfp, size_t &num)
{
bool res(true);
if (m_database.transaction()) {
QSqlQuery sql(m_database);
QString cmd = QString("SELECT TOP FROM appInfo WHERE DESKTOP_FILE_PATH='%0'")
.arg(desktopfp);
if (sql.exec(cmd)) {
if (sql.next()) {
num = sql.value(0).toInt();
QDBusReply<int> reply = m_appDBInterface->call("getAppTopState", desktopfp);
if (!reply.isValid()) {
qWarning() << m_appDBInterface->lastError();
return false;
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database.lastError();
res = false;
num = reply.value();
if (num == -1) {
qWarning() << "There's something wrong while using database";
return false;
}
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database.lastError();
res = false;
return true;
}
if (!m_database.commit()) {
qWarning() << "Failed to commit !" << cmd;
m_database.rollback();
res = false;
}
} else {
qWarning() << "Failed to start transaction mode!!!";
res = false;
}
return res;
}
bool AppInfoTablePrivate::getAppLaunchedState(QString &desktopfp, size_t &num)
{
bool res(true);
if (m_database.transaction()) {
QSqlQuery sql(m_database);
QString cmd = QString("SELECT LAUNCHED FROM appInfo WHERE DESKTOP_FILE_PATH='%0'")
.arg(desktopfp);
if (sql.exec(cmd)) {
if (sql.next()) {
num = sql.value(0).toInt();
QDBusReply<int> reply = m_appDBInterface->call("getAppLaunchedState", desktopfp);
if (!reply.isValid()) {
qWarning() << m_appDBInterface->lastError();
return false;
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database.lastError();
res = false;
num = reply.value();
if (num == -1) {
qWarning() << "There's something wrong while using database";
return false;
}
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database.lastError();
res = false;
return true;
}
if (!m_database.commit()) {
qWarning() << "Failed to commit !" << cmd;
m_database.rollback();
res = false;
}
} else {
qWarning() << "Failed to start transaction mode!!!";
res = false;
}
return res;
}
bool AppInfoTablePrivate::getAppFavoriteState(QString &desktopfp, size_t &num)
{
bool res(true);
if (m_database.transaction()) {
QSqlQuery sql(m_database);
QString cmd = QString("SELECT FAVORITES FROM appInfo WHERE DESKTOP_FILE_PATH='%0'")
.arg(desktopfp);
if (sql.exec(cmd)) {
if (sql.next()) {
num = sql.value(0).toInt();
QDBusReply<int> reply = m_appDBInterface->call("getAppFavoriteState", desktopfp);
if (!reply.isValid()) {
qWarning() << m_appDBInterface->lastError();
return false;
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database.lastError();
res = false;
num = reply.value();
if (num == -1) {
qWarning() << "There's something wrong while using database";
return false;
}
return true;
}
}
bool AppInfoTablePrivate::getAppCategory(QString &desktopfp, QString &category)
{
QDBusReply<QString> reply = m_appDBInterface->call("getAppCategory", desktopfp);
if (reply.isValid()) {
category = reply.value();
return true;
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database.lastError();
res = false;
qDebug() << m_appDBInterface->lastError();
return false;
}
if (!m_database.commit()) {
qWarning() << "Failed to commit !" << cmd;
m_database.rollback();
res = false;
}
} else {
qWarning() << "Failed to start transaction mode!!!";
res = false;
}
return res;
}
bool AppInfoTablePrivate::addAppShortcut2Desktop(QString &desktopfp)
@ -478,10 +228,10 @@ bool AppInfoTablePrivate::searchInstallApp(QString &keyWord, QStringList &instal
QSqlQuery sql(m_database);
QString cmd;
if (keyWord.size() < 2) {
cmd = QString("SELECT DESKTOP_FILE_PATH,LOCAL_NAME,ICON FROM appInfo WHERE LOCAL_NAME OR NAME_EN OR NAME_ZH OR FIRST_LETTER_OF_PINYIN LIKE '%%0%' ORDER BY FAVORITES DESC")
cmd = QString("SELECT DESKTOP_FILE_PATH,LOCAL_NAME,ICON FROM APPINFO WHERE LOCAL_NAME OR NAME_EN OR NAME_ZH OR FIRST_LETTER_OF_PINYIN LIKE '%%0%' ORDER BY FAVORITES DESC")
.arg(keyWord);
} else {
cmd = QString("SELECT DESKTOP_FILE_PATH,LOCAL_NAME,ICON FROM appInfo WHERE LOCAL_NAME OR NAME_EN OR NAME_ZH OR PINYIN_NAME OR FIRST_LETTER_OF_PINYIN LIKE '%%0%' ORDER BY FAVORITES DESC")
cmd = QString("SELECT DESKTOP_FILE_PATH,LOCAL_NAME,ICON FROM APPINFO WHERE LOCAL_NAME OR NAME_EN OR NAME_ZH OR PINYIN_NAME OR FIRST_LETTER_OF_PINYIN LIKE '%%0%' ORDER BY FAVORITES DESC")
.arg(keyWord);
}
@ -512,11 +262,11 @@ bool AppInfoTablePrivate::searchInstallApp(QStringList &keyWord, QStringList &in
QSqlQuery sql(m_database);
QString cmd;
if (keyWord.at(0).size() < 2) {
cmd = QString("SELECT DESKTOP_FILE_PATH,LOCAL_NAME,ICON,NAME_EN,NAME_ZH,FIRST_LETTER_OF_PINYIN FROM appInfo"
cmd = QString("SELECT DESKTOP_FILE_PATH,LOCAL_NAME,ICON,NAME_EN,NAME_ZH,FIRST_LETTER_OF_PINYIN FROM APPINFO"
" WHERE LOCAL_NAME LIKE '%%0%' OR NAME_EN LIKE '%%0%' OR NAME_ZH LIKE '%%0%' OR FIRST_LETTER_OF_PINYIN LIKE '%%0%'")
.arg(keyWord.at(0));
} else {
cmd = QString("SELECT DESKTOP_FILE_PATH,LOCAL_NAME,ICON,NAME_EN,NAME_ZH,FIRST_LETTER_OF_PINYIN FROM appInfo"
cmd = QString("SELECT DESKTOP_FILE_PATH,LOCAL_NAME,ICON,NAME_EN,NAME_ZH,FIRST_LETTER_OF_PINYIN FROM APPINFO"
" WHERE LOCAL_NAME LIKE '%%0%' OR NAME_EN LIKE '%%0%' OR NAME_ZH LIKE '%%0%' OR PINYIN_NAME LIKE '%%0%' OR FIRST_LETTER_OF_PINYIN LIKE '%%0%'")
.arg(keyWord.at(0));
}
@ -628,7 +378,7 @@ bool AppInfoTablePrivate::updateAppLaunchTimes(QString &desktopfp)
bool res(true);
if (m_database.transaction()) {
QSqlQuery sql(m_database);
QString cmd = QString("SELECT LAUNCH_TIMES FROM appInfo WHERE DESKTOP_FILE_PATH='%1'").arg(desktopfp);
QString cmd = QString("SELECT LAUNCH_TIMES FROM APPINFO WHERE DESKTOP_FILE_PATH='%1'").arg(desktopfp);
if (sql.exec(cmd)) {
if (sql.next()) {
cmd = QString("UPDATE appInfo SET MODIFYED_TIME='%0', LAUNCH_TIMES=%1, LAUNCHED=%2 WHERE DESKTOP_FILE_PATH='%3'")
@ -689,7 +439,7 @@ bool AppInfoTablePrivate::getAllAppDesktopList(QStringList &list)
{
bool res(true);
QSqlQuery sql(m_database);
QString cmd = QString("SELECT DESKTOP_FILE_PATH FROM appInfo");
QString cmd = QString("SELECT DESKTOP_FILE_PATH FROM APPINFO");
if (sql.exec(cmd)) {
while (sql.next()) {
@ -707,7 +457,7 @@ bool AppInfoTablePrivate::getFavoritesAppList(QStringList &list)
{
bool res(true);
QSqlQuery sql(m_database);
QString cmd = QString("SELECT DESKTOP_FILE_PATH FROM appInfo WHERE FAVORITES!=0 ORDER BY FAVORITES");
QString cmd = QString("SELECT DESKTOP_FILE_PATH FROM APPINFO WHERE FAVORITES!=0 ORDER BY FAVORITES");
if (sql.exec(cmd)) {
while (sql.next()) {
list.append(sql.value(0).toString());
@ -723,7 +473,7 @@ bool AppInfoTablePrivate::getTopAppList(QStringList &list)
{
bool res(true);
QSqlQuery sql(m_database);
QString cmd = QString("SELECT DESKTOP_FILE_PATH FROM appInfo WHERE TOP!=0 ORDER BY TOP");
QString cmd = QString("SELECT DESKTOP_FILE_PATH FROM APPINFO WHERE TOP!=0 ORDER BY TOP");
if (sql.exec(cmd)) {
while (sql.next()) {
@ -743,7 +493,7 @@ bool AppInfoTablePrivate::getLaunchTimesAppList(QStringList &list)
if (m_database.transaction()) {
QSqlQuery sql(m_database);
QSqlQuery sqlque(m_database);
QString cmd = QString("SELECT DESKTOP_FILE_PATH FROM appInfo ORDER BY LAUNCH_TIMES");
QString cmd = QString("SELECT DESKTOP_FILE_PATH FROM APPINFO ORDER BY LAUNCH_TIMES");
int count = 0;
if (sql.exec(cmd)) {
while (sql.next()) {
@ -826,12 +576,12 @@ AppInfoTable::AppInfoTable(QObject *parent) : QObject(parent), d(new AppInfoTabl
{
}
bool AppInfoTable::setAppFavoritesState(QString &desktopfp, size_t num)
void AppInfoTable::setAppFavoritesState(QString &desktopfp, size_t num)
{
return d->setAppFavoritesState(desktopfp, num);
}
bool AppInfoTable::setAppTopState(QString &desktopfp, size_t num)
void AppInfoTable::setAppTopState(QString &desktopfp, size_t num)
{
return d->setAppTopState(desktopfp, num);
}

View File

@ -20,25 +20,22 @@ public:
* set the favorites state of the app
* @param desktopfp: the desktop file path of app
* @param num: the favorites app's order(from 1)
* @return bool: true if success, else false
*/
bool setAppFavoritesState(QString &desktopfp, size_t num);
void setAppFavoritesState(QString &desktopfp, size_t num);
/**
* @brief AppInfoTable::setAppTopState
* set the top state of the app
* @param desktopfp: the desktop file path of app
* @param num: the top app's order(from 1)
* @return bool: true if success, else false
*/
bool setAppTopState(QString &desktopfp, size_t num);
void setAppTopState(QString &desktopfp, size_t num);
/**
* @brief AppInfoTable::changeFavoriteAppPos
* change the position of the app which is one of the Favorites Apps
* @param desktopfp: desktop file path of app
* @param pos: the position which the app will be changed into
* @return bool: true if success, else false
*/
bool changeFavoriteAppPos(const QString &desktopfp, size_t pos);

View File

@ -17,7 +17,7 @@
using namespace UkuiSearch;
static AppDBManager *global_instance;
QMutex AppDBManager::s_installAppMapMutex;
QMutex AppDBManager::s_mutex;
AppDBManager *AppDBManager::getInstance()
{
@ -46,7 +46,8 @@ AppDBManager::AppDBManager(QObject *parent) : QThread(parent), m_database(QSqlDa
m_qSettings->endGroup();
//初始化数据库
refreshDataBase();
refreshAllData2DB();
// refreshDataBase();
//初始化FileSystemWatcher
m_watchAppDir = new QFileSystemWatcher(this);
@ -95,19 +96,19 @@ AppDBManager::AppDBManager(QObject *parent) : QThread(parent), m_database(QSqlDa
connect(m_timer, &QTimer::timeout, this, [ & ] {
qDebug() << "Time out! Now I can update the database!";
Q_EMIT this->stopTimer();
this->refreshDataBase();
this->refreshAllData2DB();
}, Qt::DirectConnection);
connect(m_maxProcessTimer, &QTimer::timeout, this, [ & ] {
qDebug() << "I've waited too lang, I have to update the database now!";
Q_EMIT this->stopTimer();
this->refreshDataBase();
this->refreshAllData2DB();
}, Qt::DirectConnection);
//监控应用进程开启
connect(KWindowSystem::self(), &KWindowSystem::windowAdded, [ = ](WId id) {
QString desktopfp = ConvertWinidToDesktop::getConverter().tranIdToDesktop(id);
if (!desktopfp.isEmpty()) {
AppDBManager::getInstance()->updateAppLaunchTimes(desktopfp);
this->updateLaunchTimes(desktopfp);
}
});
} else {
@ -126,6 +127,7 @@ AppDBManager::~AppDBManager()
void AppDBManager::buildAppInfoDB()
{
qDebug() << "I'm going to build app info database.";
QSqlQuery sql(m_database);
QString cmd = QString("CREATE TABLE IF NOT EXISTS appInfo(%1, %2, %3, %4, %5, %6, %7, %8,%9, %10, %11, %12, %13, %14, %15, %16, %17, %18, %19, %20, %21)")
// .arg("ID INT")//自增id
@ -159,7 +161,8 @@ void AppDBManager::buildAppInfoDB()
void AppDBManager::updateAppInfoDB()
{
QMutexLocker locker(&s_installAppMapMutex);
/*
QMutexLocker locker(&s_mutex);
m_installAppMap.clear();
this->getAllDesktopFilePath(GENERAL_APP_DESKTOP_PATH);
this->getAllDesktopFilePath(ANDROID_APP_DESKTOP_PATH);
@ -167,7 +170,7 @@ void AppDBManager::updateAppInfoDB()
QStringList filePathList;
this->getFilePathList(filePathList);
QSqlQuery sql(m_database);
QString cmd = "SELECT COUNT(*) FROM appInfo";
QString cmd = "SELECT COUNT(*) FROM APPINFO";
if (!sql.exec(cmd)) {
this->buildAppInfoDB();
for (auto &filePath : filePathList) {
@ -179,7 +182,7 @@ void AppDBManager::updateAppInfoDB()
//删除多余项
if (sql.value(0).toInt() > filePathList.size()) {
int size = sql.value(0).toInt();
cmd = QString("SELECT DESKTOP_FILE_PATH FROM appInfo");
cmd = QString("SELECT DESKTOP_FILE_PATH FROM APPINFO");
if (!sql.exec(cmd)) {
qWarning() << m_database.lastError() << cmd;
return;
@ -199,13 +202,13 @@ void AppDBManager::updateAppInfoDB()
}
//添加新增项根据md5判断desktop文件是否改变以更新对应项
for (QString &filePath : filePathList) {
cmd = QString("SELECT COUNT(*) FROM appInfo WHERE DESKTOP_FILE_PATH = '%0'").arg(filePath);
cmd = QString("SELECT COUNT(*) FROM APPINFO WHERE DESKTOP_FILE_PATH = '%0'").arg(filePath);
if (sql.exec(cmd)) {
if (sql.next()) {
if (sql.value(0).toInt() == 0) {
this->addAppDesktopFile2DB(filePath);
} else {
cmd = QString("SELECT MD5 FROM appInfo WHERE DESKTOP_FILE_PATH = '%0'").arg(filePath);
cmd = QString("SELECT MD5 FROM APPINFO WHERE DESKTOP_FILE_PATH = '%0'").arg(filePath);
if (!sql.exec(cmd)) {
qWarning() << m_database.lastError() << cmd;
return;
@ -236,21 +239,23 @@ void AppDBManager::updateAppInfoDB()
return;
}
}
*/
}
void AppDBManager::getFilePathList(QStringList &pathList)
{
for (auto i=m_installAppMap.begin(); i!=m_installAppMap.end(); ++i) {
pathList.append(i.value().at(0));
}
// for (auto i=m_installAppMap.begin(); i!=m_installAppMap.end(); ++i) {
// pathList.append(i.value().at(0));
// }
}
/**
* @brief AppMatch::getAllDesktopFilePath desktop文件
* @param path desktop文件夹
*/
void AppDBManager::getAllDesktopFilePath(QString path) {
void AppDBManager::getAllDesktopFilePath(QString path)
{
/*
QDir dir(path);
if(!dir.exists()) {
return;
@ -310,6 +315,7 @@ void AppDBManager::getAllDesktopFilePath(QString path) {
++i;
}
}
*/
}
void AppDBManager::loadDesktopFilePaths(QString path, QFileInfoList &infolist)
@ -320,12 +326,12 @@ void AppDBManager::loadDesktopFilePaths(QString path, QFileInfoList &infolist)
infolist.append(dir.entryInfoList());
}
void AppDBManager::updateAllData2DB()
void AppDBManager::refreshAllData2DB()
{
m_dbChanged = false;
bool firstExec = false;
QSqlQuery sql(m_database);
QString cmd = "SELECT DESKTOP_FILE_PATH,MD5 FROM appInfo";
QString cmd = "SELECT DESKTOP_FILE_PATH,MD5 FROM APPINFO";
QMap<QString, QString> dataMap;
if (!sql.exec(cmd)) {
qDebug() << "Fail to read database, because: " << m_database.lastError();
@ -374,29 +380,25 @@ void AppDBManager::updateAllData2DB()
if (!QString::compare(dataMap.value(path), getAppDesktopMd5(path))) {
//判断系统语言是否改变
if (m_localeChanged) {
this->updateLocaleData2DB(path);
m_dbChanged = true;
this->updateLocaleData(path);
}
dataMap.remove(path);
continue;
} else {
//数据库有记录但md5值改变则update
this->updateAppDesktopFile2DB(path);
m_dbChanged = true;
this->updateDBItem(path);
dataMap.remove(path);
continue;
}
} else {
//数据库中没有记录则insert
this->addAppDesktopFile2DB(path);
m_dbChanged = true;
this->insertDBItem(path);
dataMap.remove(path);
continue;
}
}
//数据库为空则全部insert
this->addAppDesktopFile2DB(path);
m_dbChanged = true;
this->insertDBItem(path);
dataMap.remove(path);
}
@ -406,13 +408,12 @@ void AppDBManager::updateAllData2DB()
//数据库冗余项直接delete
if (!dataMap.isEmpty()) {
for (auto i = dataMap.constBegin(); i != dataMap.constEnd(); i++) {
this->deleteAppDesktopFile2DB(i.key());
m_dbChanged = true;
this->deleteDBItem(i.key());
}
}
}
bool AppDBManager::updateLocaleData2DB(QString desktopPath)
bool AppDBManager::handleLocaleDataUpdate(const QString &desktopPath)
{
bool res(true);
XdgDesktopFile desktopFile;
@ -456,20 +457,19 @@ void AppDBManager::run()
void AppDBManager::refreshDataBase()
{
if (m_database.transaction()) {
// this->updateAppInfoDB();
this->updateAllData2DB();
if (!m_database.commit()) {
qWarning() << "Failed to commit !";
m_database.rollback();
} else if (!m_dbChanged) {
qDebug() << "app DataBase has no changes!";
} else {
Q_EMIT this->finishHandleAppDB();
}
} else {
qWarning() << "Failed to start transaction mode!!!";
}
// if (m_database.transaction()) {
// this->updateAllData2DB();
// if (!m_database.commit()) {
// qWarning() << "Failed to commit !";
// m_database.rollback();
// } else if (!m_dbChanged) {
// qDebug() << "app DataBase has no changes!";
// } else {
// Q_EMIT this->finishHandleAppDB();
// }
// } else {
// qWarning() << "Failed to start transaction mode!!!";
// }
}
bool AppDBManager::openDataBase()
@ -500,7 +500,7 @@ void AppDBManager::closeDataBase()
QSqlDatabase::removeDatabase(CONNECTION_NAME);
}
QString AppDBManager::getAppDesktopMd5(QString &desktopfd)
QString AppDBManager::getAppDesktopMd5(const QString &desktopfd)
{
QString res;
QFile file(desktopfd);
@ -510,16 +510,37 @@ QString AppDBManager::getAppDesktopMd5(QString &desktopfd)
return res;
}
void AppDBManager::getInstallAppMap(QMap<QString, QStringList> &installAppMap)
bool AppDBManager::startTransaction()
{
QMutexLocker locker(&s_installAppMapMutex);
for (auto i=m_installAppMap.begin(); i!=m_installAppMap.end(); ++i) {
installAppMap[i.key().app_name] = i.value();
if (m_database.transaction()) {
return true;
} else {
qWarning() << "Failed to start transaction mode!!!";
return false;
}
installAppMap.detach();
}
bool AppDBManager::addAppDesktopFile2DB(QString &desktopfd)
bool AppDBManager::startCommit()
{
if (!m_database.commit()) {
qWarning() << "Failed to commit !";
m_database.rollback();
return false;
} else {
return true;
}
}
void AppDBManager::getInstallAppMap(QMap<QString, QStringList> &installAppMap)
{
// QMutexLocker locker(&s_mutex);
// for (auto i=m_installAppMap.begin(); i!=m_installAppMap.end(); ++i) {
// installAppMap[i.key().app_name] = i.value();
// }
// installAppMap.detach();
}
bool AppDBManager::handleDBItemInsert(const QString &desktopfd)
{
bool res(true);
QSqlQuery sql(m_database);
@ -600,11 +621,11 @@ bool AppDBManager::addAppDesktopFile2DB(QString &desktopfd)
return res;
}
bool AppDBManager::deleteAppDesktopFile2DB(const QString &desktopfd)
bool AppDBManager::handleDBItemDelete(const QString &desktopfd)
{
bool res(true);
QSqlQuery sql(m_database);
QString cmd = QString("SELECT FAVORITES, TOP FROM appInfo WHERE DESKTOP_FILE_PATH = '%0'").arg(desktopfd);
QString cmd = QString("SELECT FAVORITES, TOP FROM APPINFO WHERE DESKTOP_FILE_PATH = '%0'").arg(desktopfd);
//查询要删除信息的应用是否被收藏或顶置过
if (!sql.exec(cmd)) {
@ -629,7 +650,7 @@ bool AppDBManager::deleteAppDesktopFile2DB(const QString &desktopfd)
}
//执行删除操作
cmd = QString("DELETE FROM appInfo WHERE DESKTOP_FILE_PATH = '%0'").arg(desktopfd);
cmd = QString("DELETE FROM APPINFO WHERE DESKTOP_FILE_PATH = '%0'").arg(desktopfd);
if (!sql.exec(cmd)) {
qWarning() << m_database.lastError() << cmd;
res = false;
@ -644,14 +665,14 @@ bool AppDBManager::deleteAppDesktopFile2DB(const QString &desktopfd)
return res;
}
bool AppDBManager::updateAppDesktopFile2DB(QString &desktopfd)
bool AppDBManager::handleDBItemUpdate(const QString &desktopfd)
{
bool res(true);
XdgDesktopFile desktopfile;
desktopfile.load(desktopfd);
if (desktopfile.value("NoDisplay").toString().contains("true") || desktopfile.value("NotShowIn").toString().contains("UKUI")) {
qDebug() << "app" << desktopfd << "is changed, NoDisplay or NotShowIn is working!";
return this->deleteAppDesktopFile2DB(desktopfd);
qDebug() << "app" << desktopfd << "is changed, but NoDisplay or NotShowIn is working!";
return this->handleDBItemDelete(desktopfd);
}
QString hanzi, pinyin, firstLetterOfPinyin;
QString localName = desktopfile.localizedValue("Name", "NULL").toString();
@ -732,12 +753,11 @@ bool AppDBManager::updateAppDesktopFile2DB(QString &desktopfd)
return res;
}
bool AppDBManager::updateAppLaunchTimes(QString &desktopfp)
bool AppDBManager::handleLaunchTimesUpdate(const QString &desktopfp)
{
bool res(true);
if (m_database.transaction()) {
QSqlQuery sql(m_database);
QString cmd = QString("SELECT LAUNCH_TIMES FROM appInfo WHERE DESKTOP_FILE_PATH='%1'").arg(desktopfp);
QString cmd = QString("SELECT LAUNCH_TIMES FROM APPINFO WHERE DESKTOP_FILE_PATH='%1'").arg(desktopfp);
if (sql.exec(cmd)) {
if (sql.next()) {
int launchTimes = sql.value(0).toInt() + 1;
@ -754,6 +774,7 @@ bool AppDBManager::updateAppLaunchTimes(QString &desktopfp)
result.desktopPath = desktopfp;
result.launchTimes = launchTimes;
Q_EMIT this->appDBItemUpdate(result);
qDebug() << "app database update " << desktopfp << "launch times success!";
}
} else {
qWarning() << "Failed to exec next!" << cmd;
@ -763,18 +784,418 @@ bool AppDBManager::updateAppLaunchTimes(QString &desktopfp)
qWarning() << "Failed to exec:" << cmd;
res = false;
}
if (!m_database.commit()) {
qWarning() << "Failed to commit !" << cmd;
m_database.rollback();
res = false;
} else {
Q_EMIT this->finishHandleAppDB();
return res;
}
bool AppDBManager::handleFavoritesStateUpdate(const QString &desktopfp, int num)
{
if (num < 0) {
qWarning() << "Invalid favorite num, I quit!!!";
return false;
}
bool res(true);
QSqlQuery sql(m_database);
//查询要设置的favorites标志位是否被占用
QString cmd = QString("SELECT DESKTOP_FILE_PATH, FAVORITES FROM APPINFO WHERE FAVORITES = %1").arg(num);
if (!sql.exec(cmd)) {
qWarning() << "Fail to exec:" << cmd << "because:" << m_database.lastError();
} else {
qWarning() << "Failed to start transaction mode!!!";
while (sql.next()) {
if (sql.value("FAVORITES").toInt() == num) {
res = false;
if (sql.value("DESKTOP_FILE_PATH").toString() == desktopfp) {
qWarning() << "favorites state has no changes, I quit!";
return res;
} else {
qWarning() << "the favorites num:" << num << "has been used, fail to update favorites state of" << desktopfp;
return res;
}
}
}
}
//更新favorites状态
cmd = QString("UPDATE APPINFO SET MODIFYED_TIME='%0', FAVORITES=%1 WHERE DESKTOP_FILE_PATH='%2'")
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
.arg(num)
.arg(desktopfp);
if (!sql.exec(cmd)) {
qWarning() << "Set app favorites state failed!" << m_database.lastError();
res = false;
} else {
AppInfoResult info;
info.desktopPath = desktopfp;
info.favorite = num;
Q_EMIT this->appDBItemUpdate(info);
qDebug() << "app database update " << desktopfp << "favorites state: " << num << "success!";
}
return res;
}
bool AppDBManager::handleTopStateUpdate(const QString &desktopfp, int num)
{
if (num < 0) {
qWarning() << "Invalid top num, I quit!!!";
return false;
}
bool res(true);
QSqlQuery sql(m_database);
//查询要设置的top标志位是否被占用
QString cmd = QString("SELECT DESKTOP_FILE_PATH, TOP FROM APPINFO WHERE TOP = %1").arg(num);
if (!sql.exec(cmd)) {
qWarning() << "Fail to exec:" << cmd << "because:" << m_database.lastError();
} else {
while (sql.next()) {
if (sql.value("TOP").toInt() == num) {
res = false;
if (sql.value("DESKTOP_FILE_PATH").toString() == desktopfp) {
qWarning() << "top state has no changes, I quit!";
return res;
} else {
qWarning() << "the top num:" << num << "has been used, fail to update top state of" << desktopfp;
return res;
}
}
}
}
//更新top状态
cmd = QString("UPDATE APPINFO SET MODIFYED_TIME='%0', TOP=%1 WHERE DESKTOP_FILE_PATH='%2'")
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
.arg(num)
.arg(desktopfp);
if (!sql.exec(cmd)) {
qWarning() << "Set app favorites state failed!" << m_database.lastError();
res = false;
} else {
AppInfoResult info;
info.desktopPath = desktopfp;
info.top = num;
Q_EMIT this->appDBItemUpdate(info);
qDebug() << "app database update " << desktopfp << "top state: " << num << "success!";
}
return res;
}
bool AppDBManager::handleLockStateUpdate(const QString &desktopfp, int num)
{
bool res(true);
QSqlQuery sql(m_database);
QString cmd = QString("UPDATE appInfo SET MODIFYED_TIME='%0', LOCK=%1 WHERE DESKTOP_FILE_PATH='%2'")
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
.arg(num)
.arg(desktopfp);
if (!sql.exec(cmd)) {
qWarning() << "Set app favorites state failed!" << m_database.lastError();
res = false;
} else {
AppInfoResult info;
info.desktopPath = desktopfp;
info.lock = num;
Q_EMIT this->appDBItemUpdate(info);
qDebug() << "app database update " << desktopfp << "lock state: " << num << "success!";
}
return res;
}
void AppDBManager::insertDBItem(const QString &desktopfd)
{
PendingAppInfo item(desktopfd, PendingAppInfo::HandleType::Insert);
PendingAppInfoQueue::getAppInfoQueue().enqueue(item);
}
void AppDBManager::updateDBItem(const QString &desktopfd)
{
PendingAppInfo item(desktopfd, PendingAppInfo::HandleType::UpdateAll);
PendingAppInfoQueue::getAppInfoQueue().enqueue(item);
}
void AppDBManager::deleteDBItem(const QString &desktopfd)
{
PendingAppInfo item(desktopfd, PendingAppInfo::HandleType::Delete);
PendingAppInfoQueue::getAppInfoQueue().enqueue(item);
}
void AppDBManager::updateLocaleData(const QString &desktopfp)
{
PendingAppInfo item(desktopfp, PendingAppInfo::HandleType::UpdateLocaleData);
PendingAppInfoQueue::getAppInfoQueue().enqueue(item);
}
void AppDBManager::updateLaunchTimes(const QString &desktopfp)
{
PendingAppInfo item(desktopfp, PendingAppInfo::HandleType::UpdateLaunchTimes);
PendingAppInfoQueue::getAppInfoQueue().enqueue(item);
}
void AppDBManager::updateFavoritesState(const QString &desktopfp, int num)
{
PendingAppInfo item(desktopfp, PendingAppInfo::HandleType::UpdateFavorites, num);
PendingAppInfoQueue::getAppInfoQueue().enqueue(item);
}
void AppDBManager::updateTopState(const QString &desktopfp, int num)
{
PendingAppInfo item(desktopfp, PendingAppInfo::HandleType::UpdateTop);
item.setTop(num);
PendingAppInfoQueue::getAppInfoQueue().enqueue(item);
}
void AppDBManager::udpateLockState(const QString &desktopfp, int num)
{
PendingAppInfo item(desktopfp, PendingAppInfo::HandleType::UpdateTop);
item.setLock(num);
PendingAppInfoQueue::getAppInfoQueue().enqueue(item);
}
bool AppDBManager::changeFavoriteAppPos(const QString &desktopfp, int pos)
{
if (pos < 1) {
qWarning() << "To be moved to a invalid favorites pos , I quit!!";
return false;
}
bool res(true);
QSqlQuery sql(m_database);
QString cmd = QString("SELECT FAVORITES FROM APPINFO WHERE DESKTOP_FILE_PATH = '%0'").arg(desktopfp);
int previousPos = 0;
//记录应用原位置
if (!sql.exec(cmd)) {
qWarning() << "Fail to change favorite-app pos, because: " << m_database.lastError() << " when exec :" << cmd;
res = false;
} else {
if (sql.next()) {
previousPos = sql.value(0).toInt();
if (previousPos < 1) {
qWarning() << QString("app: %1 is not a favorites app, I quit!!").arg(desktopfp);
}
if (previousPos == pos) {
qDebug() << "favorite app's pos has no changes!";
return res;
}
cmd = QString("SELECT DESKTOP_FILE_PATH, FAVORITES FROM APPINFO WHERE FAVORITES BETWEEN MIN(%1, %2) AND MAX(%1, %2)")
.arg(previousPos)
.arg(pos);
} else {
qWarning() << "Fail to change favorite-app pos when exec next, because: " << m_database.lastError();
}
}
//更新原位置和新位置之间的应用的位置
if (!sql.exec(cmd)) {
qWarning() << "Fail to change favorite-app pos, because: " << m_database.lastError() << " when exec :" << cmd;
res = false;
} else {
while (sql.next()) {
if (sql.value("FAVORITES").toInt() == previousPos) {
this->updateFavoritesState(desktopfp, pos);
continue;
}
if (previousPos > pos) {
this->updateFavoritesState(sql.value("DESKTOP_FILE_PATH").toString(), sql.value("FAVORITES").toInt() + 1);
} else {
this->updateFavoritesState(sql.value("DESKTOP_FILE_PATH").toString(), sql.value("FAVORITES").toInt() - 1);
}
}
}
return res;
}
bool AppDBManager::changeTopAppPos(const QString &desktopfp, int pos)
{
if (pos < 1) {
qWarning() << "To be moved to a invalid top pos, I quit!!";
return false;
}
bool res(true);
QSqlQuery sql(m_database);
QString cmd = QString("SELECT TOP FROM APPINFO WHERE DESKTOP_FILE_PATH = '%0'").arg(desktopfp);
int previousPos = 0;
//记录应用原位置
if (!sql.exec(cmd)) {
qWarning() << "Fail to change top-app pos, because: " << m_database.lastError() << " when exec :" << cmd;
res = false;
} else {
if (sql.next()) {
previousPos = sql.value(0).toInt();
if (previousPos < 1) {
qWarning() << QString("app: %1 is not a favorites app, I quit!!").arg(desktopfp);
res = false;
return res;
}
if (previousPos == pos) {
qDebug() << "top app's pos has no changes!";
res = false;
return res;
}
cmd = QString("SELECT DESKTOP_FILE_PATH, TOP FROM APPINFO WHERE TOP BETWEEN MIN(%1, %2) AND MAX(%1, %2)")
.arg(previousPos)
.arg(pos);
} else {
qWarning() << "Fail to change top-app pos when exec next, because: " << m_database.lastError();
}
}
//更新原位置和新位置之间的应用的位置
if (!sql.exec(cmd)) {
qWarning() << "Fail to change top-app pos, because: " << m_database.lastError() << " when exec :" << cmd;
res = false;
} else {
while (sql.next()) {
if (sql.value("TOP").toInt() == previousPos) {
this->updateTopState(desktopfp, pos);
continue;
}
if (previousPos > pos) {
this->updateTopState(sql.value("DESKTOP_FILE_PATH").toString(), sql.value("TOP").toInt() + 1);
} else {
this->updateTopState(sql.value("DESKTOP_FILE_PATH").toString(), sql.value("TOP").toInt() - 1);
}
}
}
return res;
}
QVector<AppInfoResult> AppDBManager::getAppInfoResults()
{
QVector<AppInfoResult> appInfoResults;
QSqlQuery sql(m_database);
QString cmd = QString("SELECT DESKTOP_FILE_PATH,LOCAL_NAME,ICON,CATEGORY,TOP,FAVORITES,LAUNCH_TIMES,LOCK,FIRST_LETTER_ALL FROM APPINFO");
if (sql.exec(cmd)) {
while (sql.next()) {
AppInfoResult result;
result.desktopPath = sql.value("DESKTOP_FILE_PATH").toString();
result.appLocalName = sql.value("LOCAL_NAME").toString();
result.iconName = sql.value("ICON").toString();
result.category = sql.value("CATEGORY").toString();
result.top = sql.value("TOP").toInt();
result.favorite = sql.value("FAVORITES").toInt();
result.launchTimes = sql.value("LAUNCH_TIMES").toInt();
result.lock = sql.value("LOCK").toInt();
result.firstLetter = sql.value("FIRST_LETTER_ALL").toString();
appInfoResults.append(std::move(result));
}
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database.lastError();
}
return appInfoResults;
}
int AppDBManager::getAppLockState(const QString &desktopfp)
{
int lockState = -1;
QSqlQuery sql(m_database);
QString cmd = QString("SELECT LOCK FROM APPINFO WHERE DESKTOP_FILE_PATH='%0'")
.arg(desktopfp);
if (sql.exec(cmd)) {
if (sql.next()) {
lockState = sql.value(0).toInt();
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database.lastError();
}
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database.lastError();
}
return lockState;
}
int AppDBManager::getAppTopState(const QString &desktopfp)
{
int topState = -1;
QSqlQuery sql(m_database);
QString cmd = QString("SELECT TOP FROM APPINFO WHERE DESKTOP_FILE_PATH='%0'")
.arg(desktopfp);
if (sql.exec(cmd)) {
if (sql.next()) {
topState = sql.value(0).toInt();
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database.lastError();
}
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database.lastError();
}
return topState;
}
int AppDBManager::getAppLaunchedState(const QString &desktopfp)
{
int launchedState = -1;
QSqlQuery sql(m_database);
QString cmd = QString("SELECT LAUNCHED FROM APPINFO WHERE DESKTOP_FILE_PATH='%0'")
.arg(desktopfp);
if (sql.exec(cmd)) {
if (sql.next()) {
launchedState = sql.value(0).toInt();
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database.lastError();
}
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database.lastError();
}
return launchedState;
}
int AppDBManager::getAppFavoriteState(const QString &desktopfp)
{
int favoriteState = -1;
QSqlQuery sql(m_database);
QString cmd = QString("SELECT FAVORITES FROM APPINFO WHERE DESKTOP_FILE_PATH='%0'")
.arg(desktopfp);
if (sql.exec(cmd)) {
if (sql.next()) {
favoriteState = sql.value(0).toInt();
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database.lastError();
}
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database.lastError();
}
return favoriteState;
}
QString AppDBManager::getAppCategory(const QString &desktopfp)
{
QString category;
QSqlQuery sql(m_database);
QString cmd = QString("SELECT CATEGORY FROM APPINFO WHERE DESKTOP_FILE_PATH='%0'")
.arg(desktopfp);
if (sql.exec(cmd)) {
if (sql.next()) {
category = sql.value(0).toString();
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database.lastError();
}
} else {
qWarning() << QString("cmd %0 failed!").arg(cmd) << m_database.lastError();
}
return category;
}

View File

@ -2,6 +2,7 @@
#define APPDBMANAGER_H
#include "app-db-common.h"
#include "pending-app-info-queue.h"
#include <QDir>
#include <QObject>
@ -42,6 +43,8 @@ class AppDBManager : public QThread
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface","org.ukui.search.appDBManager")
enum APP_LOCK_STATE{
APP_UNLOCK = 0,
APP_LOCK
@ -50,16 +53,52 @@ class AppDBManager : public QThread
public:
static AppDBManager *getInstance();
QString getAppDesktopMd5(QString &desktopfd);
//刷新数据库数据
void refreshAllData2DB();
void getInstallAppMap(QMap<QString, QStringList> &installAppMap);
//获取desktop文件的md5值
QString getAppDesktopMd5(const QString &desktopfd);
bool startTransaction();
bool startCommit();
bool handleDBItemInsert(const QString &desktopfd);
bool handleDBItemUpdate(const QString &desktopfd);
bool handleDBItemDelete(const QString &desktopfd);
bool handleLocaleDataUpdate(const QString &desktopPath);
bool handleLaunchTimesUpdate(const QString &desktopfp);
bool handleFavoritesStateUpdate(const QString &desktopfp, int num);
bool handleTopStateUpdate(const QString &desktopfp, int num);
bool handleLockStateUpdate(const QString &desktopfp, int num);
public Q_SLOTS:
//对数据库单条所有信息进行增删改
void insertDBItem(const QString &desktopfd);
void updateDBItem(const QString &desktopfd);
void deleteDBItem(const QString &desktopfd);
//对数据库某字段进行update
void updateLocaleData(const QString &desktopfp);
void updateLaunchTimes(const QString &desktopfp);
void updateFavoritesState(const QString &desktopfp, int num);
void updateTopState(const QString &desktopfp, int num);
void udpateLockState(const QString &desktopfp, int num);
//拖动改变置顶和收藏应用位置
bool changeFavoriteAppPos(const QString &desktopfp, int pos);
bool changeTopAppPos(const QString &desktopfp, int pos);
//获取数据库中全部信息
QVector<AppInfoResult> getAppInfoResults();
//查询某应用的某个字段的值
int getAppLockState(const QString &desktopfp);
int getAppTopState(const QString &desktopfp);
int getAppLaunchedState(const QString &desktopfp);
int getAppFavoriteState(const QString &desktopfp);
QString getAppCategory(const QString &desktopfp);
bool addAppDesktopFile2DB(QString &desktopfd);
bool deleteAppDesktopFile2DB(const QString &desktopfd);
bool updateAppDesktopFile2DB(QString &desktopfd);
bool updateAppLaunchTimes(QString &desktopfp);
void updateAllData2DB();
bool updateLocaleData2DB(QString desktopPath);
protected:
void run() override;
@ -67,32 +106,39 @@ private:
explicit AppDBManager(QObject *parent = nullptr);
~AppDBManager();
//加载指定路径path中的所有desktop文件路径到infolist中
void loadDesktopFilePaths(QString path, QFileInfoList &infolist);
void refreshDataBase();
//链接数据库
bool openDataBase();
//刷新数据库
void refreshDataBase();
//关闭数据库,断开链接
void closeDataBase();
//创建数据库字段
void buildAppInfoDB();
//暂时弃用
void updateAppInfoDB();
void getAllDesktopFilePath(QString path);
void getFilePathList(QStringList &pathList);
void getInstallAppMap(QMap<QString, QStringList> &installAppMap);
QSettings *m_qSettings = nullptr;
private:
static QMutex s_mutex;
bool m_localeChanged;
bool m_dbChanged;
QSettings *m_qSettings = nullptr;
QTimer *m_timer = nullptr;
QTimer *m_maxProcessTimer = nullptr;
QSqlDatabase m_database;
QFileSystemWatcher *m_watchAppDir = nullptr;
static QMutex s_installAppMapMutex;
QMap<NameString, QStringList> m_installAppMap;
//应用黑名单
QStringList m_excludedDesktopfiles = {
"/usr/share/applications/software-properties-livepatch.desktop",
"/usr/share/applications/mate-color-select.desktop",
@ -141,12 +187,17 @@ private:
"/usr/share/applications/screensavers"
};
//暂时弃用
QMap<NameString, QStringList> m_installAppMap;
Q_SIGNALS:
//操作数据库
void appDBItemUpdate(const AppInfoResult&);
void appDBItemAdd(const AppInfoResult&);
void appDBItemDelete(const QString&);
void finishHandleAppDB();
//定时器操作
void startTimer();
void maxProcessTimerStart();
void stopTimer();

View File

@ -0,0 +1,145 @@
#include "pending-app-info-queue.h"
#include "app-db-manager.h"
using namespace UkuiSearch;
QMutex PendingAppInfoQueue::s_mutex;
PendingAppInfoQueue &PendingAppInfoQueue::getAppInfoQueue()
{
static PendingAppInfoQueue instance;
return instance;
}
void PendingAppInfoQueue::enqueue(const PendingAppInfo &appInfo)
{
QMutexLocker locker(&s_mutex);
m_handleTimes++;
int index = m_cache.indexOf(appInfo);
if (index == -1) {
m_cache << appInfo;
} else {
//已插入项操作类型为对某字段更新
if (m_cache[index].handleType() > PendingAppInfo::HandleType::UpdateAll) {
if (appInfo.handleType() > PendingAppInfo::HandleType::UpdateAll) {
m_cache[index].merge(appInfo);
} else {
m_cache[index].setHandleType(appInfo);
}
} else {
//已插入项操作类型为对全部字段进行增删改时,设置为优先级高的操作类型
if (m_cache[index].handleType() > appInfo.handleType()) {
m_cache[index].setHandleType(appInfo);
}
}
}
//启动定时器
if (!m_maxProcessTimer->isActive()) {
qDebug() << "start max timer";
Q_EMIT this->startMaxProcessTimer();
}
Q_EMIT this->startMinProcessTimer();
}
void PendingAppInfoQueue::run()
{
exec();
}
PendingAppInfoQueue::PendingAppInfoQueue(QObject *parent) : QThread(parent)
{
this->start();
m_handleTimes = 0;
m_minProcessTimer = new QTimer;
m_maxProcessTimer = new QTimer;
m_minProcessTimer->setInterval(500);
m_maxProcessTimer->setInterval(5*1000);
m_minProcessTimer->setSingleShot(true);
m_maxProcessTimer->setSingleShot(true);
m_minProcessTimer->moveToThread(this);
m_maxProcessTimer->moveToThread(this);
connect(this, SIGNAL(startMinProcessTimer()), m_minProcessTimer, SLOT(start()));
connect(this, SIGNAL(startMaxProcessTimer()), m_maxProcessTimer, SLOT(start()));
connect(this, &PendingAppInfoQueue::stopTimer, m_minProcessTimer, &QTimer::stop);
connect(this, &PendingAppInfoQueue::stopTimer, m_maxProcessTimer, &QTimer::stop);
connect(m_minProcessTimer, &QTimer::timeout, this, &PendingAppInfoQueue::processCache);
connect(m_maxProcessTimer, &QTimer::timeout, this, &PendingAppInfoQueue::processCache);
}
PendingAppInfoQueue::~PendingAppInfoQueue()
{
if (m_minProcessTimer) {
delete m_minProcessTimer;
}
if (m_maxProcessTimer) {
delete m_maxProcessTimer;
}
}
void PendingAppInfoQueue::processCache()
{
s_mutex.lock();
qDebug() << "handle apps:" << m_handleTimes;
m_handleTimes = 0;
m_cache.swap(m_pendingAppInfos);
s_mutex.unlock();
if (m_pendingAppInfos.isEmpty()) {
qWarning() << "No App Info will be process, I'll stop process cache of app queue.";
return;
}
if (AppDBManager::getInstance()->startTransaction()) {
for (const PendingAppInfo &info : m_pendingAppInfos) {
PendingAppInfo::HandleTypes handleTypes = info.handleType();
if (handleTypes < PendingAppInfo::HandleType::UpdateAll) {
switch (handleTypes) {
case PendingAppInfo::HandleType::Delete:
AppDBManager::getInstance()->handleDBItemDelete(info.path());
break;
case PendingAppInfo::HandleType::Insert:
AppDBManager::getInstance()->handleDBItemInsert(info.path());
break;
case PendingAppInfo::HandleType::UpdateAll:
AppDBManager::getInstance()->handleDBItemUpdate(info.path());
break;
default:
break;
}
} else {
if (handleTypes & PendingAppInfo::HandleType::UpdateLocaleData) {
AppDBManager::getInstance()->handleLocaleDataUpdate(info.path());
}
if (handleTypes & PendingAppInfo::HandleType::UpdateLaunchTimes) {
AppDBManager::getInstance()->handleLaunchTimesUpdate(info.path());
}
if (handleTypes & PendingAppInfo::HandleType::UpdateFavorites) {
AppDBManager::getInstance()->handleFavoritesStateUpdate(info.path(), info.favoritesState());
}
if (handleTypes & PendingAppInfo::HandleType::UpdateTop) {
AppDBManager::getInstance()->handleTopStateUpdate(info.path(), info.topState());
}
if (handleTypes & PendingAppInfo::HandleType::UpdateLock) {
AppDBManager::getInstance()->handleLockStateUpdate(info.path(), info.lockState());
}
}
}
if (AppDBManager::getInstance()->startCommit()) {
Q_EMIT AppDBManager::getInstance()->finishHandleAppDB();
}
m_pendingAppInfos.clear();
m_pendingAppInfos.squeeze();
}
}

View File

@ -0,0 +1,51 @@
#ifndef PENDINGAPPINFOQUEUE_H
#define PENDINGAPPINFOQUEUE_H
#include "pending-app-info.h"
#include <QThread>
#include <QMutexLocker>
#include <QTimer>
#include <QVector>
namespace UkuiSearch{
class PendingAppInfoQueue : public QThread
{
Q_OBJECT
public:
static PendingAppInfoQueue &getAppInfoQueue();
void enqueue(const PendingAppInfo& appInfo);
protected:
void run() override;
private:
explicit PendingAppInfoQueue(QObject *parent = nullptr);
PendingAppInfoQueue(const PendingAppInfoQueue&) = delete;
PendingAppInfoQueue& operator =(const PendingAppInfoQueue&) = delete;
~PendingAppInfoQueue();
void processCache();
private:
static QMutex s_mutex;
QTimer *m_minProcessTimer = nullptr;
QTimer *m_maxProcessTimer = nullptr;
QVector<UkuiSearch::PendingAppInfo> m_cache;
QVector<UkuiSearch::PendingAppInfo> m_pendingAppInfos;
int m_handleTimes;
Q_SIGNALS:
void startMinProcessTimer();
void startMaxProcessTimer();
void stopTimer();
};
}
#endif // PENDINGAPPINFOQUEUE_H

View File

@ -0,0 +1,73 @@
#ifndef PENDINGAPPINFO_H
#define PENDINGAPPINFO_H
#include <QString>
#include <QFlags>
namespace UkuiSearch {
class PendingAppInfo
{
public:
enum HandleType{
Delete = 0,
Insert = 1u,
UpdateAll = 1u << 1,
UpdateLocaleData = 1u << 2,
UpdateLaunchTimes = 1u << 3,
UpdateFavorites = 1u << 4,
UpdateTop = 1u << 5,
UpdateLock = 1u << 6
};
Q_DECLARE_FLAGS(HandleTypes, HandleType)
PendingAppInfo() = default;
PendingAppInfo(QString desktopfp, HandleTypes type, int favorites = -1, int top = -1, int lock = -1)
: m_desktopfp(desktopfp),
m_handleType(type),
m_favoritesState(favorites),
m_topState(top),
m_lockState(lock) {}
QString path() const {return m_desktopfp;}
HandleTypes handleType() const {return m_handleType;}
int favoritesState() const {return m_favoritesState;}
int topState() const {return m_topState;}
int lockState() const {return m_lockState;}
void setHandleType(const PendingAppInfo & info) {m_handleType = info.handleType();}
void setFavorites(int favoritesState) {m_favoritesState = favoritesState;}
void setTop(int top) {m_topState = top;}
void setLock(int lock) {m_lockState = lock;}
void merge(const PendingAppInfo &info)
{
m_handleType |= info.handleType();
if (info.favoritesState() != -1) {
m_favoritesState = info.favoritesState();
}
if (info.topState() != -1) {
m_topState = info.topState();
}
if (info.lockState() != -1) {
m_lockState = info.lockState();
}
}
bool operator ==(const PendingAppInfo& rhs) const {
return (m_desktopfp == rhs.m_desktopfp);
}
private:
QString m_desktopfp;
HandleTypes m_handleType;
int m_favoritesState;
int m_topState;
int m_lockState;
};
}
Q_DECLARE_OPERATORS_FOR_FLAGS(UkuiSearch::PendingAppInfo::HandleTypes)
#endif // PENDINGAPPINFO_H

View File

@ -10,7 +10,7 @@ using namespace UkuiSearch;
class SignalTransformer : public QObject
{
Q_CLASSINFO("D-Bus Interface","org.ukui.search.appdb")
Q_CLASSINFO("D-Bus Interface","org.ukui.search.signalTransformer")
Q_OBJECT

View File

@ -32,8 +32,13 @@ UkuiSearchAppDataService::UkuiSearchAppDataService(int &argc, char *argv[], cons
if (!sessionBus.registerService("com.ukui.search.appdb.service")) {
qCritical() << "QDbus register service failed reason:" << sessionBus.lastError();
}
if(!sessionBus.registerObject("/org/ukui/search/appDataBase", SignalTransformer::getTransformer(), QDBusConnection::ExportAllSignals)) {
qCritical() << "ukui-search-fileindex dbus register object failed reason:" << sessionBus.lastError();
if(!sessionBus.registerObject("/org/ukui/search/appDataBase/dbManager", AppDBManager::getInstance(), QDBusConnection::ExportAllSlots)) {
qCritical() << "ukui-search-app-db-manager dbus register object failed reason:" << sessionBus.lastError();
}
if(!sessionBus.registerObject("/org/ukui/search/appDataBase/signalTransformer", SignalTransformer::getTransformer(), QDBusConnection::ExportAllSignals)) {
qCritical() << "ukui-search-signal-transformer dbus register object failed reason:" << sessionBus.lastError();
}
connect(this, &QtSingleApplication::messageReceived, [ & ](QString msg) {

View File

@ -29,12 +29,15 @@ SOURCES += \
main.cpp \
convert-winid-to-desktop.cpp \
app-db-manager.cpp \
pending-app-info-queue.cpp \
signal-transformer.cpp \
ukui-search-app-data-service.cpp \
HEADERS += \
convert-winid-to-desktop.h \
app-db-manager.h \
pending-app-info-queue.h \
pending-app-info.h \
signal-transformer.h \
ukui-search-app-data-service.h \