From 68e8b9bd7f2c51c647a34db74c19ba169284718a Mon Sep 17 00:00:00 2001 From: JunjieBai Date: Mon, 4 Dec 2023 16:49:52 +0800 Subject: [PATCH] feat(app-database-service):add the support for flatpak & kaiming applications. --- libsearch/appdata/app-info-table.cpp | 2 +- ukui-search-app-data-service/CMakeLists.txt | 3 +- .../app-db-manager.cpp | 177 +++++++----------- ukui-search-app-data-service/app-db-manager.h | 13 +- .../conf/application-dirs.conf | 1 + 5 files changed, 83 insertions(+), 113 deletions(-) create mode 100644 ukui-search-app-data-service/conf/application-dirs.conf diff --git a/libsearch/appdata/app-info-table.cpp b/libsearch/appdata/app-info-table.cpp index 9a1efa5..b53ed4e 100644 --- a/libsearch/appdata/app-info-table.cpp +++ b/libsearch/appdata/app-info-table.cpp @@ -37,7 +37,7 @@ AppInfoTablePrivate::AppInfoTablePrivate(AppInfoTable *parent) : QObject(parent) "org.ukui.search.signalTransformer"); if (!m_signalTransInterface->isValid()) { - qCritical() << "Create privateDirWatcher Interface Failed Because: " << QDBusConnection::sessionBus().lastError(); + qCritical() << "Create signalTransformer Interface Failed Because: " << QDBusConnection::sessionBus().lastError(); return; } else { connect(m_signalTransInterface, SIGNAL(appDBItemsUpdate(ApplicationInfoMap)), this, SLOT(sendAppDBItemsUpdate(ApplicationInfoMap))); diff --git a/ukui-search-app-data-service/CMakeLists.txt b/ukui-search-app-data-service/CMakeLists.txt index d40c3f9..f0c3363 100644 --- a/ukui-search-app-data-service/CMakeLists.txt +++ b/ukui-search-app-data-service/CMakeLists.txt @@ -62,4 +62,5 @@ target_link_libraries(ukui-search-app-data-service PRIVATE install(TARGETS ukui-search-app-data-service DESTINATION /usr/bin) install(FILES ../data/ukui-search-app-data-service.desktop DESTINATION /etc/xdg/autostart) -install(FILES conf/com.ukui.search.appdb.service DESTINATION /usr/share/dbus-1/services/) \ No newline at end of file +install(FILES conf/com.ukui.search.appdb.service DESTINATION /usr/share/dbus-1/services/) +install(FILES conf/application-dirs.conf DESTINATION /etc/ukui/ukui-search/) \ No newline at end of file diff --git a/ukui-search-app-data-service/app-db-manager.cpp b/ukui-search-app-data-service/app-db-manager.cpp index 6007f99..ea458a1 100644 --- a/ukui-search-app-data-service/app-db-manager.cpp +++ b/ukui-search-app-data-service/app-db-manager.cpp @@ -37,6 +37,8 @@ #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"; +static const QString ALL_APP_DIRS_CONF = "/etc/ukui/ukui-search/application-dirs.conf"; + using namespace UkuiSearch; static AppDBManager *global_instance; @@ -98,9 +100,13 @@ AppDBManager::AppDBManager(QObject *parent) : QThread(parent), m_database(QSqlDa } //刷新应用数据 - QStringList appPaths; - appPaths << GENERAL_APP_DESKTOP_PATH << ANDROID_APP_DESKTOP_PATH - << SNAPD_APP_DESKTOP_PATH << AUTOSTART_APP_DESKTOP_PATH; + QFile file(ALL_APP_DIRS_CONF); + file.open(QIODevice::ReadOnly); + QString content = file.readAll(); + file.close(); + + QStringList appPaths = content.split(",",Qt::SkipEmptyParts); + appPaths.append(ANDROID_APP_DESKTOP_PATH); refreshAllData2DB(appPaths, m_dbVersionNeedUpdate); if (m_dbVersionNeedUpdate) { @@ -111,64 +117,7 @@ AppDBManager::AppDBManager(QObject *parent) : QThread(parent), m_database(QSqlDa } //初始化FileSystemWatcher - initFileSystemWatcher(); - - /* - //初始化FileSystemWatcher - m_watchAppDir = new QFileSystemWatcher(this); - m_watchAppDir->addPath(GENERAL_APP_DESKTOP_PATH); - QDir androidPath(ANDROID_APP_DESKTOP_PATH); - if(!androidPath.exists()) { - androidPath.mkpath(ANDROID_APP_DESKTOP_PATH); - } - m_watchAppDir->addPath(ANDROID_APP_DESKTOP_PATH); - - QDir snapdPath(SNAPD_APP_DESKTOP_PATH); - if(!snapdPath.exists()) { - snapdPath.mkpath(SNAPD_APP_DESKTOP_PATH); - } - m_watchAppDir->addPath(SNAPD_APP_DESKTOP_PATH); - - //初始化timer - this->start(); - m_timer = new QTimer(); - m_maxProcessTimer = new QTimer(); - - m_timer->setInterval(2*1000); - m_maxProcessTimer->setInterval(5*1000); - - m_timer->setSingleShot(true); - m_maxProcessTimer->setSingleShot(true); - - m_timer->moveToThread(this); - m_maxProcessTimer->moveToThread(this); - - connect(this, SIGNAL(startTimer()), m_timer, SLOT(start())); - connect(this, SIGNAL(maxProcessTimerStart()), m_maxProcessTimer, SLOT(start())); - connect(this, &AppDBManager::stopTimer, m_timer, &QTimer::stop); - connect(this, &AppDBManager::stopTimer, m_maxProcessTimer, &QTimer::stop); - - //监听desktop文件所在目录,由于directoryChange会发多次信号,使用计时器阻塞 - connect(m_watchAppDir, &QFileSystemWatcher::directoryChanged, this, [ = ](const QString & path) { - qDebug() << "m_watchAppDir directoryChanged:" << path; - Q_EMIT this->startTimer(); - if (!m_maxProcessTimer->isActive()) { - Q_EMIT this->maxProcessTimerStart(); - } - }); - - //计时器超时统一进行更新操作 - connect(m_timer, &QTimer::timeout, this, [ & ] { - qDebug() << "Time out! Now I can update the database!"; - Q_EMIT this->stopTimer(); - 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->refreshAllData2DB(); - }, Qt::DirectConnection); - */ + initFileSystemWatcher(appPaths); m_processManagerInterface = new QDBusInterface(QStringLiteral("com.kylin.ProcessManager"), QStringLiteral("/com/kylin/ProcessManager/AppLauncher"), @@ -250,58 +199,14 @@ void AppDBManager::buildAppInfoDB() } } -void AppDBManager::initFileSystemWatcher() +void AppDBManager::initFileSystemWatcher(const QStringList& appDirs) { m_watcher = new FileSystemWatcher; - m_watcher->addWatch(GENERAL_APP_DESKTOP_PATH); - QDir androidDir(ANDROID_APP_DESKTOP_PATH); - if(!androidDir.exists()) { - androidDir.mkpath(ANDROID_APP_DESKTOP_PATH); + + auto helper = new ApplicationDirWatcherHelper(m_watcher, this); + for (const QString& appDir : appDirs) { + helper->addPath(appDir); } - m_watcher->addWatch(ANDROID_APP_DESKTOP_PATH); - - m_snapdDir = new QDir(SNAPD_APP_DESKTOP_PATH); - if(!m_snapdDir->exists()) { - m_snapdWatcher = new FileSystemWatcher(false); - QDir dir("/var/lib/snapd"); - if (!dir.exists()) { - dir.setPath("/var/lib"); - } - m_snapdPath = dir.absolutePath(); - m_snapdWatcher->addWatch(m_snapdPath); - } else { - m_watcher->addWatch(SNAPD_APP_DESKTOP_PATH); - } - - m_watcher->addWatch(AUTOSTART_APP_DESKTOP_PATH); - - connect(m_snapdWatcher, &FileSystemWatcher::created, this, [ = ] (const QString &path, bool isDir) { - if (isDir) { - //监测新增目录为/var/lib/snapd时,将其替换为snapdWatcher的watch path - if (path == "/var/lib/snapd") { - m_snapdWatcher->removeWatch(m_snapdPath); - m_snapdWatcher->addWatch(path); - qDebug() << "~~~~~~~add watch" << path << "~~~~~remove watch" << m_snapdPath; - m_snapdPath = path; - //snapd下的desktop目录可能在还没替换监听目录为/var/lib/snapd时就已经被创建,因此需要特别判断 - QDir dir("/var/lib/snapd/desktop"); - if (dir.exists()) { - if (m_snapdDir->exists()) { - m_watcher->addWatch(SNAPD_APP_DESKTOP_PATH); - m_snapdWatcher->removeWatch(m_snapdPath); - qDebug() << "======add watch" << SNAPD_APP_DESKTOP_PATH << "======remove watch" << m_snapdPath; - } - } - } - //检测到/var/lib/snapd/desktop被创建,则将监听目录替换为/var/lib/snapd/desktop/applications - if (path == "/var/lib/snapd/desktop" and m_snapdDir->exists()) { - m_watcher->addWatch(SNAPD_APP_DESKTOP_PATH); - m_snapdWatcher->removeWatch(m_snapdPath); - qDebug() << "======add watch" << SNAPD_APP_DESKTOP_PATH << "======remove watch" << m_snapdPath; - } - - } - }); connect(m_watcher, &FileSystemWatcher::created, this, [ = ] (const QString &desktopfp, bool isDir) { //event is IN_CREATE @@ -1702,3 +1607,55 @@ void AppDBManager::handleAppLaunched(QString desktopFilePath) { qWarning() << "desktopFilePath is empty."; } } + +ApplicationDirWatcherHelper::ApplicationDirWatcherHelper(FileSystemWatcher *watcher, QObject *parent) : QObject(parent), m_watcher(watcher) +{ +} + +void ApplicationDirWatcherHelper::addPath(const QString &path) { + QDir dir(path); + if (dir.exists() || dir.mkpath(path)) { + qDebug() << "=====add desktop watch=====" << path; + m_watcher->addWatch(path); + return; + } + + auto watcher = new FileSystemWatcher(false); + m_watcherMap.insert(path, watcher); + + while (!dir.exists()) { + QString dirPath = dir.absolutePath(); + dir.setPath(dirPath.left(dirPath.lastIndexOf("/"))); + } + qDebug() << "=====addWatch=====" << dir.absolutePath(); + watcher->addWatch(dir.absolutePath()); + + connect(watcher, &FileSystemWatcher::created, this, [ &,watcher ] (const QString &path, bool isDir) { + if (isDir) { + QString appPath = m_watcherMap.key(watcher); + if (appPath == path) { + qDebug() << "=====add desktop watch=====" << appPath; + m_watcher->addWatch(path); + m_watcherMap.value(appPath)->deleteLater(); + m_watcherMap.remove(appPath); + } else if (appPath.startsWith(path+ "/")) { + watcher->clearAll(); + QDir dir(appPath); + //会有类似mkdir -p的一次性将子文件夹创建出来的情况,需要挨层判断 + while (!dir.exists()) { + dir.setPath(dir.absolutePath().left(dir.absolutePath().lastIndexOf("/"))); + } + if (dir.absolutePath() == appPath) { + qDebug() << "=====add desktop watch=====" << appPath; + m_watcher->addWatch(appPath); + m_watcherMap.value(appPath)->deleteLater(); + m_watcherMap.remove(appPath); + } else { + qDebug() << "=====addWatch=====" << dir.absolutePath(); + watcher->addWatch(dir.absolutePath()); + } + } + } + }); + +} \ No newline at end of file diff --git a/ukui-search-app-data-service/app-db-manager.h b/ukui-search-app-data-service/app-db-manager.h index 413fb96..6552720 100644 --- a/ukui-search-app-data-service/app-db-manager.h +++ b/ukui-search-app-data-service/app-db-manager.h @@ -135,7 +135,7 @@ private: void buildAppInfoDB(); //初始化fileSystemWatcher - void initFileSystemWatcher(); + void initFileSystemWatcher(const QStringList& appDirs); //处理置顶收藏移动位置 bool handleChangeFavoritesPos(const QString &desktopFilePath, const uint pos, const uint previousPos, ApplicationInfoMap &updatedInfo); @@ -253,6 +253,17 @@ Q_SIGNALS: void maxProcessTimerStart(); void stopTimer(); }; + +class ApplicationDirWatcherHelper : public QObject +{ + Q_OBJECT +public: + explicit ApplicationDirWatcherHelper(FileSystemWatcher *watcher,QObject *parent = nullptr); + void addPath(const QString& path); +private: + FileSystemWatcher *m_watcher = nullptr; + QMap m_watcherMap; +}; } #endif // APPDBMANAGER_H diff --git a/ukui-search-app-data-service/conf/application-dirs.conf b/ukui-search-app-data-service/conf/application-dirs.conf new file mode 100644 index 0000000..bb3b13d --- /dev/null +++ b/ukui-search-app-data-service/conf/application-dirs.conf @@ -0,0 +1 @@ +/usr/share/applications,/var/lib/snapd/desktop/applications,/var/lib/flatpak/exports/share/applications,/var/lib/kaiming/exports/share/applications \ No newline at end of file