Add a new function to traverse the desktop files and to handle the data in AppDataBase.

Adjust the code structure.
This commit is contained in:
JunjieBai 2022-06-23 10:21:22 +08:00
parent e7cfd7bd83
commit 5b90706ca8
9 changed files with 336 additions and 123 deletions

View File

@ -24,7 +24,7 @@ AppSearchPlugin::AppSearchPlugin(QObject *parent) : QThread(parent), m_appSearch
connect(this, SIGNAL(startTimer), m_timer, SLOT(start())); connect(this, SIGNAL(startTimer), m_timer, SLOT(start()));
connect(this, &AppSearchPlugin::stopTimer, m_timer, &QTimer::stop); connect(this, &AppSearchPlugin::stopTimer, m_timer, &QTimer::stop);
connect(m_timer, &QTimer::timeout, this, [ & ]{ connect(m_timer, &QTimer::timeout, this, [ & ]{
qWarning()<<"-------------->stopped by itself"; qWarning() << "The app-search thread stopped because of timeout.";
this->quit(); this->quit();
}); });

View File

@ -3,14 +3,21 @@
#include <QCryptographicHash> #include <QCryptographicHash>
#include <QFile> #include <QFile>
#include "app-db-manager.h" #include "app-db-manager.h"
#include "../libsearch/file-utils.h" #include "file-utils.h"
using namespace UkuiSearch; #include "convert-winid-to-desktop.h"
#define GENERAL_APP_DESKTOP_PATH "/usr/share/applications/" #define GENERAL_APP_DESKTOP_PATH "/usr/share/applications/"
#define ANDROID_APP_DESKTOP_PATH QDir::homePath() + "/.local/share/applications/" #define ANDROID_APP_DESKTOP_PATH QDir::homePath() + "/.local/share/applications/"
#define SNAPD_APP_DESKTOP_PATH "/var/lib/snapd/desktop/applications/" #define SNAPD_APP_DESKTOP_PATH "/var/lib/snapd/desktop/applications/"
static AppDBManager *global_instance = AppDBManager::getInstance(); #define LAST_LOCALE_NAME QDir::homePath() + "/.config/org.ukui/ukui-search/appdata/last-locale-name.conf"
#define LOCALE_NAME_VALUE "CurrentLocaleName"
using namespace UkuiSearch;
static AppDBManager *global_instance;
QMutex AppDBManager::s_installAppMapMutex; QMutex AppDBManager::s_installAppMapMutex;
AppDBManager *AppDBManager::getInstance() AppDBManager *AppDBManager::getInstance()
{ {
if (!global_instance) { if (!global_instance) {
@ -18,9 +25,29 @@ AppDBManager *AppDBManager::getInstance()
} }
return global_instance; return global_instance;
} }
AppDBManager::AppDBManager(QObject *parent) : QObject(parent), m_database(new QSqlDatabase)
AppDBManager::AppDBManager(QObject *parent) : QObject(parent), m_database(QSqlDatabase())
{ {
openDataBase(); //链接数据库
if (openDataBase()) {
//监听系统语言变化
m_qSettings = new QSettings(LAST_LOCALE_NAME, QSettings::IniFormat);
m_localeChanged = false;
m_qSettings->beginGroup(LOCALE_NAME_VALUE);
QString lastLocale = m_qSettings->value(LOCALE_NAME_VALUE).toString();
if (QLocale::system().name().compare(lastLocale)) {
qDebug() << "I'm going to update the locale name in conf file.";
if (!lastLocale.isEmpty()) {
m_localeChanged = true;
}
m_qSettings->setValue(LOCALE_NAME_VALUE, QLocale::system().name());
}
m_qSettings->endGroup();
//初始化数据库
initDataBase();
//初始化FileSystemWatcher
m_watchAppDir = new QFileSystemWatcher(this); m_watchAppDir = new QFileSystemWatcher(this);
m_watchAppDir->addPath(GENERAL_APP_DESKTOP_PATH); m_watchAppDir->addPath(GENERAL_APP_DESKTOP_PATH);
QDir androidPath(ANDROID_APP_DESKTOP_PATH); QDir androidPath(ANDROID_APP_DESKTOP_PATH);
@ -35,20 +62,31 @@ AppDBManager::AppDBManager(QObject *parent) : QObject(parent), m_database(new QS
} }
m_watchAppDir->addPath(SNAPD_APP_DESKTOP_PATH); m_watchAppDir->addPath(SNAPD_APP_DESKTOP_PATH);
initDateBaseConnection(); //监听desktop文件所在目录,TODO:directoryChange会发多次信号需要计时器阻塞
connect(m_watchAppDir, &QFileSystemWatcher::directoryChanged, this, [ = ](const QString & path) { connect(m_watchAppDir, &QFileSystemWatcher::directoryChanged, this, [ = ](const QString & path) {
qDebug() << "m_watchAppDir directoryChanged:" << path; qDebug() << "m_watchAppDir directoryChanged:" << path;
if (m_database->transaction()) { if (m_database.transaction()) {
this->updateAppInfoDB(); // this->updateAppInfoDB();
if (!m_database->commit()) { this->updateAllData2DB();
if (!m_database.commit()) {
qWarning() << "Failed to commit !"; qWarning() << "Failed to commit !";
m_database->rollback(); m_database.rollback();
} }
} else { } else {
qWarning() << "Failed to start transaction mode!!!"; qWarning() << "Failed to start transaction mode!!!";
} }
}); });
//监控应用进程开启
connect(KWindowSystem::self(), &KWindowSystem::windowAdded, [ = ](WId id) {
QString desktopfp = ConvertWinidToDesktop::getConverter().tranIdToDesktop(id);
if (!desktopfp.isEmpty()) {
AppDBManager::getInstance()->updateAppLaunchTimes(desktopfp);
}
});
} else {
qDebug() << "App-db-manager does nothing.";
}
} }
AppDBManager::~AppDBManager() AppDBManager::~AppDBManager()
@ -62,8 +100,8 @@ AppDBManager::~AppDBManager()
void AppDBManager::buildAppInfoDB() void AppDBManager::buildAppInfoDB()
{ {
QSqlQuery sql(*m_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)") 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 // .arg("ID INT")//自增id
.arg("DESKTOP_FILE_PATH TEXT")//desktop文件路径 .arg("DESKTOP_FILE_PATH TEXT")//desktop文件路径
.arg("MODIFYED_TIME TEXT")//YYYYMMDDHHmmSS 修改日期 .arg("MODIFYED_TIME TEXT")//YYYYMMDDHHmmSS 修改日期
@ -73,6 +111,7 @@ void AppDBManager::buildAppInfoDB()
.arg("NAME_ZH TEXT")//应用中文名称 .arg("NAME_ZH TEXT")//应用中文名称
.arg("PINYIN_NAME TEXT")//中文拼音 .arg("PINYIN_NAME TEXT")//中文拼音
.arg("FIRST_LETTER_OF_PINYIN TEXT")//中文拼音首字母 .arg("FIRST_LETTER_OF_PINYIN TEXT")//中文拼音首字母
.arg("FIRST_LETTER_ALL")//中英文首字母(只包含一个,目前方案取拼音首字母的第一项,由于模糊拼音算法可能出问题)
.arg("ICON TEXT")//图标名称(或路径) .arg("ICON TEXT")//图标名称(或路径)
.arg("TYPE TEXT")//应用类型 .arg("TYPE TEXT")//应用类型
.arg("CATEGORY TEXT")//应用分类 .arg("CATEGORY TEXT")//应用分类
@ -87,7 +126,7 @@ void AppDBManager::buildAppInfoDB()
.arg("PRIMARY KEY (DESKTOP_FILE_PATH)"); .arg("PRIMARY KEY (DESKTOP_FILE_PATH)");
if (!sql.exec(cmd)) { if (!sql.exec(cmd)) {
qWarning() << m_database->lastError() << cmd; qWarning() << m_database.lastError() << cmd;
return; return;
} }
} }
@ -101,28 +140,28 @@ void AppDBManager::updateAppInfoDB()
this->getAllDesktopFilePath(SNAPD_APP_DESKTOP_PATH); this->getAllDesktopFilePath(SNAPD_APP_DESKTOP_PATH);
QStringList filePathList; QStringList filePathList;
this->getFilePathList(filePathList); this->getFilePathList(filePathList);
QSqlQuery sql(*m_database); QSqlQuery sql(m_database);
QString cmd; QString cmd = "SELECT COUNT(*) FROM appInfo";
if (!sql.exec("SELECT COUNT(*) FROM appInfo")) { if (!sql.exec(cmd)) {
this->buildAppInfoDB(); this->buildAppInfoDB();
for (auto &filePath : filePathList) { for (auto &filePath : filePathList) {
this->addAppDesktopFile2DB(filePath); this->addAppDesktopFile2DB(filePath);
} }
} else { } else {
cmd = QString("SELECT COUNT(*) FROM appInfo");
if (sql.exec(cmd)) { if (sql.exec(cmd)) {
if (sql.next()) { if (sql.next()) {
//删除多余项
if (sql.value(0).toInt() > filePathList.size()) { if (sql.value(0).toInt() > filePathList.size()) {
int size = sql.value(0).toInt(); 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)) { if (!sql.exec(cmd)) {
qWarning() << m_database->lastError() << cmd; qWarning() << m_database.lastError() << cmd;
return; return;
} }
QString path; QString path;
for (int i = 0; i<size; ++i) { for (int i = 0; i<size; ++i) {
if (!sql.next()) { if (!sql.next()) {
qWarning() << m_database->lastError() << cmd; qWarning() << m_database.lastError() << cmd;
return; return;
} }
path = sql.value(0).toString(); path = sql.value(0).toString();
@ -132,7 +171,8 @@ void AppDBManager::updateAppInfoDB()
} }
} }
} }
for (QString &filePath:filePathList) { //添加新增项根据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.exec(cmd)) {
if (sql.next()) { if (sql.next()) {
@ -141,11 +181,11 @@ void AppDBManager::updateAppInfoDB()
} else { } 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)) { if (!sql.exec(cmd)) {
qWarning() << m_database->lastError() << cmd; qWarning() << m_database.lastError() << cmd;
return; return;
} }
if (!sql.next()) { if (!sql.next()) {
qWarning() << m_database->lastError() << cmd; qWarning() << m_database.lastError() << cmd;
return; return;
} }
if (sql.value(0).toString() != getAppDesktopMd5(filePath)) { if (sql.value(0).toString() != getAppDesktopMd5(filePath)) {
@ -153,20 +193,20 @@ void AppDBManager::updateAppInfoDB()
} }
} }
} else { } else {
qWarning() << m_database->lastError() << cmd; qWarning() << m_database.lastError() << cmd;
return; return;
} }
} else { } else {
qWarning() << m_database->lastError() << cmd; qWarning() << m_database.lastError() << cmd;
return; return;
} }
} }
} else { } else {
qWarning() << m_database->lastError() << cmd; qWarning() << m_database.lastError() << cmd;
return; return;
} }
} else { } else {
qWarning() << m_database->lastError() << cmd; qWarning() << m_database.lastError() << cmd;
return; return;
} }
} }
@ -246,41 +286,172 @@ void AppDBManager::getAllDesktopFilePath(QString path) {
} }
} }
void AppDBManager::initDateBaseConnection() void AppDBManager::loadDesktopFilePaths(QString path, QFileInfoList &infolist)
{ {
if (m_database->transaction()) { QDir dir(path);
this->updateAppInfoDB(); dir.setSorting(QDir::DirsFirst);
if (!m_database->commit()) { dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
infolist.append(dir.entryInfoList());
}
void AppDBManager::updateAllData2DB()
{
bool firstExec = false;
QSqlQuery sql(m_database);
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();
this->buildAppInfoDB();
firstExec = true;
} else {
sql.exec(cmd);
while (sql.next()) {
dataMap.insert(sql.value("DESKTOP_FILE_PATH").toString(), sql.value("MD5").toString());
}
}
//遍历desktop文件
QFileInfoList infos;
this->loadDesktopFilePaths(GENERAL_APP_DESKTOP_PATH, infos);
this->loadDesktopFilePaths(ANDROID_APP_DESKTOP_PATH, infos);
this->loadDesktopFilePaths(SNAPD_APP_DESKTOP_PATH, infos);
if(infos.size() < 1) {
return;
}
XdgDesktopFile desktopfile;
for (int i = 0; i < infos.length(); i++) {
QFileInfo fileInfo = infos.at(i);
QString path = fileInfo.filePath();
//对目录递归
if (fileInfo.isDir()) {
loadDesktopFilePaths(path, infos);
continue;
}
//排除非法路径(黑名单 + 非desktop文件
if (m_excludedDesktopfiles.contains(path) or !path.endsWith(".desktop")) {
continue;
}
desktopfile.load(path);
//排除NoDisplay和NotShowIn字段排除loaclized名字为空
if (desktopfile.value("NoDisplay").toString().contains("true") or
desktopfile.value("NotShowIn").toString().contains("UKUI") or
desktopfile.localizedValue("Name").toString().isEmpty()) {
continue;
}
if (!firstExec) {
//数据库有记录
if (dataMap.contains(path)) {
if (!QString::compare(dataMap.value(path), getAppDesktopMd5(path))) {
//判断系统语言是否改变
if (m_localeChanged) {
this->updateLocaleData2DB(path);
}
dataMap.remove(path);
continue;
} else {
//数据库有记录但md5值改变则update
this->updateAppDesktopFile2DB(path);
dataMap.remove(path);
continue;
}
} else {
//数据库中没有记录则insert
this->addAppDesktopFile2DB(path);
dataMap.remove(path);
continue;
}
}
//数据库为空则全部insert
this->addAppDesktopFile2DB(path);
dataMap.remove(path);
}
//遍历完成后重置标志位
m_localeChanged = false;
//数据库冗余项直接delete
if (!dataMap.isEmpty()) {
for (auto i = dataMap.constBegin(); i != dataMap.constEnd(); i++) {
this->deleteAppDesktopFile2DB(i.key());
}
}
}
bool AppDBManager::updateLocaleData2DB(QString desktopPath)
{
bool res(true);
XdgDesktopFile desktopFile;
desktopFile.load(desktopPath);
QString localName = desktopFile.localizedValue("Name", "NULL").toString();
QString firstLetter2All = localName;
if (localName.contains(QRegExp("[\\x4e00-\\x9fa5]+"))) {
firstLetter2All = FileUtils::findMultiToneWords(localName).at(0);
}
QSqlQuery sql(m_database);
QString cmd = QString("UPDATE appInfo SET "
"LOCAL_NAME = '%0', FIRST_LETTER_ALL = '%1'"
"WHERE DESKTOP_FILE_PATH='%2'")
.arg(localName)
.arg(firstLetter2All)
.arg(desktopPath);
if (!sql.exec(cmd)) {
qWarning() << m_database.lastError() << cmd;
res = false;
}
if (res) {
qDebug() << "Already to update the locale app-data of " << desktopPath;
} else {
qDebug() << "Fail to update the locale app-data of " << desktopPath;
}
return res;
}
void AppDBManager::initDataBase()
{
if (m_database.transaction()) {
// this->updateAppInfoDB();
this->updateAllData2DB();
if (!m_database.commit()) {
qWarning() << "Failed to commit !"; qWarning() << "Failed to commit !";
m_database->rollback(); m_database.rollback();
} }
} else { } else {
qWarning() << "Failed to start transaction mode!!!"; qWarning() << "Failed to start transaction mode!!!";
} }
} }
void AppDBManager::openDataBase() bool AppDBManager::openDataBase()
{ {
bool res(true);
QDir dir; QDir dir;
if (!dir.exists(APP_DATABASE_PATH)) { if (!dir.exists(APP_DATABASE_PATH)) {
dir.mkpath(APP_DATABASE_PATH); dir.mkpath(APP_DATABASE_PATH);
} }
if (QSqlDatabase::contains(CONNECTION_NAME)) { if (QSqlDatabase::contains(CONNECTION_NAME)) {
*m_database = QSqlDatabase::database(CONNECTION_NAME); m_database = QSqlDatabase::database(CONNECTION_NAME);
} else { } else {
*m_database = QSqlDatabase::addDatabase("QSQLITE", CONNECTION_NAME); m_database = QSqlDatabase::addDatabase("QSQLITE", CONNECTION_NAME);
m_database->setDatabaseName(APP_DATABASE_PATH + APP_DATABASE_NAME); m_database.setDatabaseName(APP_DATABASE_PATH + APP_DATABASE_NAME);
} }
if(!m_database->open()) { if(!m_database.open()) {
qWarning() << m_database->lastError(); qWarning() << "Fail to open AppDataBase, because" << m_database.lastError();
QApplication::quit(); res = false;
} }
return res;
} }
void AppDBManager::closeDataBase() void AppDBManager::closeDataBase()
{ {
m_database->close(); m_database.close();
delete m_database; // delete m_database;
QSqlDatabase::removeDatabase(CONNECTION_NAME); QSqlDatabase::removeDatabase(CONNECTION_NAME);
} }
@ -306,11 +477,18 @@ void AppDBManager::getInstallAppMap(QMap<QString, QStringList> &installAppMap)
bool AppDBManager::addAppDesktopFile2DB(QString &desktopfd) bool AppDBManager::addAppDesktopFile2DB(QString &desktopfd)
{ {
bool res(true); bool res(true);
QSqlQuery sql(*m_database); QSqlQuery sql(m_database);
XdgDesktopFile desktopfile; XdgDesktopFile desktopfile;
desktopfile.load(desktopfd); desktopfile.load(desktopfd);
QString hanzi, pinyin, firstLetterOfPinyin; QString hanzi, pinyin, firstLetterOfPinyin;
QString localName = desktopfile.localizedValue("Name", "NULL").toString();
QString firstLtter2All = localName;
bool isHanzi = true; bool isHanzi = true;
if (localName.contains(QRegExp("[\\x4e00-\\x9fa5]+"))) {
firstLtter2All = FileUtils::findMultiToneWords(localName).at(0);
}
if (desktopfile.contains("Name[zh_CN]")) { if (desktopfile.contains("Name[zh_CN]")) {
hanzi = desktopfile.value("Name[zh_CN]").toString(); hanzi = desktopfile.value("Name[zh_CN]").toString();
} else { } else {
@ -319,10 +497,11 @@ bool AppDBManager::addAppDesktopFile2DB(QString &desktopfd)
isHanzi = false; isHanzi = false;
} }
} }
if (isHanzi) { if (isHanzi) {
QStringList pinyinList = FileUtils::findMultiToneWords(hanzi); QStringList pinyinList = FileUtils::findMultiToneWords(hanzi);
for (int i = 0; i<pinyinList.size(); ++i) { for (int i = 0; i<pinyinList.size(); ++i) {
if (i%2) { if (i % 2) {
firstLetterOfPinyin += pinyinList.at(i); firstLetterOfPinyin += pinyinList.at(i);
} else { } else {
pinyin += pinyinList.at(i); pinyin += pinyinList.at(i);
@ -331,21 +510,26 @@ bool AppDBManager::addAppDesktopFile2DB(QString &desktopfd)
} }
QString cmd = QString("INSERT INTO appInfo " QString cmd = QString("INSERT INTO appInfo "
"(DESKTOP_FILE_PATH,MODIFYED_TIME,INSERT_TIME,LOCAL_NAME,NAME_EN,NAME_ZH,PINYIN_NAME,FIRST_LETTER_OF_PINYIN,ICON,TYPE,CATEGORY,EXEC,COMMENT,MD5,LAUNCH_TIMES,FAVORITES,LAUNCHED,TOP,LOCK) " "(DESKTOP_FILE_PATH, MODIFYED_TIME, INSERT_TIME, "
"VALUES('%1','%2','%3','%4','%5','%6','%7','%8','%9','%10','%11','%12','%13','%14',%15,%16,%17,%18,%19)") "LOCAL_NAME, NAME_EN, NAME_ZH, PINYIN_NAME, "
"FIRST_LETTER_OF_PINYIN, FIRST_LETTER_ALL, "
"ICON, TYPE, CATEGORY, EXEC, COMMENT, MD5, "
"LAUNCH_TIMES, FAVORITES, LAUNCHED, TOP, LOCK) "
"VALUES('%1','%2','%3','%4','%5','%6','%7','%8','%9','%10','%11','%12','%13','%14','%15',%16,%17,%18,%19,%20)")
.arg(desktopfd) .arg(desktopfd)
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")) .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")) .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
.arg(desktopfile.localizedValue("Name").toString()) .arg(localName)
.arg(desktopfile.value("Name").toString()) .arg(desktopfile.value("Name").toString())
.arg(hanzi) .arg(hanzi)
.arg(pinyin) .arg(pinyin)
.arg(firstLetterOfPinyin) .arg(firstLetterOfPinyin)
.arg(firstLtter2All)
.arg(desktopfile.value("Icon").toString()) .arg(desktopfile.value("Icon").toString())
.arg(desktopfile.value("Type").toString()) .arg(desktopfile.value("Type").toString())
.arg(desktopfile.value("Categories").toString()) .arg(desktopfile.value("Categories").toString())
.arg(desktopfile.value("Exec").toString()) .arg(desktopfile.value("Exec").toString())
.arg(desktopfile.value("Comment").toString()) .arg(desktopfile.value("Comment").toString().replace("'", "''"))
.arg(getAppDesktopMd5(desktopfd)) .arg(getAppDesktopMd5(desktopfd))
.arg(0) .arg(0)
.arg(0) .arg(0)
@ -353,7 +537,7 @@ bool AppDBManager::addAppDesktopFile2DB(QString &desktopfd)
.arg(0) .arg(0)
.arg(0); .arg(0);
if (!sql.exec(cmd)) { if (!sql.exec(cmd)) {
qWarning() << m_database->lastError() << cmd; qWarning() << m_database.lastError() << cmd;
res = false; res = false;
} }
if (res) { if (res) {
@ -364,13 +548,13 @@ bool AppDBManager::addAppDesktopFile2DB(QString &desktopfd)
return res; return res;
} }
bool AppDBManager::deleteAppDesktopFile2DB(QString &desktopfd) bool AppDBManager::deleteAppDesktopFile2DB(const QString &desktopfd)
{ {
bool res(true); bool res(true);
QSqlQuery sql(*m_database); QSqlQuery sql(m_database);
QString cmd = QString("DELETE FROM appInfo WHERE DESKTOP_FILE_PATH = '%0'").arg(desktopfd); QString cmd = QString("DELETE FROM appInfo WHERE DESKTOP_FILE_PATH = '%0'").arg(desktopfd);
if (!sql.exec(cmd)) { if (!sql.exec(cmd)) {
qWarning() << m_database->lastError() << cmd; qWarning() << m_database.lastError() << cmd;
res = false; res = false;
} }
if (res) { if (res) {
@ -391,7 +575,14 @@ bool AppDBManager::updateAppDesktopFile2DB(QString &desktopfd)
return this->deleteAppDesktopFile2DB(desktopfd); return this->deleteAppDesktopFile2DB(desktopfd);
} }
QString hanzi, pinyin, firstLetterOfPinyin; QString hanzi, pinyin, firstLetterOfPinyin;
QString localName = desktopfile.localizedValue("Name", "NULL").toString();
QString firstLetter2All = localName;
bool isHanzi = true; bool isHanzi = true;
if (localName.contains(QRegExp("[\\x4e00-\\x9fa5]+"))) {
firstLetter2All = FileUtils::findMultiToneWords(localName).at(0);
}
if (desktopfile.contains("Name[zh_CN]")) { if (desktopfile.contains("Name[zh_CN]")) {
hanzi = desktopfile.value("Name[zh_CN]").toString(); hanzi = desktopfile.value("Name[zh_CN]").toString();
} else { } else {
@ -400,17 +591,20 @@ bool AppDBManager::updateAppDesktopFile2DB(QString &desktopfd)
isHanzi = false; isHanzi = false;
} }
} }
if (isHanzi) { if (isHanzi) {
QStringList pinyinList = FileUtils::findMultiToneWords(hanzi); QStringList pinyinList = FileUtils::findMultiToneWords(hanzi);
firstLetter2All = pinyinList.at(0);
for (int i = 0; i<pinyinList.size(); ++i) { for (int i = 0; i<pinyinList.size(); ++i) {
if (i%2) { if (i % 2) {
firstLetterOfPinyin += pinyinList.at(i); firstLetterOfPinyin += pinyinList.at(i);
} else { } else {
pinyin += pinyinList.at(i); pinyin += pinyinList.at(i);
} }
} }
} }
QSqlQuery sql(*m_database);
QSqlQuery sql(m_database);
QString cmd = QString("UPDATE appInfo SET " QString cmd = QString("UPDATE appInfo SET "
"MODIFYED_TIME='%0'," "MODIFYED_TIME='%0',"
"LOCAL_NAME='%1'," "LOCAL_NAME='%1',"
@ -418,28 +612,30 @@ bool AppDBManager::updateAppDesktopFile2DB(QString &desktopfd)
"NAME_ZH='%3'" "NAME_ZH='%3'"
",PINYIN_NAME='%4'," ",PINYIN_NAME='%4',"
"FIRST_LETTER_OF_PINYIN='%5'," "FIRST_LETTER_OF_PINYIN='%5',"
"ICON='%6'," "FIRST_LETTER_ALL='%6'"
"TYPE='%7'," "ICON='%7',"
"CATEGORY='%8'," "TYPE='%8',"
"EXEC='%9'," "CATEGORY='%9',"
"COMMENT='%10'," "EXEC='%10',"
"MD5='%11' " "COMMENT='%11',"
"WHERE DESKTOP_FILE_PATH='%12'") "MD5='%12' "
"WHERE DESKTOP_FILE_PATH='%13'")
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")) .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
.arg(desktopfile.localizedValue("Name").toString()) .arg(localName)
.arg(desktopfile.value("Name").toString()) .arg(desktopfile.value("Name").toString())
.arg(hanzi) .arg(hanzi)
.arg(pinyin) .arg(pinyin)
.arg(firstLetterOfPinyin) .arg(firstLetterOfPinyin)
.arg(firstLetter2All)
.arg(desktopfile.value("Icon").toString()) .arg(desktopfile.value("Icon").toString())
.arg(desktopfile.value("Type").toString()) .arg(desktopfile.value("Type").toString())
.arg(desktopfile.value("Categories").toString()) .arg(desktopfile.value("Categories").toString())
.arg(desktopfile.value("Exec").toString()) .arg(desktopfile.value("Exec").toString())
.arg(desktopfile.value("Comment").toString()) .arg(desktopfile.value("Comment").toString().replace("'", "''"))
.arg(getAppDesktopMd5(desktopfd)) .arg(getAppDesktopMd5(desktopfd))
.arg(desktopfd); .arg(desktopfd);
if (!sql.exec(cmd)) { if (!sql.exec(cmd)) {
qWarning() << m_database->lastError() << cmd; qWarning() << m_database.lastError() << cmd;
res = false; res = false;
} }
if (res) { if (res) {
@ -453,8 +649,8 @@ bool AppDBManager::updateAppDesktopFile2DB(QString &desktopfd)
bool AppDBManager::updateAppLaunchTimes(QString &desktopfp) bool AppDBManager::updateAppLaunchTimes(QString &desktopfp)
{ {
bool res(true); bool res(true);
if (m_database->transaction()) { if (m_database.transaction()) {
QSqlQuery sql(*m_database); 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.exec(cmd)) {
if (sql.next()) { if (sql.next()) {
@ -464,7 +660,7 @@ bool AppDBManager::updateAppLaunchTimes(QString &desktopfp)
.arg(1) .arg(1)
.arg(desktopfp); .arg(desktopfp);
if (!sql.exec(cmd)) { if (!sql.exec(cmd)) {
qWarning() << "Set app favorites state failed!" << m_database->lastError(); qWarning() << "Set app favorites state failed!" << m_database.lastError();
res = false; res = false;
} }
} else { } else {
@ -475,9 +671,9 @@ bool AppDBManager::updateAppLaunchTimes(QString &desktopfp)
qWarning() << "Failed to exec:" << cmd; qWarning() << "Failed to exec:" << cmd;
res = false; res = false;
} }
if (!m_database->commit()) { if (!m_database.commit()) {
qWarning() << "Failed to commit !" << cmd; qWarning() << "Failed to commit !" << cmd;
m_database->rollback(); m_database.rollback();
res = false; res = false;
} }
} else { } else {

View File

@ -11,6 +11,7 @@
#include <QDateTime> #include <QDateTime>
#include <QFileSystemWatcher> #include <QFileSystemWatcher>
#include <QMutex> #include <QMutex>
#include <QSettings>
#include "app-db-common-defines.h" #include "app-db-common-defines.h"
#define CONNECTION_NAME QLatin1String("ukss-appdb-connection") #define CONNECTION_NAME QLatin1String("ukss-appdb-connection")
@ -51,25 +52,31 @@ public:
void getInstallAppMap(QMap<QString, QStringList> &installAppMap); void getInstallAppMap(QMap<QString, QStringList> &installAppMap);
bool addAppDesktopFile2DB(QString &desktopfd); bool addAppDesktopFile2DB(QString &desktopfd);
bool deleteAppDesktopFile2DB(QString &desktopfd); bool deleteAppDesktopFile2DB(const QString &desktopfd);
bool updateAppDesktopFile2DB(QString &desktopfd); bool updateAppDesktopFile2DB(QString &desktopfd);
bool updateAppLaunchTimes(QString &desktopfp); bool updateAppLaunchTimes(QString &desktopfp);
void updateAllData2DB();
bool updateLocaleData2DB(QString desktopPath);
private: private:
explicit AppDBManager(QObject *parent = nullptr); explicit AppDBManager(QObject *parent = nullptr);
~AppDBManager(); ~AppDBManager();
void getAllDesktopFilePath(QString path); void loadDesktopFilePaths(QString path, QFileInfoList &infolist);
void initDateBaseConnection(); void initDataBase();
void openDataBase(); bool openDataBase();
void closeDataBase(); void closeDataBase();
void buildAppInfoDB(); void buildAppInfoDB();
void updateAppInfoDB(); void updateAppInfoDB();
void getAllDesktopFilePath(QString path);
void getFilePathList(QStringList &pathList); void getFilePathList(QStringList &pathList);
QSqlDatabase *m_database = nullptr; QSettings *m_qSettings = nullptr;
bool m_localeChanged;
QSqlDatabase m_database;
QFileSystemWatcher *m_watchAppDir = nullptr; QFileSystemWatcher *m_watchAppDir = nullptr;
@ -119,6 +126,9 @@ private:
"/usr/share/applications/openjdk-8-policytool.desktop", "/usr/share/applications/openjdk-8-policytool.desktop",
"/usr/share/applications/kylin-io-monitor.desktop", "/usr/share/applications/kylin-io-monitor.desktop",
"/usr/share/applications/wps-office-uninstall.desktop", "/usr/share/applications/wps-office-uninstall.desktop",
//原本额外排除的目录,不知道额外的原因,有可能之后有问题--bjj20220621
"/usr/share/applications/screensavers"
}; };
}; };

View File

@ -26,6 +26,12 @@ ConvertWinidToDesktop::ConvertWinidToDesktop(QObject *parent) : QObject(parent)
{ {
} }
ConvertWinidToDesktop &ConvertWinidToDesktop::getConverter()
{
static ConvertWinidToDesktop instance;
return instance;
}
QString ConvertWinidToDesktop::tranIdToDesktop(WId id) QString ConvertWinidToDesktop::tranIdToDesktop(WId id)
{ {
KWindowInfo info(id, 0, NET::WM2AllProperties); KWindowInfo info(id, 0, NET::WM2AllProperties);

View File

@ -47,12 +47,16 @@ class ConvertWinidToDesktop : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ConvertWinidToDesktop(QObject *parent = nullptr); static ConvertWinidToDesktop &getConverter();
~ConvertWinidToDesktop();
QString tranIdToDesktop(WId id); QString tranIdToDesktop(WId id);
private: private:
explicit ConvertWinidToDesktop(QObject *parent = nullptr);
ConvertWinidToDesktop(const ConvertWinidToDesktop&) = delete;
ConvertWinidToDesktop& operator =(const ConvertWinidToDesktop&) = delete;
~ConvertWinidToDesktop();
QString m_classClass = nullptr; QString m_classClass = nullptr;
QString m_className = nullptr; QString m_className = nullptr;
QString m_statusName = nullptr; QString m_statusName = nullptr;

View File

@ -59,9 +59,9 @@ int main(int argc, char *argv[])
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif #endif
UkuiSearchAppDataService ukss(argc, argv, "ukui-search-app-data-service"); UkuiSearchAppDataService appDB(argc, argv, "ukui-search-app-data-service");
if (ukss.isRunning()) if (appDB.isRunning()) {
return 0; return 0;
}
return ukss.exec(); return appDB.exec();
} }

View File

@ -1,35 +1,30 @@
#include <QDebug> #include <QDebug>
#include "ukui-search-app-data-service.h" #include "ukui-search-app-data-service.h"
#include "app-db-manager.h" #include "app-db-manager.h"
#include "convert-winid-to-desktop.h"
using namespace UkuiSearch; using namespace UkuiSearch;
UkuiSearchAppDataService::UkuiSearchAppDataService(int &argc, char *argv[], const QString &applicationName): UkuiSearchAppDataService::UkuiSearchAppDataService(int &argc, char *argv[], const QString &applicationName):
QtSingleApplication (applicationName, argc, argv) QtSingleApplication (applicationName, argc, argv)
{ {
qDebug()<<"ukui search app data service constructor start"; qDebug() << "ukui search app data service constructor start";
setApplicationVersion(QString("v%1").arg(VERSION)); setApplicationVersion(QString("v%1").arg(VERSION));
setQuitOnLastWindowClosed(false); setQuitOnLastWindowClosed(false);
if (!this->isRunning()) { if (!this->isRunning()) {
connect(this, &QtSingleApplication::messageReceived, [=](QString msg) { qDebug() << "First running";
AppDBManager::getInstance();
connect(this, &QtSingleApplication::messageReceived, [ & ](QString msg) {
this->parseCmd(msg, true); this->parseCmd(msg, true);
}); });
//监控应用进程开启
connect(KWindowSystem::self(), &KWindowSystem::windowAdded, [ = ](WId id) {
ConvertWinidToDesktop reply;
QString desktopfp = reply.tranIdToDesktop(id);
if (!desktopfp.isEmpty()) {
AppDBManager::getInstance()->updateAppLaunchTimes(desktopfp);
}
});
} }
//parse cmd //parse cmd
qDebug()<<"parse cmd"; qDebug() << "parse cmd";
auto message = this->arguments().join(' ').toUtf8(); auto message = this->arguments().join(' ').toUtf8();
parseCmd(message, !isRunning()); parseCmd(message, !isRunning());
qDebug()<<"ukui search app data service constructor end"; qDebug() << "ukui search app data service constructor end";
} }
void UkuiSearchAppDataService::parseCmd(QString msg, bool isPrimary) void UkuiSearchAppDataService::parseCmd(QString msg, bool isPrimary)

View File

@ -1,4 +1,4 @@
QT += core gui dbus sql xml KWindowSystem QT += core gui dbus sql KWindowSystem
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
@ -6,8 +6,7 @@ greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = ukui-search-app-data-service TARGET = ukui-search-app-data-service
VERSION = 1.0.0 VERSION = 1.0.0
DEFINES += VERSION='\\"$${VERSION}\\"' DEFINES += VERSION='\\"$${VERSION}\\"'
CONFIG += c++11 link_pkgconfig no_keywords lrelease CONFIG += c++11 no_keywords
PKGCONFIG += glib-2.0 gio-unix-2.0 gio-2.0 poppler-qt5
# The following define makes your compiler emit warnings if you use # The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings # any Qt feature that has been marked deprecated (the exact warnings
@ -24,23 +23,19 @@ QMAKE_CXXFLAGS += -Werror=return-type -Werror=return-local-addr -Werror=uninitia
#include(../libsearch/appdata/appdata.pri) #include(../libsearch/appdata/appdata.pri)
include(../3rd-parties/qtsingleapplication/qtsingleapplication.pri) include(../3rd-parties/qtsingleapplication/qtsingleapplication.pri)
LIBS += -lQt5Xdg -lquazip5 -luchardet -ltesseract LIBS += -lQt5Xdg
SOURCES += \ SOURCES += \
main.cpp \ main.cpp \
convert-winid-to-desktop.cpp \ convert-winid-to-desktop.cpp \
app-db-manager.cpp \ app-db-manager.cpp \
ukui-search-app-data-service.cpp \ ukui-search-app-data-service.cpp \
../libsearch/file-utils.cpp \
../libsearch/gobject-template.cpp
HEADERS += \ HEADERS += \
convert-winid-to-desktop.h \ convert-winid-to-desktop.h \
app-db-manager.h \ app-db-manager.h \
ukui-search-app-data-service.h \ ukui-search-app-data-service.h \
app-db-common-defines.h \ app-db-common-defines.h \
../libsearch/file-utils.h \
../libsearch/gobject-template.h
target.path = /usr/bin target.path = /usr/bin
INSTALLS += target INSTALLS += target
@ -52,3 +47,7 @@ INSTALLS += desktop
LIBS += -L$$OUT_PWD/../libchinese-segmentation/ -lchinese-segmentation LIBS += -L$$OUT_PWD/../libchinese-segmentation/ -lchinese-segmentation
INCLUDEPATH += $$PWD/../libchinese-segmentation INCLUDEPATH += $$PWD/../libchinese-segmentation
DEPENDPATH += $$PWD/../libchinese-segmentation DEPENDPATH += $$PWD/../libchinese-segmentation
LIBS += -L$$OUT_PWD/../libsearch/ -lukui-search
INCLUDEPATH += $$PWD/../libsearch
DEPENDPATH += $$PWD/../libsearch

View File

@ -58,8 +58,6 @@ private:
void initDiskWatcher(); void initDiskWatcher();
void handleDisk(); void handleDisk();
void handleAddedUDiskDevice(QDBusMessage msg);
void handleRemovedUDiskDevice(QDBusMessage msg);
void handleIndexItemAppend(const QString &path, QStringList &blackList); void handleIndexItemAppend(const QString &path, QStringList &blackList);
void handleIndexItemRemove(const QString &path); void handleIndexItemRemove(const QString &path);
@ -86,6 +84,11 @@ private:
QStringList m_currentUDiskDeviceList; QStringList m_currentUDiskDeviceList;
QString m_removedUDiskDevice; QString m_removedUDiskDevice;
QMap<QString, QStringList> m_currentUDiskDeviceInfo; QMap<QString, QStringList> m_currentUDiskDeviceInfo;
private Q_SLOTS:
void handleAddedUDiskDevice(QDBusMessage msg);
void handleRemovedUDiskDevice(QDBusMessage msg);
Q_SIGNALS: Q_SIGNALS:
void udiskRemoved(); void udiskRemoved();
void appendIndexItem(const QString&, const QStringList&); void appendIndexItem(const QString&, const QStringList&);