diff --git a/CMakeLists.txt b/CMakeLists.txt
index d991a26..723fdee 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -27,7 +27,7 @@ find_package(PkgConfig REQUIRED)
set(UKUI_MENU_EXTERNAL_LIBS "")
# glib-2.0 gio-unix-2.0 gsettings-qt x11 kysdk-waylandhelper
-set(UKUI_MENU_PC_PKGS glib-2.0 gio-unix-2.0 gsettings-qt x11 kysdk-waylandhelper)
+set(UKUI_MENU_PC_PKGS glib-2.0 gio-unix-2.0 gsettings-qt x11 kysdk-waylandhelper ukui-search)
foreach(external_lib IN ITEMS ${UKUI_MENU_PC_PKGS})
pkg_check_modules(${external_lib} REQUIRED ${external_lib})
@@ -87,6 +87,7 @@ set(SOURCE_FILES
src/extension/menu-extension.cpp src/extension/menu-extension.h
src/extension/menu-extension-iface.h
src/appdata/data-provider-plugin-iface.h
+ src/appdata/app-data-manager.cpp src/appdata/app-data-manager.h
src/extension/extensions/folder-extension.cpp src/extension/extensions/folder-extension.h
src/extension/extensions/recent-file-extension.cpp src/extension/extensions/recent-file-extension.h
)
diff --git a/src/appdata/app-data-manager.cpp b/src/appdata/app-data-manager.cpp
new file mode 100644
index 0000000..d5d6ece
--- /dev/null
+++ b/src/appdata/app-data-manager.cpp
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2023, KylinSoft Co., Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#include "app-data-manager.h"
+
+#include
+
+#define APP_ICON_PREFIX "image://appicon/"
+
+namespace UkuiMenu {
+
+class AppDataWorker : public QObject
+{
+ Q_OBJECT
+public:
+ explicit AppDataWorker(AppDataManager *appManager = nullptr);
+
+Q_SIGNALS:
+ void appDataChanged();
+ void favoriteAppChanged();
+ void appDataBaseOpenFailed();
+
+private Q_SLOTS:
+ void initAppData();
+ void onAppAdded(const QVector &infos);
+ void onAppUpdated(QVector infos);
+ void onAppDeleted(QStringList infos);
+
+private:
+ void updateFavoriteApps();
+
+private:
+ AppDataManager *m_appManager{nullptr};
+ UkuiSearch::AppInfoTable *m_appInfoTable = nullptr;
+};
+
+AppDataWorker::AppDataWorker(AppDataManager *appManager) : QObject(nullptr), m_appManager(appManager)
+{
+ m_appInfoTable = new UkuiSearch::AppInfoTable(this);
+ if (!m_appInfoTable || !m_appManager) {
+ return;
+ }
+
+ initAppData();
+
+ connect(m_appInfoTable, &UkuiSearch::AppInfoTable::appDBItems2BAdd, this, &AppDataWorker::onAppAdded);
+ connect(m_appInfoTable, &UkuiSearch::AppInfoTable::appDBItems2BUpdate, this, &AppDataWorker::onAppUpdated);
+ connect(m_appInfoTable, &UkuiSearch::AppInfoTable::appDBItems2BDelete, this, &AppDataWorker::onAppDeleted);
+ connect(m_appInfoTable, &UkuiSearch::AppInfoTable::DBOpenFailed, this, &AppDataWorker::appDataBaseOpenFailed);
+}
+
+void AppDataWorker::initAppData()
+{
+ QVector appInfos;
+ if (!m_appInfoTable->getAppInfoResults(appInfos)) {
+ return;
+ }
+
+ if (appInfos.isEmpty()) {
+ return;
+ }
+
+ // parse app-info
+ QVector normalApps;
+
+ for (const auto &info : appInfos) {
+ DataEntity app;
+ app.setTop(info.top);
+ app.setLock(info.lock == 1);
+ app.setFavorite(info.favorite);
+ app.setLaunchTimes(info.launchTimes);
+
+ app.setId(info.desktopPath);
+ app.setIcon(APP_ICON_PREFIX + info.iconName);
+ app.setName(info.appLocalName);
+ app.setCategory(info.category);
+ app.setFirstLetter(info.firstLetter);
+
+ normalApps.append(app);
+ }
+
+ {
+ QMutexLocker locker(&m_appManager->m_mutex);
+ m_appManager->m_normalApps.swap(normalApps);
+ }
+
+ updateFavoriteApps();
+}
+
+void AppDataWorker::updateFavoriteApps()
+{
+ QVector favoriteApps;
+ for (const auto &app : m_appManager->m_normalApps) {
+ if (app.favorite() > 0) {
+ favoriteApps.append(app);
+ }
+ }
+
+ if (favoriteApps.isEmpty()) {
+ return;
+ }
+
+ // 排序搜藏夹数据
+ std::sort(favoriteApps.begin(), favoriteApps.end(), [](const DataEntity& a, const DataEntity &b) {
+ return a.favorite() < b.favorite();
+ });
+
+ {
+ QMutexLocker locker(&m_appManager->m_mutex);
+ m_appManager->m_favoriteApps.swap(favoriteApps);
+ }
+
+ Q_EMIT favoriteAppChanged();
+}
+
+void AppDataWorker::onAppAdded(const QVector &infos)
+{
+ if (infos.isEmpty()) {
+ return;
+ }
+
+ {
+ QMutexLocker locker(&m_appManager->m_mutex);
+ for (const auto &info: infos) {
+ DataEntity app;
+ app.setTop(info.top);
+ app.setLock(info.lock == 1);
+ app.setFavorite(info.favorite);
+ app.setLaunchTimes(info.launchTimes);
+ app.setId(info.desktopPath);
+ app.setIcon(APP_ICON_PREFIX + info.iconName);
+ app.setName(info.appLocalName);
+ app.setCategory(info.category);
+ app.setFirstLetter(info.firstLetter);
+
+ m_appManager->m_normalApps.append(app);
+ }
+ }
+
+ Q_EMIT appDataChanged();
+}
+
+void AppDataWorker::onAppUpdated(QVector infos)
+{
+ if (infos.isEmpty()) {
+ return;
+ }
+
+ for (auto &app : m_appManager->m_normalApps) {
+ if (infos.isEmpty()) {
+ break;
+ }
+ for (int i = 0; i < infos.size(); ++i) {
+ const UkuiSearch::AppInfoResult &info = infos.at(i);
+ if (info.desktopPath == app.id()) {
+ QMutexLocker locker(&m_appManager->m_mutex);
+
+ app.setTop(info.top);
+ app.setLock(info.lock == 1);
+ app.setFavorite(info.favorite);
+ app.setLaunchTimes(info.launchTimes);
+ app.setIcon(APP_ICON_PREFIX + info.iconName);
+ app.setName(info.appLocalName);
+ app.setCategory(info.category);
+ app.setFirstLetter(info.firstLetter);
+
+ infos.remove(i);
+ break;
+ }
+ }
+ }
+
+ Q_EMIT appDataChanged();
+ updateFavoriteApps();
+}
+
+void AppDataWorker::onAppDeleted(QStringList infos)
+{
+ if (infos.isEmpty()) {
+ return;
+ }
+
+ QVector::iterator appIterator = m_appManager->m_normalApps.begin();
+ for (; appIterator != m_appManager->m_normalApps.end(); ++appIterator) {
+ if (infos.isEmpty()) {
+ break;
+ }
+
+ QStringList::iterator infoIterator = infos.begin();
+ for (; infoIterator != infos.end(); ++infoIterator) {
+ if ((*appIterator).id() == *infoIterator) {
+ QMutexLocker locker(&m_appManager->m_mutex);
+ m_appManager->m_normalApps.erase(appIterator);
+ infos.erase(infoIterator);
+ break;
+ }
+ }
+ }
+
+ Q_EMIT appDataChanged();
+ updateFavoriteApps();
+}
+
+// ===== AppDataManager ===== //
+AppDataManager *AppDataManager::instance()
+{
+ static AppDataManager appDataManager;
+ return &appDataManager;
+}
+
+AppDataManager::AppDataManager()
+{
+ AppDataWorker *appDataWorker = new AppDataWorker(this);
+ appDataWorker->moveToThread(&m_workerThread);
+
+ connect(&m_workerThread, &QThread::finished, appDataWorker, &QObject::deleteLater);
+ connect(appDataWorker, &AppDataWorker::appDataChanged, this, &AppDataManager::appDataChanged);
+ connect(appDataWorker, &AppDataWorker::favoriteAppChanged, this, &AppDataManager::favoriteAppChanged);
+
+ m_workerThread.start();
+}
+
+AppDataManager::~AppDataManager()
+{
+ m_workerThread.quit();
+ m_workerThread.wait();
+}
+
+QVector AppDataManager::normalApps()
+{
+ QMutexLocker locker(&m_mutex);
+ return m_normalApps;
+}
+
+QVector AppDataManager::favoriteApps()
+{
+ QMutexLocker locker(&m_mutex);
+ return m_favoriteApps;
+}
+
+} // UkuiMenu
+
+#include "app-data-manager.moc"
diff --git a/src/appdata/app-data-manager.h b/src/appdata/app-data-manager.h
new file mode 100644
index 0000000..4d01933
--- /dev/null
+++ b/src/appdata/app-data-manager.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2023, KylinSoft Co., Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#ifndef UKUI_MENU_APP_DATA_MANAGER_H
+#define UKUI_MENU_APP_DATA_MANAGER_H
+
+#include
+#include
+#include
+#include
+#include
+
+#include "commons.h"
+
+namespace UkuiMenu {
+
+class AppDataManager : public QObject
+{
+ friend class AppDataWorker;
+ Q_OBJECT
+public:
+ static AppDataManager *instance();
+
+ ~AppDataManager() override;
+
+ AppDataManager(const AppDataManager& obj) = delete;
+ AppDataManager &operator=(const AppDataManager& obj) = delete;
+ AppDataManager(AppDataManager&& obj) = delete;
+ AppDataManager &operator=(AppDataManager&& obj) = delete;
+
+ QVector normalApps();
+ QVector favoriteApps();
+
+Q_SIGNALS:
+ void appDataChanged();
+ void favoriteAppChanged();
+
+private:
+ AppDataManager();
+
+private:
+ QMutex m_mutex;
+ QThread m_workerThread;
+ QVector m_normalApps;
+ QVector m_favoriteApps;
+};
+
+} // UkuiMenu
+
+#endif //UKUI_MENU_APP_DATA_MANAGER_H
diff --git a/src/commons.cpp b/src/commons.cpp
index 5c645e5..10c740b 100644
--- a/src/commons.cpp
+++ b/src/commons.cpp
@@ -20,17 +20,128 @@
#include
-UkuiMenu::DataEntity::DataEntity(const UkuiMenu::DataEntity &obj)
-{
- m_type = obj.m_type;
- m_name = obj.m_name;
- m_icon = obj.m_icon;
- m_comment = obj.m_comment;
- m_extraData = obj.m_extraData;
-}
-
UkuiMenu::DataEntity::DataEntity(UkuiMenu::DataType::Type type, QString name, QString icon, QString comment, QString extraData)
: m_type(type), m_name(std::move(name)), m_icon(std::move(icon)), m_comment(std::move(comment)), m_extraData(std::move(extraData))
{
}
+
+int UkuiMenu::DataEntity::top() const
+{
+ return m_top;
+}
+
+void UkuiMenu::DataEntity::setTop(int top)
+{
+ m_top = top;
+}
+
+bool UkuiMenu::DataEntity::isLock() const
+{
+ return m_lock;
+}
+
+void UkuiMenu::DataEntity::setLock(bool lock)
+{
+ m_lock = lock;
+}
+
+int UkuiMenu::DataEntity::favorite() const
+{
+ return m_favorite;
+}
+
+void UkuiMenu::DataEntity::setFavorite(int favorite)
+{
+ m_favorite = favorite;
+}
+
+int UkuiMenu::DataEntity::launchTimes() const
+{
+ return m_launchTimes;
+}
+
+void UkuiMenu::DataEntity::setLaunchTimes(int launchTimes)
+{
+ m_launchTimes = launchTimes;
+}
+
+QString UkuiMenu::DataEntity::id() const
+{
+ return m_id;
+}
+
+void UkuiMenu::DataEntity::setId(const QString &id)
+{
+ m_id = id;
+}
+
+void UkuiMenu::DataEntity::setCategory(const QString &category)
+{
+ m_category = category;
+}
+
+QString UkuiMenu::DataEntity::category() const
+{
+ return m_category;
+}
+
+void UkuiMenu::DataEntity::setFirstLetter(const QString &firstLetter)
+{
+ m_firstLetter = firstLetter;
+}
+
+QString UkuiMenu::DataEntity::firstLetter() const
+{
+ return m_firstLetter;
+}
+
+void UkuiMenu::DataEntity::setType(UkuiMenu::DataType::Type type)
+{
+ m_type = type;
+}
+
+UkuiMenu::DataType::Type UkuiMenu::DataEntity::type() const
+{
+ return m_type;
+}
+
+void UkuiMenu::DataEntity::setIcon(const QString &icon)
+{
+ m_icon = icon;
+}
+
+QString UkuiMenu::DataEntity::icon() const
+{
+ return m_icon;
+}
+
+void UkuiMenu::DataEntity::setName(const QString &name)
+{
+ m_name = name;
+}
+
+QString UkuiMenu::DataEntity::name() const
+{
+ return m_name;
+}
+
+void UkuiMenu::DataEntity::setComment(const QString &comment)
+{
+ m_comment = comment;
+}
+
+QString UkuiMenu::DataEntity::comment() const
+{
+ return m_comment;
+}
+
+void UkuiMenu::DataEntity::setExtraData(const QString &extraData)
+{
+ m_extraData = extraData;
+}
+
+QString UkuiMenu::DataEntity::extraData() const
+{
+ return m_extraData;
+}
diff --git a/src/commons.h b/src/commons.h
index 1b31b51..b472467 100644
--- a/src/commons.h
+++ b/src/commons.h
@@ -68,30 +68,57 @@ public:
ExtraData
};
DataEntity() = default;
- DataEntity(const DataEntity& obj);
DataEntity(DataType::Type type, QString name, QString icon, QString comment, QString extraData);
- void setType(DataType::Type type) {m_type = type;}
- DataType::Type type() {return m_type;}
+ int top() const;
+ void setTop(int top);
- void setIcon(const QString& icon) {m_icon = icon;}
- QString icon() {return m_icon;}
+ bool isLock() const;
+ void setLock(bool lock);
- void setName(const QString& name) {m_name = name;}
- QString name() {return m_name;}
+ int favorite() const;
+ void setFavorite(int favorite);
- void setComment(const QString& comment) {m_comment = comment;}
- QString comment() {return m_comment;}
+ int launchTimes() const;
+ void setLaunchTimes(int launchTimes);
- void setExtraData(const QString& extraData) {m_extraData = extraData;}
- QString extraData() {return m_extraData;}
+ QString id() const;
+ void setId(const QString& id);
+
+ void setCategory(const QString& category);
+ QString category() const;
+
+ void setFirstLetter(const QString& firstLetter);
+ QString firstLetter() const;
+
+ void setType(DataType::Type type);
+ DataType::Type type() const;
+
+ void setIcon(const QString& icon);
+ QString icon() const;
+
+ void setName(const QString& name);
+ QString name() const;
+
+ void setComment(const QString& comment);
+ QString comment() const;
+
+ void setExtraData(const QString& extraData);
+ QString extraData() const;
private:
+ bool m_lock{false}; // 应用锁定
+ int m_top{0}; // 置顶状态及序号
+ int m_favorite{0}; // 收藏状态及序号
+ int m_launchTimes{0}; // 启动次数
+ DataType::Type m_type {DataType::Normal};
+ QString m_id; // 应用可执行文件路径
QString m_icon;
QString m_name;
- QString m_comment; // 应用描述
- QString m_extraData; // 额外的数据
- DataType::Type m_type {DataType::Normal};
+ QString m_category;
+ QString m_firstLetter;
+ QString m_comment; // 应用描述
+ QString m_extraData; // 额外的数据
};
class CommonsModule