diff --git a/libsearch/appdata/app-info-table-private.h b/libsearch/appdata/app-info-table-private.h index ccc1706..ede3d85 100644 --- a/libsearch/appdata/app-info-table-private.h +++ b/libsearch/appdata/app-info-table-private.h @@ -52,7 +52,8 @@ public: QString lastError(void) const; //通过pid查找desktop文件 - bool tranPidToDesktopFp(int pid, QString &desktopfp); + bool tranPidToDesktopFp(uint pid, QString &desktopfp); + bool desktopFilePathFromName(const QString &desktopFileName, QString &desktopFilePath); //下面的接口都不外放,暂时没啥用 bool setAppLaunchTimes(const QString &desktopfp, size_t num); diff --git a/libsearch/appdata/app-info-table.cpp b/libsearch/appdata/app-info-table.cpp index b20abd2..07d462a 100644 --- a/libsearch/appdata/app-info-table.cpp +++ b/libsearch/appdata/app-info-table.cpp @@ -176,7 +176,7 @@ QString AppInfoTablePrivate::lastError() const return m_database->lastError().text(); } -bool AppInfoTablePrivate::tranPidToDesktopFp(int pid, QString &desktopfp) +bool AppInfoTablePrivate::tranPidToDesktopFp(uint pid, QString &desktopfp) { QDBusReply reply = m_appDBInterface->call("tranPidToDesktopFp", pid); if (reply.isValid()) { @@ -188,6 +188,18 @@ bool AppInfoTablePrivate::tranPidToDesktopFp(int pid, QString &desktopfp) } } +bool AppInfoTablePrivate::desktopFilePathFromName(const QString &desktopFileName, QString &desktopFilePath) +{ + QDBusReply reply = m_appDBInterface->call("desktopFilePathFromName", desktopFileName); + if (reply.isValid()) { + desktopFilePath = reply.value(); + return true; + } else { + qDebug() << m_appDBInterface->lastError(); + return false; + } +} + bool AppInfoTablePrivate::setAppLaunchTimes(const QString &desktopfp, size_t num) { bool res(true); @@ -556,11 +568,16 @@ QString AppInfoTable::lastError() const return d->lastError(); } -bool AppInfoTable::tranPidToDesktopFp(int pid, QString &desktopfp) +bool AppInfoTable::tranPidToDesktopFp(uint pid, QString &desktopfp) { return d->tranPidToDesktopFp(pid, desktopfp); } +bool AppInfoTable::desktopFilePathFromName(const QString &desktopFileName, QString &desktopFilePath) +{ + return d->desktopFilePathFromName(desktopFileName, desktopFilePath); +} + //下面接口暂时没啥用,不外放。 bool AppInfoTable::setAppLaunchTimes(const QString &desktopfp, size_t num) { diff --git a/libsearch/appdata/app-info-table.h b/libsearch/appdata/app-info-table.h index 8444b3f..65a19ef 100644 --- a/libsearch/appdata/app-info-table.h +++ b/libsearch/appdata/app-info-table.h @@ -95,7 +95,9 @@ public: * @param desktopfp: the desktop file path of the process corresponding to pid * @return bool:true if success,else false */ - bool tranPidToDesktopFp(int pid, QString &desktopfp); + bool tranPidToDesktopFp(uint pid, QString &desktopfp); + + bool desktopFilePathFromName(const QString &desktopFileName, QString &desktopFilePath); private: //暂不外放的接口 diff --git a/libsearch/appdata/application-info.cpp b/libsearch/appdata/application-info.cpp index 94c0cbe..70574f6 100644 --- a/libsearch/appdata/application-info.cpp +++ b/libsearch/appdata/application-info.cpp @@ -96,3 +96,13 @@ bool ApplicationInfo::tranPidToDesktopFp(int pid, QString &desktopFilePath) { return AppInfoTable::self()->tranPidToDesktopFp(pid, desktopFilePath); } + +bool ApplicationInfo::tranPidToDesktopFp(uint pid, QString &desktopFilePath) +{ + return AppInfoTable::self()->tranPidToDesktopFp(pid, desktopFilePath); +} + +bool ApplicationInfo::desktopFilePathFromName(const QString &desktopFileName, QString &desktopFilePath) +{ + return AppInfoTable::self()->desktopFilePathFromName(desktopFileName, desktopFilePath); +} diff --git a/libsearch/appdata/application-info.h b/libsearch/appdata/application-info.h index d899564..56fdd04 100644 --- a/libsearch/appdata/application-info.h +++ b/libsearch/appdata/application-info.h @@ -109,7 +109,17 @@ public: * @param desktopFilePath: the desktop file path of the process corresponding to pid * @return bool:true if success,else false */ - bool tranPidToDesktopFp(int pid, QString &desktopFilePath); + bool tranPidToDesktopFp(int pid, QString &desktopFilePath);//obsolete + bool tranPidToDesktopFp(uint pid, QString &desktopFilePath); + + /** + * @brief ApplicationInfo::desktopFilePathFromName + * find the desktop file path of the process which corresponds to the desktop file name (without .desktop) + * @param desktopFileName: the desktop file name of the process which need to get its desktop file path + * @param desktopFilePath: the desktop file path of the process corresponding to pid + * @return bool:true if success,else false + */ + bool desktopFilePathFromName(const QString &desktopFileName, QString &desktopFilePath); Q_SIGNALS: void DBOpenFailed(); diff --git a/libsearch/appdata/application-property-helper.cpp b/libsearch/appdata/application-property-helper.cpp index 680bbda..8a8c238 100644 --- a/libsearch/appdata/application-property-helper.cpp +++ b/libsearch/appdata/application-property-helper.cpp @@ -105,6 +105,10 @@ ApplicationPropertyHelper::ApplicationPropertyHelper(ApplicationProperty::Proper case ApplicationProperty::DontDisplay: d->m_databaseField = "DONT_DISPLAY"; d->m_valueType = QMetaType::Int; + break; + case ApplicationProperty::AutoStart: + d->m_databaseField = "AUTO_START"; + d->m_valueType = QMetaType::Int; } } diff --git a/libsearch/appdata/application-property.h b/libsearch/appdata/application-property.h index c813b6c..b81d799 100644 --- a/libsearch/appdata/application-property.h +++ b/libsearch/appdata/application-property.h @@ -52,7 +52,8 @@ enum Property { Launched, //是否从开始菜单启动过 Top, //置顶顺序(0 未置顶) Lock, //是否锁定(不允许显示或打开) - DontDisplay //是否不需要显示(设置了Nodisplay等字段) + DontDisplay, //是否不需要显示(设置了Nodisplay等字段) + AutoStart //是否自启动(位于自启动目录/etc/xdg/autostart下) }; } //namespace ApplicationProperty typedef QVector ApplicationProperties; diff --git a/ukui-search-app-data-service/app-db-manager.cpp b/ukui-search-app-data-service/app-db-manager.cpp index 4c80c56..0476c22 100644 --- a/ukui-search-app-data-service/app-db-manager.cpp +++ b/ukui-search-app-data-service/app-db-manager.cpp @@ -29,12 +29,12 @@ #define GENERAL_APP_DESKTOP_PATH "/usr/share/applications" #define ANDROID_APP_DESKTOP_PATH QDir::homePath() + "/.local/share/applications" #define SNAPD_APP_DESKTOP_PATH "/var/lib/snapd/desktop/applications" -#define AUTOSTART_APP_DESKTOP_PATH "/etc/xdg/autostart" #define LAST_LOCALE_NAME QDir::homePath() + "/.config/org.ukui/ukui-search/appdata/last-locale-name.conf" #define LOCALE_NAME_VALUE "CurrentLocaleName" #define APP_DATABASE_VERSION_CONFIG QDir::homePath() + "/.config/org.ukui/ukui-search/appdata/app-database-version.conf" #define APP_DATABASE_VERSION_VALUE "AppDatabaseVersion" +static const QString AUTOSTART_APP_DESKTOP_PATH = "/etc/xdg/autostart"; using namespace UkuiSearch; static AppDBManager *global_instance; @@ -207,7 +207,7 @@ 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)") + 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, %22)") // .arg("ID INT")//自增id .arg("DESKTOP_FILE_PATH TEXT PRIMARY KEY NOT NULL")//desktop文件路径 .arg("MODIFYED_TIME TEXT")//YYYYMMDDHHmmSS 修改日期 @@ -229,7 +229,8 @@ void AppDBManager::buildAppInfoDB() .arg("LAUNCHED INT")//应用安装后是否打开过0:未打开过;1:打开过 .arg("TOP INT")//置顶顺序 0:未置顶;>0的数字表示置顶顺序 .arg("LOCK INT")//应用是否锁定(管控),0未锁定,1锁定 - .arg("DONT_DISPLAY INT");//应用隐藏(NoDisplay, NotShowIn或位于autostart) + .arg("DONT_DISPLAY INT")//应用隐藏(NoDisplay, NotShowIn) + .arg("AUTO_START INT");//自启应用 if (!sql.exec(cmd)) { qWarning() << m_database.lastError() << cmd; return; @@ -550,20 +551,23 @@ bool AppDBManager::handleDBItemInsert(const QString &desktopFilePath) } int dontDisplay = 0; - if (desktopfile.value("NoDisplay").toString().contains("true") || - desktopfile.value("NotShowIn").toString().contains("UKUI") || - desktopFilePath.startsWith(AUTOSTART_APP_DESKTOP_PATH)) { + if (desktopfile.value("NoDisplay").toString().contains("true") || desktopfile.value("NotShowIn").toString().contains("UKUI")) { dontDisplay = 1; } + int isAutoStartApp = 0; + if (desktopFilePath.startsWith(AUTOSTART_APP_DESKTOP_PATH + "/")) { + isAutoStartApp = 1; + } + sql.prepare(QString("INSERT INTO appInfo " "(DESKTOP_FILE_PATH, MODIFYED_TIME, INSERT_TIME, " "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, DONT_DISPLAY) " + "LAUNCH_TIMES, FAVORITES, LAUNCHED, TOP, LOCK, DONT_DISPLAY, AUTO_START) " "VALUES(:desktopFilePath, '%0', '%1', :localName, :enName, :zhName, :pinyinName, :firstLetterOfPinyin, :firstLetter2All, " - ":icon, :type, :categories, :exec, :comment,'%2',%3,%4,%5,%6,%7,%8)") + ":icon, :type, :categories, :exec, :comment,'%2',%3,%4,%5,%6,%7,%8,%9)") .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")) .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")) .arg(getAppDesktopMd5(desktopFilePath)) @@ -572,7 +576,8 @@ bool AppDBManager::handleDBItemInsert(const QString &desktopFilePath) .arg(0) .arg(0) .arg(0) - .arg(dontDisplay)); + .arg(dontDisplay) + .arg(isAutoStartApp)); sql.bindValue(":desktopFilePath", desktopFilePath); sql.bindValue(":localName", localName); sql.bindValue(":enName", desktopfile.value("Name").toString()); @@ -704,14 +709,19 @@ bool AppDBManager::handleDBItemDelete(const QString &desktopFilePath) bool AppDBManager::handleDBItemUpdate(const QString &desktopFilePath) { bool res(true); - int dontDisplay = 0; XdgDesktopFile desktopfile; desktopfile.load(desktopFilePath); - if (desktopfile.value("NoDisplay").toString().contains("true") || - desktopfile.value("NotShowIn").toString().contains("UKUI") || - desktopFilePath.startsWith(AUTOSTART_APP_DESKTOP_PATH)) { + + int dontDisplay = 0; + if (desktopfile.value("NoDisplay").toString().contains("true") || desktopfile.value("NotShowIn").toString().contains("UKUI")) { dontDisplay = 1; } + + int isAutoStartApp = 0; + if (desktopFilePath.startsWith(AUTOSTART_APP_DESKTOP_PATH + "/")) { + isAutoStartApp = 1; + } + QString hanzi, pinyin, firstLetterOfPinyin; QString localName = desktopfile.localizedValue("Name", "NULL").toString(); QString firstLetter2All = localName; @@ -757,11 +767,13 @@ bool AppDBManager::handleDBItemUpdate(const QString &desktopFilePath) "EXEC=:exec," "COMMENT=:comment," "MD5='%1'," - "DONT_DISPLAY=%2 " + "DONT_DISPLAY=%2," + "AUTO_START=%3 " "WHERE DESKTOP_FILE_PATH=:desktopFilePath") .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")) .arg(getAppDesktopMd5(desktopFilePath)) - .arg(dontDisplay)); + .arg(dontDisplay) + .arg(isAutoStartApp)); sql.bindValue(":desktopFilePath", desktopFilePath); sql.bindValue(":localName", localName); sql.bindValue(":enName", desktopfile.value("Name").toString()); @@ -1396,27 +1408,30 @@ bool AppDBManager::handleValueSet(const ApplicationInfoMap appInfoMap) return res; } -QString AppDBManager::tranPidToDesktopFp(int pid) +QString AppDBManager::tranPidToDesktopFp(uint pid) { QString exePath = QFile::symLinkTarget("/proc/" + QString::number(pid) + "/exe"); - QString desktopfp; + QString desktopFilePath; QSqlQuery sql(m_database); sql.setForwardOnly(true); - sql.prepare("SELECT DESKTOP_FILE_PATH, EXEC FROM APPINFO WHERE EXEC LIKE :exePath AND DONT_DISPLAY = 0"); + sql.prepare("SELECT DESKTOP_FILE_PATH, EXEC FROM APPINFO WHERE EXEC LIKE :exePath"); sql.bindValue(":exePath", "%" + exePath.section('/', -1) + "%"); if (sql.exec()) { QMap execInfos; while (sql.next()) { execInfos[sql.value("DESKTOP_FILE_PATH").toString()] = sql.value("EXEC").toString(); - desktopfp = sql.value("DESKTOP_FILE_PATH").toString(); + desktopFilePath = sql.value("DESKTOP_FILE_PATH").toString(); } //筛选后有多个结果时进一步过滤 if (execInfos.size() > 1) { - desktopfp.clear(); - for (const QString &path : execInfos.values()) { - QStringList execlist = path.split(" ", QString::SkipEmptyParts); + desktopFilePath.clear(); + for (auto it = execInfos.constBegin(); it != execInfos.constEnd(); it++) { + if (it.key().startsWith(AUTOSTART_APP_DESKTOP_PATH + "/")) { + continue; + } + QStringList execlist = it.value().split(" ", QString::SkipEmptyParts); for (QString &partOfExec : execlist) { //remove the cmd option if (partOfExec.contains("%")) { @@ -1427,27 +1442,67 @@ QString AppDBManager::tranPidToDesktopFp(int pid) partOfExec.remove("\""); } //compare the binary path - if ((partOfExec.contains("/") && partOfExec == exePath) || - (partOfExec == exePath.section("/", -1))) { - desktopfp = execInfos.key(path); + if ((partOfExec.contains("/") && partOfExec == exePath) || (partOfExec == exePath.section("/", -1))) { + desktopFilePath = it.key(); break; } } - if (!desktopfp.isEmpty()) { + if (!desktopFilePath.isEmpty()) { break; } } } - if (!desktopfp.isEmpty()) { - qDebug() << "PID: " << pid << "Desktop file path: " << desktopfp; + if (!desktopFilePath.isEmpty()) { + qDebug() << "PID: " << pid << "Desktop file path: " << desktopFilePath; } else { qWarning() << "Can not find the desktop file of" << exePath << "by pid:" << pid; } } else { qWarning() << "Fail to exec cmd" << sql.lastQuery() << m_database.lastError(); } - return desktopfp; + return desktopFilePath; +} + +QString AppDBManager::desktopFilePathFromName(const QString &desktopFileName) +{ + QString desktopFilePath; + QSqlQuery query(m_database); + query.setForwardOnly(true); + query.prepare("SELECT DESKTOP_FILE_PATH FROM APPINFO WHERE DESKTOP_FILE_PATH LIKE :desktopFilePath"); + query.bindValue(":desktopFilePath", "%/" + desktopFileName + ".desktop"); + + if (query.exec()) { + QStringList results; + while (query.next()) { + desktopFilePath = query.value("DESKTOP_FILE_PATH").toString(); + results.append(desktopFilePath); + } + //筛选后有多个结果时进一步过滤 + if (results.size() > 1) { + desktopFilePath.clear(); + for (const QString &path : results) { + if (path.startsWith(AUTOSTART_APP_DESKTOP_PATH + "/")) { + continue; + } else { + desktopFilePath = path; + } + + if (!desktopFilePath.isEmpty()) { + break; + } + } + } + + if (!desktopFilePath.isEmpty()) { + qDebug() << "Desktop file path is" << desktopFilePath; + } else { + qWarning() << "Can not find the desktop file by Name:" << desktopFileName; + } + } else { + qWarning() << "Fail to exec cmd" << query.lastQuery(); + } + return desktopFilePath; } void AppDBManager::insertDBItem(const QString &desktopfd) diff --git a/ukui-search-app-data-service/app-db-manager.h b/ukui-search-app-data-service/app-db-manager.h index 62aaaa9..53772ee 100644 --- a/ukui-search-app-data-service/app-db-manager.h +++ b/ukui-search-app-data-service/app-db-manager.h @@ -37,7 +37,7 @@ #define APP_DATABASE_PATH QDir::homePath()+"/.config/org.ukui/ukui-search/appdata/" #define APP_DATABASE_NAME "app-info.db" #define CONNECTION_NAME QLatin1String("ukss-appdb-connection") -static const QString APP_DATABASE_VERSION = QStringLiteral("1.1"); +static const QString APP_DATABASE_VERSION = QStringLiteral("1.2"); namespace UkuiSearch { /** @@ -84,7 +84,8 @@ public: public Q_SLOTS: //通过pid查找对应的desktop文件 - QString tranPidToDesktopFp(int pid); + QString tranPidToDesktopFp(uint pid); + QString desktopFilePathFromName(const QString &desktopFileName); //对数据库单条所有信息进行增删改 void insertDBItem(const QString &desktopfd); @@ -170,7 +171,8 @@ private: {"LAUNCHED", "INT"}, {"TOP", "INT"}, {"LOCK", "INT"}, - {"DONT_DISPLAY", "INT"} + {"DONT_DISPLAY", "INT"}, + {"AUTO_START", "INT"} }; //应用黑名单