From 50f7bb1f5ce66b0273767f2eccaff9e3737fb16c Mon Sep 17 00:00:00 2001 From: JunjieBai Date: Tue, 8 Aug 2023 17:00:31 +0800 Subject: [PATCH] feat(app-database-service):add a method to find desktop file through WinId, add a START_UP_WMCLASS field to the database. --- libsearch/appdata/app-info-table-private.h | 1 + libsearch/appdata/app-info-table.cpp | 17 +++++ libsearch/appdata/app-info-table.h | 2 + libsearch/appdata/application-info.cpp | 5 ++ libsearch/appdata/application-info.h | 10 +++ .../app-db-manager.cpp | 67 ++++++++++++++++--- ukui-search-app-data-service/app-db-manager.h | 9 ++- .../dbus/app-database-adaptor.cpp | 8 +++ .../dbus/app-database-adaptor.h | 5 ++ .../dbus/org.ukui.appdatabase.xml | 4 ++ 10 files changed, 117 insertions(+), 11 deletions(-) diff --git a/libsearch/appdata/app-info-table-private.h b/libsearch/appdata/app-info-table-private.h index ede3d85..f74ead9 100644 --- a/libsearch/appdata/app-info-table-private.h +++ b/libsearch/appdata/app-info-table-private.h @@ -53,6 +53,7 @@ public: //通过pid查找desktop文件 bool tranPidToDesktopFp(uint pid, QString &desktopfp); + bool tranWinIdToDesktopFilePath(const QVariant &winId, QString &desktopfp); bool desktopFilePathFromName(const QString &desktopFileName, QString &desktopFilePath); //下面的接口都不外放,暂时没啥用 diff --git a/libsearch/appdata/app-info-table.cpp b/libsearch/appdata/app-info-table.cpp index 07d462a..8aa0fa2 100644 --- a/libsearch/appdata/app-info-table.cpp +++ b/libsearch/appdata/app-info-table.cpp @@ -188,6 +188,18 @@ bool AppInfoTablePrivate::tranPidToDesktopFp(uint pid, QString &desktopfp) } } +bool AppInfoTablePrivate::tranWinIdToDesktopFilePath(const QVariant &winId, QString &desktopfp) +{ + QDBusReply reply = m_appDBInterface->call("tranWinIdToDesktopFilePath", QVariant::fromValue(QDBusVariant(winId))); + if (reply.isValid()) { + desktopfp = reply.value(); + return true; + } else { + qDebug() << m_appDBInterface->lastError(); + return false; + } +} + bool AppInfoTablePrivate::desktopFilePathFromName(const QString &desktopFileName, QString &desktopFilePath) { QDBusReply reply = m_appDBInterface->call("desktopFilePathFromName", desktopFileName); @@ -578,6 +590,11 @@ bool AppInfoTable::desktopFilePathFromName(const QString &desktopFileName, QStri return d->desktopFilePathFromName(desktopFileName, desktopFilePath); } +bool AppInfoTable::tranWinIdToDesktopFilePath(const QVariant &winId, QString &desktopfp) +{ + return d->tranWinIdToDesktopFilePath(winId, desktopfp); +} + //下面接口暂时没啥用,不外放。 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 65a19ef..9fc819e 100644 --- a/libsearch/appdata/app-info-table.h +++ b/libsearch/appdata/app-info-table.h @@ -99,6 +99,8 @@ public: bool desktopFilePathFromName(const QString &desktopFileName, QString &desktopFilePath); + bool tranWinIdToDesktopFilePath(const QVariant &winId, QString &desktopfp); + private: //暂不外放的接口 bool setAppLaunchTimes(const QString &desktopfp, size_t num); diff --git a/libsearch/appdata/application-info.cpp b/libsearch/appdata/application-info.cpp index 70574f6..dd1eeec 100644 --- a/libsearch/appdata/application-info.cpp +++ b/libsearch/appdata/application-info.cpp @@ -106,3 +106,8 @@ bool ApplicationInfo::desktopFilePathFromName(const QString &desktopFileName, QS { return AppInfoTable::self()->desktopFilePathFromName(desktopFileName, desktopFilePath); } + +bool ApplicationInfo::tranWinIdToDesktopFilePath(const QVariant &winId, QString &desktopFilePath) +{ + return AppInfoTable::self()->tranWinIdToDesktopFilePath(winId, desktopFilePath); +} diff --git a/libsearch/appdata/application-info.h b/libsearch/appdata/application-info.h index 56fdd04..393ae11 100644 --- a/libsearch/appdata/application-info.h +++ b/libsearch/appdata/application-info.h @@ -121,6 +121,16 @@ public: */ bool desktopFilePathFromName(const QString &desktopFileName, QString &desktopFilePath); + /** + * @brief ApplicationInfo::tranWinIdToDesktopFilePath + * find the desktop file path of the process which corresponds to the winId. + * it will find through tranPidToDesktopFp method first, and then use the winId if the desktop file can not be found by pid; + * @param winId: the winId 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 tranWinIdToDesktopFilePath(const QVariant &winId, QString &desktopFilePath); + Q_SIGNALS: void DBOpenFailed(); void appDBItems2BUpdate(ApplicationInfoMap); diff --git a/ukui-search-app-data-service/app-db-manager.cpp b/ukui-search-app-data-service/app-db-manager.cpp index 1f30d94..18b9dd3 100644 --- a/ukui-search-app-data-service/app-db-manager.cpp +++ b/ukui-search-app-data-service/app-db-manager.cpp @@ -170,13 +170,10 @@ AppDBManager::AppDBManager(QObject *parent) : QThread(parent), m_database(QSqlDa //监控应用进程开启 connect(KWindowSystem::self(), &KWindowSystem::windowAdded, [ = ](WId id) { - KWindowInfo info(id, NET::Properties(), NET::WM2AllProperties); - if (info.valid()) { - QString desktopfp; - desktopfp = this->tranPidToDesktopFp(info.pid()); - if (!desktopfp.isEmpty()) { - this->updateLaunchTimes(desktopfp); - } + QDBusVariant dbusVariant(id); + QString desktopFilePath = this->tranWinIdToDesktopFilePath(dbusVariant); + if (!desktopFilePath.isEmpty()) { + this->updateLaunchTimes(desktopFilePath); } }); m_adaptor = new AppDBManagerAdaptor(this); @@ -566,9 +563,9 @@ bool AppDBManager::handleDBItemInsert(const QString &desktopFilePath) "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, AUTO_START) " + "LAUNCH_TIMES, FAVORITES, LAUNCHED, TOP, LOCK, DONT_DISPLAY, AUTO_START, START_UP_WMCLASS) " "VALUES(:desktopFilePath, '%0', '%1', :localName, :enName, :zhName, :pinyinName, :firstLetterOfPinyin, :firstLetter2All, " - ":icon, :type, :categories, :exec, :comment,'%2',%3,%4,%5,%6,%7,%8,%9)") + ":icon, :type, :categories, :exec, :comment,'%2',%3,%4,%5,%6,%7,%8,%9, :wmClass)") .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")) .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")) .arg(getAppDesktopMd5(desktopFilePath)) @@ -591,6 +588,7 @@ bool AppDBManager::handleDBItemInsert(const QString &desktopFilePath) sql.bindValue(":categories", desktopfile.value("Categories").toString()); sql.bindValue(":exec", desktopfile.value("Exec").toString()); sql.bindValue(":comment", desktopfile.value("Comment").toString()); + sql.bindValue(":wmClass", desktopfile.value("StartupWMClass").toString()); if (!this->startTransaction()) { return false; @@ -767,6 +765,7 @@ bool AppDBManager::handleDBItemUpdate(const QString &desktopFilePath) "CATEGORY=:categories," "EXEC=:exec," "COMMENT=:comment," + "START_UP_WMCLASS=:wmClass," "MD5='%1'," "DONT_DISPLAY=%2," "AUTO_START=%3 " @@ -787,6 +786,7 @@ bool AppDBManager::handleDBItemUpdate(const QString &desktopFilePath) sql.bindValue(":categories", desktopfile.value("Categories").toString()); sql.bindValue(":exec", desktopfile.value("Exec").toString()); sql.bindValue(":comment", desktopfile.value("Comment").toString()); + sql.bindValue(":wmClass", desktopfile.value("StartupWMClass").toString()); if (!this->startTransaction()) { return false; @@ -1530,6 +1530,55 @@ QString AppDBManager::desktopFilePathFromName(const QString &desktopFileName) return desktopFilePath; } +QString AppDBManager::tranWinIdToDesktopFilePath(const QDBusVariant &id) +{ + KWindowInfo info(id.variant().toULongLong(), NET::Properties(), NET::WM2AllProperties); + QString desktopFilePath; + if (info.valid()) { + desktopFilePath = this->tranPidToDesktopFp(info.pid()); + if (desktopFilePath.isEmpty()) { + QString classClass = info.windowClassClass(); //the 2nd part of WM_CLASS, specified by the application writer + QSqlQuery query(m_database); + query.setForwardOnly(true); + query.prepare("SELECT DESKTOP_FILE_PATH, START_UP_WMCLASS FROM APPINFO WHERE EXEC LIKE :classClass OR DESKTOP_FILE_PATH LIKE :classClass OR START_UP_WMCLASS=:windowClassClass"); + query.bindValue(":classClass", "%" + classClass + "%"); + query.bindValue(":windowClassClass", classClass); + + if (query.exec()) { + QMap wmClassInfos; + while (query.next()) { + wmClassInfos[query.value("DESKTOP_FILE_PATH").toString()] = query.value("START_UP_WMCLASS").toString(); + desktopFilePath = query.value("DESKTOP_FILE_PATH").toString(); + } + //筛选后有多个结果时进一步过滤 + if (wmClassInfos.size() > 1) { + desktopFilePath.clear(); + for (auto it = wmClassInfos.constBegin(); it != wmClassInfos.constEnd(); it++) { + if (it.key().startsWith(AUTOSTART_APP_DESKTOP_PATH)) { + continue; + } + if (it.key().section("/", -1) == (classClass + ".desktop") || it.value() == classClass) { + desktopFilePath = it.key(); + break; + } + } + } + + if (!desktopFilePath.isEmpty()) { + qDebug() << "WId:" << id.variant() << "Classclass of window:" << classClass << "Desktop file path:" << desktopFilePath; + } else { + qWarning() << "Can not find the desktop file by windowClassClass:" << classClass; + } + } else { + qWarning() << "Fail to exec cmd" << query.lastQuery(); + } + } + } else { + qWarning() << "Cannot find desktop flie by WinId:" << id.variant() << "it is invalid" << id.variant().toULongLong(); + } + return desktopFilePath; +} + void AppDBManager::insertDBItem(const QString &desktopfd) { PendingAppInfo item(desktopfd, PendingAppInfo::HandleType::Insert); diff --git a/ukui-search-app-data-service/app-db-manager.h b/ukui-search-app-data-service/app-db-manager.h index 8df9718..0f02f3d 100644 --- a/ukui-search-app-data-service/app-db-manager.h +++ b/ukui-search-app-data-service/app-db-manager.h @@ -38,7 +38,10 @@ #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.2"); +/** + * changelog(1.2 to 1.3): Add the START_UP_WMCLASS field in order to find desktop file path by the windowClassClass. + */ +static const QString APP_DATABASE_VERSION = QStringLiteral("1.3"); namespace UkuiSearch { /** @@ -87,6 +90,7 @@ public Q_SLOTS: //通过pid查找对应的desktop文件 QString tranPidToDesktopFp(uint pid); QString desktopFilePathFromName(const QString &desktopFileName); + QString tranWinIdToDesktopFilePath(const QDBusVariant &id); //对数据库单条所有信息进行增删改 void insertDBItem(const QString &desktopfd); @@ -173,7 +177,8 @@ private: {"TOP", "INT"}, {"LOCK", "INT"}, {"DONT_DISPLAY", "INT"}, - {"AUTO_START", "INT"} + {"AUTO_START", "INT"}, + {"START_UP_WMCLASS", "TEXT"} }; //应用黑名单 diff --git a/ukui-search-app-data-service/dbus/app-database-adaptor.cpp b/ukui-search-app-data-service/dbus/app-database-adaptor.cpp index 59d58fc..8fc4965 100644 --- a/ukui-search-app-data-service/dbus/app-database-adaptor.cpp +++ b/ukui-search-app-data-service/dbus/app-database-adaptor.cpp @@ -67,6 +67,14 @@ QString AppDBManagerAdaptor::tranPidToDesktopFp(uint pid) return out0; } +QString AppDBManagerAdaptor::tranWinIdToDesktopFilePath(const QDBusVariant &id) +{ + // handle method call org.ukui.search.appDBManager.tranWinIdToDesktopFilePath + QString out0; + QMetaObject::invokeMethod(parent(), "tranWinIdToDesktopFilePath", Q_RETURN_ARG(QString, out0), Q_ARG(QDBusVariant, id)); + return out0; +} + void AppDBManagerAdaptor::updateDBItem(const QString &desktopfd) { // handle method call org.ukui.search.appDBManager.updateDBItem diff --git a/ukui-search-app-data-service/dbus/app-database-adaptor.h b/ukui-search-app-data-service/dbus/app-database-adaptor.h index 365f578..65e7d6e 100644 --- a/ukui-search-app-data-service/dbus/app-database-adaptor.h +++ b/ukui-search-app-data-service/dbus/app-database-adaptor.h @@ -41,6 +41,10 @@ class AppDBManagerAdaptor: public QDBusAbstractAdaptor " \n" " \n" " \n" +" \n" +" \n" +" \n" +" \n" " \n" " \n" " \n" @@ -87,6 +91,7 @@ public Q_SLOTS: // METHODS void insertDBItem(const QString &desktopfd); void setValue(UkuiSearch::ApplicationInfoMap infos2BSet); QString tranPidToDesktopFp(uint pid); + QString tranWinIdToDesktopFilePath(const QDBusVariant &id); void updateDBItem(const QString &desktopfd); void updateFavoritesState(const QString &desktopFilePath); void updateFavoritesState(const QString &desktopFilePath, uint num); diff --git a/ukui-search-app-data-service/dbus/org.ukui.appdatabase.xml b/ukui-search-app-data-service/dbus/org.ukui.appdatabase.xml index 1b79c5b..84f8636 100644 --- a/ukui-search-app-data-service/dbus/org.ukui.appdatabase.xml +++ b/ukui-search-app-data-service/dbus/org.ukui.appdatabase.xml @@ -9,6 +9,10 @@ + + + +