diff --git a/CMakeLists.txt b/CMakeLists.txt index 723fdee..ade39f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,6 +88,7 @@ set(SOURCE_FILES 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/appdata/plugin/all-app-data-provider.cpp src/appdata/plugin/all-app-data-provider.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/plugin/all-app-data-provider.cpp b/src/appdata/plugin/all-app-data-provider.cpp new file mode 100644 index 0000000..a8935cc --- /dev/null +++ b/src/appdata/plugin/all-app-data-provider.cpp @@ -0,0 +1,182 @@ +/* + * 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 "all-app-data-provider.h" +#include "app-data-manager.h" +#include "app-folder-helper.h" + +#include + +namespace UkuiMenu { + +AllAppDataProvider::AllAppDataProvider() : DataProviderPluginIFace() +{ + reloadFolderData(); + reloadAppData(); + + connect(AppDataManager::instance(), &AppDataManager::appAdded, this, &AllAppDataProvider::onAppAdded); + connect(AppDataManager::instance(), &AppDataManager::appDeleted, this, &AllAppDataProvider::onAppDeleted); + connect(AppDataManager::instance(), &AppDataManager::appUpdated, this, &AllAppDataProvider::onAppUpdated); + connect(AppFolderHelper::instance(), &AppFolderHelper::folderDataChanged, this, &AllAppDataProvider::onAppFolderChanged); +} + +int AllAppDataProvider::index() +{ + return 0; +} + +QString AllAppDataProvider::name() +{ + return tr("All"); +} + +QString AllAppDataProvider::icon() +{ + return "text-plain"; +} + +QString AllAppDataProvider::title() +{ + return "Recently installed"; +} + +PluginGroup::Group AllAppDataProvider::group() +{ + return PluginGroup::SortMenuItem; +} + +QVector AllAppDataProvider::data() +{ + QVector data; + mergeData(data); + return data; +} + +void AllAppDataProvider::forceUpdate() +{ + reloadFolderData(); + reloadAppData(); + sendData(); +} + +void AllAppDataProvider::reloadAppData() +{ + QMutexLocker locker(&m_mutex); + m_appData.clear(); + + // TODO 验证多线程间隐式共享数复制后导致迭代器实现问题 + QList apps = AppDataManager::instance()->normalApps(); + if (apps.isEmpty()) { + return; + } + + for (const auto &app : apps) { + if (!m_folderApps.contains(app.id())) { + m_appData.append(app); + } + } + + std::sort(m_appData.begin(), m_appData.end(), [](const DataEntity &a, const DataEntity &b) { + return (a.top() > b.top()) || (a.launchTimes() > b.launchTimes()); + }); +} + +void AllAppDataProvider::reloadFolderData() +{ + QMutexLocker locker(&m_mutex); + + m_folderApps.clear(); + m_folderData.clear(); + + QVector folders = AppFolderHelper::instance()->folderData(); + if (folders.isEmpty()) { + return; + } + + std::sort(folders.begin(), folders.end(), [](const Folder &a, const Folder &b) { + return a.index < b.index; + }); + + DataEntity folderItem; + for (const auto &folder : folders) { + folderItem.setType(DataType::Folder); + folderItem.setIcon("image://appicon/text-plain"); + folderItem.setName(folder.name); + + m_folderApps.unite(folder.apps.toSet()); + m_folderData.append(folderItem); + } +} + +void AllAppDataProvider::mergeData(QVector &data) +{ + QMutexLocker locker(&m_mutex); + data.append(m_folderData); + data.append(m_appData.toVector()); +} + +void AllAppDataProvider::sendData() +{ + QVector data; + mergeData(data); + Q_EMIT dataChanged(data); +} + +void AllAppDataProvider::onAppFolderChanged() +{ + reloadFolderData(); + sendData(); +} + +void AllAppDataProvider::onAppAdded(const QList& apps) +{ + { + QMutexLocker locker(&m_mutex); + m_appData.append(apps); + } + sendData(); +} + +void AllAppDataProvider::onAppDeleted(QStringList idList) +{ + removeApps(idList); + sendData(); +} + +void AllAppDataProvider::removeApps(QStringList &idList) +{ + QMutexLocker locker(&m_mutex); + + QList::iterator iterator = m_appData.begin(); + while (iterator != m_appData.end() && !idList.isEmpty()) { + if (idList.removeOne((*iterator).id())) { + iterator = m_appData.erase(iterator); + continue; + } + ++iterator; + } +} + +void AllAppDataProvider::onAppUpdated(const QList& apps) +{ + Q_UNUSED(apps); + reloadAppData(); + sendData(); +} + +} // UkuiMenu diff --git a/src/appdata/plugin/all-app-data-provider.h b/src/appdata/plugin/all-app-data-provider.h new file mode 100644 index 0000000..b2c9498 --- /dev/null +++ b/src/appdata/plugin/all-app-data-provider.h @@ -0,0 +1,64 @@ +/* + * 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_ALL_APP_DATA_PROVIDER_H +#define UKUI_MENU_ALL_APP_DATA_PROVIDER_H + +#include "data-provider-plugin-iface.h" +#include +#include + +namespace UkuiMenu { + +class AllAppDataProvider : public DataProviderPluginIFace +{ + Q_OBJECT +public: + explicit AllAppDataProvider(); + int index() override; + QString name() override; + QString icon() override; + QString title() override; + PluginGroup::Group group() override; + QVector data() override; + void forceUpdate() override; + +private Q_SLOTS: + void onAppAdded(const QList& apps); + void onAppDeleted(QStringList idList); + void onAppUpdated(const QList& apps); + // TODO 文件夹数据新增,删除信号处理 + void onAppFolderChanged(); + +private: + inline void sendData(); + void removeApps(QStringList& idList); + void reloadAppData(); + void reloadFolderData(); + void mergeData(QVector &data); + +private: + QMutex m_mutex; + QSet m_folderApps; + QList m_appData; + QVector m_folderData; +}; + +} // UkuiMenu + +#endif //UKUI_MENU_ALL_APP_DATA_PROVIDER_H