From 898b61d312f49be13b96a55d19f26120f1ffaa5a Mon Sep 17 00:00:00 2001 From: qiqi49 Date: Fri, 19 Jan 2024 11:10:07 +0800 Subject: [PATCH] =?UTF-8?q?feat(extension):=E5=AE=9E=E7=8E=B0=E6=94=B6?= =?UTF-8?q?=E8=97=8F=E5=8C=BA=E5=9F=9F=E6=98=BE=E7=A4=BA=E5=BA=94=E7=94=A8?= =?UTF-8?q?=E7=BB=84=E5=92=8C=E5=8F=B3=E9=94=AE=E8=8F=9C=E5=8D=95=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 4 + src/data-entity.h | 3 +- src/extension/context-menu-extension.h | 2 +- src/extension/favorite/app-favorite-model.cpp | 316 ++++++++++++++++ src/extension/favorite/app-favorite-model.h | 71 ++++ .../favorite/favorite-context-menu.cpp | 75 +++- .../favorite/favorite-context-menu.h | 4 + .../favorite/favorite-folder-helper.cpp | 354 ++++++++++++++++++ .../favorite/favorite-folder-helper.h | 97 +++++ src/extension/favorite/favorite-widget.cpp | 8 +- src/extension/favorite/favorite-widget.h | 1 + src/extension/favorite/favorites-config.cpp | 162 ++++++++ src/extension/favorite/favorites-config.h | 45 +++ src/extension/favorite/favorites-model.cpp | 95 +++++ src/extension/favorite/favorites-model.h | 51 +++ src/extension/menu/app-menu-plugin.cpp | 2 +- src/libappdata/app-database-interface.cpp | 23 +- src/libappdata/app-database-interface.h | 12 +- src/libappdata/basic-app-model.cpp | 2 +- src/libappdata/basic-app-model.h | 2 +- src/model/folder-model.cpp | 12 +- 21 files changed, 1314 insertions(+), 27 deletions(-) create mode 100644 src/extension/favorite/app-favorite-model.cpp create mode 100644 src/extension/favorite/app-favorite-model.h create mode 100644 src/extension/favorite/favorite-folder-helper.cpp create mode 100644 src/extension/favorite/favorite-folder-helper.h create mode 100644 src/extension/favorite/favorites-config.cpp create mode 100644 src/extension/favorite/favorites-config.h create mode 100644 src/extension/favorite/favorites-model.cpp create mode 100644 src/extension/favorite/favorites-model.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b74783..f07c9fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,6 +129,10 @@ set(SOURCE_FILES src/extension/favorite/favorite-extension-plugin.cpp src/extension/favorite/favorite-extension-plugin.h src/extension/favorite/favorite-context-menu.cpp src/extension/favorite/favorite-context-menu.h src/extension/favorite/favorite-widget.cpp src/extension/favorite/favorite-widget.h + src/extension/favorite/app-favorite-model.cpp src/extension/favorite/app-favorite-model.h + src/extension/favorite/favorites-config.cpp src/extension/favorite/favorites-config.h + src/extension/favorite/favorites-model.cpp src/extension/favorite/favorites-model.h + src/extension/favorite/favorite-folder-helper.cpp src/extension/favorite/favorite-folder-helper.h src/libappdata/basic-app-model.cpp src/libappdata/basic-app-model.h src/libappdata/app-database-interface.cpp src/libappdata/app-database-interface.h ) diff --git a/src/data-entity.h b/src/data-entity.h index e82d915..1f7adc2 100644 --- a/src/data-entity.h +++ b/src/data-entity.h @@ -34,7 +34,8 @@ public: enum Type { Normal, // 普通Item Label, // 标签数据 - Folder // 文件夹 + Folder, // 应用组 + Files // 文件夹 }; Q_ENUM(Type); }; diff --git a/src/extension/context-menu-extension.h b/src/extension/context-menu-extension.h index f1b0e58..9b33877 100644 --- a/src/extension/context-menu-extension.h +++ b/src/extension/context-menu-extension.h @@ -34,7 +34,7 @@ public: Extension, /**< 扩展页 */ FolderPage, /**< 文件夹页面 */ FullScreen, /**< 全屏应用列表 */ - FullScreenFolder, /**< 全屏文件夹页面 */ + Folder, /**< 应用组页面 */ }; Q_ENUM(Location) }; diff --git a/src/extension/favorite/app-favorite-model.cpp b/src/extension/favorite/app-favorite-model.cpp new file mode 100644 index 0000000..c06de8a --- /dev/null +++ b/src/extension/favorite/app-favorite-model.cpp @@ -0,0 +1,316 @@ +// +// Created by qiqi on 23-12-27. +// + +#include "favorites-config.h" +#include "app-favorite-model.h" +#include "favorite-folder-helper.h" + +#include +#include +#include +#include + +namespace UkuiMenu { + +AppFavoritesModel &AppFavoritesModel::instance() +{ + static AppFavoritesModel appFavoritesModel; + return appFavoritesModel; +} + +AppFavoritesModel::AppFavoritesModel(QObject *parent) : QAbstractListModel(parent) +{ + m_sourceModel = BasicAppModel::instance(); + + updateData(); + + connect(m_sourceModel, &BasicAppModel::dataChanged, this, &AppFavoritesModel::onAppUpdated); + connect(m_sourceModel, &BasicAppModel::rowsAboutToBeRemoved, this, &AppFavoritesModel::onAppRemoved); + connect(FavoriteFolderHelper::instance(), &FavoriteFolderHelper::folderAdded, this,&AppFavoritesModel::onFolderAdded); + connect(FavoriteFolderHelper::instance(), &FavoriteFolderHelper::folderToBeDeleted, this, &AppFavoritesModel::onFolderDeleted); + connect(FavoriteFolderHelper::instance(), &FavoriteFolderHelper::folderDataChanged, this, &AppFavoritesModel::onFolderChanged); +} + +AppFavoritesModel::~AppFavoritesModel() +{ +} + +QHash AppFavoritesModel::roleNames() const +{ + QHash names; + names.insert(DataEntity::Id, "id"); + names.insert(DataEntity::Icon, "icon"); + names.insert(DataEntity::Name, "name"); + names.insert(DataEntity::Type, "type"); + return names; +} + +int AppFavoritesModel::rowCount(const QModelIndex &parent) const +{ + return m_favoritesApps.count() + m_folders.count() + m_favoritesFiles.count(); +} + +QVariant AppFavoritesModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.row() >= rowCount()) { + return {}; + } + + if (index.row() < m_favoritesApps.count()) { + return m_favoritesApps.at(index.row()).data(role); + + } else if (index.row() < m_favoritesApps.count() + m_folders.count() && index.row() >= m_favoritesApps.count()) { + return folderData(index, role); + + } else { + return fileData(index, role); + } +} + +void AppFavoritesModel::getFavoritesApps() +{ + m_favoritesApps.clear(); + for (int i = 0; i < m_sourceModel->rowCount(QModelIndex()); i++) { + updateFavoritesApps(m_sourceModel->appOfIndex(i), m_sourceModel->index(i)); + } +} + +void AppFavoritesModel::onAppUpdated(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles) +{ + for (const auto &role : roles) { + if (role == DataEntity::Favorite) { + updateFavoritesApps(m_sourceModel->appOfIndex(topLeft.row()), topLeft); + } + } +} + +void AppFavoritesModel::getFoldersId() +{ + QVector foldersId; + for (const auto &folder : FavoriteFolderHelper::instance()->folderData()) { + foldersId.append(folder.getId()); + } + m_folders.swap(foldersId); +} + +void AppFavoritesModel::getFavoritesFiles() +{ +} + +void AppFavoritesModel::updateFavoritesApps(const DataEntity &app, const QModelIndex &sourceIndex) +{ + if (app.id().isEmpty()) { + return; + } + + if (app.favorite() > 0 && !FavoriteFolderHelper::instance()->containApp(app.id())) { + QPersistentModelIndex index(sourceIndex); + addFavoriteApp(index); + + } else if (app.favorite() == 0) { + QPersistentModelIndex index(sourceIndex); + removeFavoriteApp(index); + } +} + +void AppFavoritesModel::updateData() +{ + getFavoritesApps(); + getFoldersId(); + getFavoritesFiles(); +} + +QVariant AppFavoritesModel::folderData(const QModelIndex &index, int role) const +{ + FavoritesFolder folder; + int folderId = m_folders.at(index.row() - m_favoritesApps.count()); + if (!FavoriteFolderHelper::instance()->getFolderFromId(folderId, folder)) { + return {}; + } + + switch (role) { + case DataEntity::Id: + return QString::number(folder.getId()); + case DataEntity::Icon: + return FavoriteFolderHelper::folderIcon(folder).join(" "); + case DataEntity::Name: + return folder.getName(); + case DataEntity::Type: + return DataType::Folder; + default: + break; + } + + return {}; +} + +QVariant AppFavoritesModel::fileData(const QModelIndex &index, int role) const +{ + int fileIndex = index.row() - m_favoritesApps.count() - m_folders.count(); + QString url = m_favoritesFiles.at(fileIndex); + + switch (role) { + case DataEntity::Id: + return url; + case DataEntity::Icon: { + QMimeDatabase mimeDatabase; + return mimeDatabase.mimeTypeForFile(url).iconName(); + } + case DataEntity::Name: + return QUrl(url).fileName(); + case DataEntity::Type: + return DataType::Files; + default: + break; + } + + return {}; +} + +QStringList AppFavoritesModel::favoritesApps() const +{ + QMap apps; + for (auto index : m_favoritesApps) { + QString id = m_sourceModel->data(index, DataEntity::Id).toString(); + int favorite = m_sourceModel->data(index, DataEntity::Favorite).toInt(); + apps.insert(favorite, id); + } + + return apps.values(); +} + +void AppFavoritesModel::changeAppState(const QString &id, const int &index) +{ + if (id.isEmpty()) { + return; + } + + m_sourceModel->databaseInterface()->fixAppToFavorite(id, index); + + // 同步配置文件,更新应用顺序 + if (index > 0) { + FavoritesConfig::instance().insertValue(id, index); + } +} + +bool AppFavoritesModel::getApp(const QString &appid, DataEntity &app) +{ + return m_sourceModel->databaseInterface()->getApp(appid, app); +} + +void AppFavoritesModel::onAppRemoved(const QModelIndex &parent, int first, int last) +{ + for(int row = first; row <= last; ++row) { + QModelIndex sourceIndex = m_sourceModel->index(row, 0, {}); + QPersistentModelIndex index(sourceIndex); + + if (index.data(DataEntity::Favorite).toInt() > 0) { + QString appId = index.data(DataEntity::Id).toString(); + + if (!m_favoritesApps.contains(index) && FavoriteFolderHelper::instance()->containApp(appId)) { + FavoriteFolderHelper::instance()->removeAppFromFolder(appId); + } + + removeFavoriteApp(index); + } + } +} + +void AppFavoritesModel::addFavoriteApp(const QPersistentModelIndex &modelIndex) +{ + if (m_favoritesApps.contains(modelIndex)) { + return; + } + + beginInsertRows(QModelIndex(), m_favoritesApps.count(), m_favoritesApps.count()); + m_favoritesApps.append(modelIndex); + endInsertRows(); + + FavoritesConfig::instance().insertValue(modelIndex.data(DataEntity::Id).toString()); +} + +void AppFavoritesModel::removeFavoriteApp(const QPersistentModelIndex &modelIndex) +{ + if (!m_favoritesApps.contains(modelIndex)) { + return; + } + + beginRemoveRows(QModelIndex(), m_favoritesApps.indexOf(modelIndex), m_favoritesApps.indexOf(modelIndex)); + m_favoritesApps.removeOne(modelIndex); + endRemoveRows(); + + FavoritesConfig::instance().removeValueById(modelIndex.data(DataEntity::Id).toString()); +} + +void AppFavoritesModel::onFolderAdded(const int &folderId, const int &order) +{ + if (!m_folders.contains(folderId)) { + beginInsertRows(QModelIndex(), m_favoritesApps.count() + m_folders.count(), m_favoritesApps.count() + m_folders.count()); + m_folders.append(folderId); + endInsertRows(); + + FavoritesFolder folder; + FavoriteFolderHelper::instance()->getFolderFromId(folderId, folder); + for (auto app : folder.getApps()) { + removeFavoriteApp(getIndexFromAppId(app)); + } + + FavoritesConfig::instance().insertValue(QString::number(folderId), std::max(0, order)); + } +} + +void AppFavoritesModel::onFolderDeleted(const int &folderId, const QStringList &apps) +{ + if (m_folders.contains(folderId)) { + beginRemoveRows(QModelIndex(), m_favoritesApps.count() + m_folders.indexOf(folderId), m_favoritesApps.count() + m_folders.indexOf(folderId)); + m_folders.removeOne(folderId); + endRemoveRows(); + + for (auto app : apps) { + QPersistentModelIndex modelIndex(m_sourceModel->index(m_sourceModel->indexOfApp(app))); + addFavoriteApp(modelIndex); + } + + FavoritesConfig::instance().removeValueById(QString::number(folderId)); + } +} + +void AppFavoritesModel::onFolderChanged(const int &folderId, const QString &appId) +{ + QVector roles; + if (appId.isEmpty()) { + roles.append(DataEntity::Name); + int row = m_favoritesApps.count() + m_folders.indexOf(folderId); + + Q_EMIT dataChanged(index(row), index(row), roles); + return; + } + + if (FavoriteFolderHelper::instance()->containApp(appId)) { + removeFavoriteApp(getIndexFromAppId(appId)); + + } else { + QPersistentModelIndex modelIndex(m_sourceModel->index(m_sourceModel->indexOfApp(appId))); + addFavoriteApp(modelIndex); + } + + roles.append(DataEntity::Icon); + int row = m_favoritesApps.count() + m_folders.indexOf(folderId); + + Q_EMIT dataChanged(index(row), index(row), roles); +} + +QPersistentModelIndex AppFavoritesModel::getIndexFromAppId(const QString &id) const +{ + auto modelIndex = std::find_if(m_favoritesApps.constBegin(), m_favoritesApps.constEnd(), [&id] (const QPersistentModelIndex &index) { + return index.data(DataEntity::Id).toString() == id; + }); + + if (modelIndex == m_favoritesApps.constEnd()) { + return {}; + } + + return *modelIndex; +} +} // UkuiMenu diff --git a/src/extension/favorite/app-favorite-model.h b/src/extension/favorite/app-favorite-model.h new file mode 100644 index 0000000..26a9146 --- /dev/null +++ b/src/extension/favorite/app-favorite-model.h @@ -0,0 +1,71 @@ +// +// Created by qiqi on 23-12-27. +// + +#ifndef UKUI_MENU_APP_FAVORITE_MODEL_H +#define UKUI_MENU_APP_FAVORITE_MODEL_H + +#include "data-entity.h" +#include "libappdata/basic-app-model.h" + +#include +#include +#include + +namespace UkuiMenu { + +class AppFavoritesModel : public QAbstractListModel +{ +Q_OBJECT +public: + static AppFavoritesModel &instance(); + ~AppFavoritesModel() override; + QHash roleNames() const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role) const override; + + QStringList favoritesApps() const; + void changeAppState(const QString &id, const int &index); + bool getApp(const QString &appid, DataEntity &app); + +private: + explicit AppFavoritesModel(QObject *parent = nullptr); + + void getFavoritesApps(); + void getFoldersId(); + void getFavoritesFiles(); + void updateData(); + + void addFavoriteApp(const QPersistentModelIndex &modelIndex); + void removeFavoriteApp(const QPersistentModelIndex &modelIndex); + void onAppRemoved(const QModelIndex &parent, int first, int last); + void onAppUpdated(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles = QVector()); + void updateFavoritesApps(const DataEntity &app, const QModelIndex &sourceIndex); + QPersistentModelIndex getIndexFromAppId(const QString &id) const; + + void onFolderAdded(const int &folderId, const int &order); + void onFolderDeleted(const int &folderId, const QStringList &apps); + void onFolderChanged(const int &folderId, const QString &appId); + + QVariant folderData(const QModelIndex &index, int role) const; + QVariant fileData(const QModelIndex &index, int role) const; + +private: + /** + *不在应用组的收藏应用在baseModel的对应index + */ + QVector m_favoritesApps; + /** + *应用组的唯一Id + */ + QVector m_folders; + /** + *收藏文件夹的唯一路径 + */ + QVector m_favoritesFiles; + BasicAppModel *m_sourceModel = nullptr; +}; + +} // UkuiMenu + +#endif //UKUI_MENU_APP_FAVORITE_MODEL_H diff --git a/src/extension/favorite/favorite-context-menu.cpp b/src/extension/favorite/favorite-context-menu.cpp index 3a08bc7..9ec2205 100644 --- a/src/extension/favorite/favorite-context-menu.cpp +++ b/src/extension/favorite/favorite-context-menu.cpp @@ -17,7 +17,9 @@ */ #include "favorite-context-menu.h" +#include "favorite-folder-helper.h" #include "app-data-manager.h" +#include "favorites-model.h" #include "event-track.h" namespace UkuiMenu { @@ -35,33 +37,51 @@ FavoriteContextMenu::actions(const DataEntity &data, QMenu *parent, const MenuIn return {}; } - if (data.type() != DataType::Normal) { - return {}; - } - QList list; + if (data.type() == DataType::Folder) { + list << new QAction(QObject::tr("Dissolve folder"), parent); + QObject::connect(list.last(), &QAction::triggered, parent, [data] { + FavoriteFolderHelper::instance()->deleteFolder(data.id().toInt()); + }); + return list; + } + switch (location) { case MenuInfo::AppList: - case MenuInfo::FolderPage: - case MenuInfo::Extension: { + case MenuInfo::FolderPage: { if (data.favorite() == 0) { list << new QAction(QObject::tr("Fix to favorite"), parent); QObject::connect(list.last(), &QAction::triggered, parent, [data] { - Q_EMIT AppDataManager::instance()->fixToFavoriteSignal(data.id(), 1); + FavoritesModel::instance().addAppToFavorites(data.id()); EventTrack::instance()->sendDefaultEvent("fix_to_favorite", "Right-click Menu"); }); - } else if (locationId == "favorite") { + + } else if (data.favorite() > 0) { list << new QAction(QObject::tr("Remove from favorite"), parent); QObject::connect(list.last(), &QAction::triggered, parent, [data] { - Q_EMIT AppDataManager::instance()->fixToFavoriteSignal(data.id(), 0); + FavoritesModel::instance().removeAppFromFavorites(data.id()); EventTrack::instance()->sendDefaultEvent("remove_from_favorite", "Right-click Menu"); }); } break; } + case MenuInfo::Extension: { + QAction *action = new QAction(QObject::tr("Remove from favorite"), parent); + QObject::connect(action, &QAction::triggered, parent, [data] { + FavoritesModel::instance().removeAppFromFavorites(data.id()); + EventTrack::instance()->sendDefaultEvent("remove_from_favorite", "Right-click Menu"); + }); + list << action; + + appendActionsForAppsOutsideFolder(parent, data.id(), list); + break; + } case MenuInfo::FullScreen: - case MenuInfo::FullScreenFolder: + case MenuInfo::Folder: { + appendActionsForAppsInFolder(parent, data.id(), list); + break; + } default: break; } @@ -69,4 +89,39 @@ FavoriteContextMenu::actions(const DataEntity &data, QMenu *parent, const MenuIn return list; } +void FavoriteContextMenu::appendActionsForAppsInFolder(QObject *parent, const QString &appId, QList &list) +{ + FavoritesFolder folder; + + list << new QAction(QObject::tr("Remove from folder"), parent); + QObject::connect(list.last(), &QAction::triggered, parent, [appId] { + FavoriteFolderHelper::instance()->removeAppFromFolder(appId); + }); +} + +void FavoriteContextMenu::appendActionsForAppsOutsideFolder(QObject *parent, const QString &appId, QList &list) +{ + QAction *action = new QAction(QObject::tr("Add to folder"), parent); + + QMenu *subMenu = new QMenu(); + QAction *subAction = new QAction(QObject::tr("Create a new folder"), parent); + QObject::connect(subAction, &QAction::triggered, parent, [appId] { + FavoritesModel::instance().addAppToFolder(appId, ""); + }); + subMenu->addAction(subAction); + + for (auto folder : FavoriteFolderHelper::instance()->folderData()) { + QString folderName = folder.getName(); + int folderId = folder.getId(); + QAction *subAction = new QAction(QObject::tr("Add to ").append(folderName), parent); + QObject::connect(subAction, &QAction::triggered, parent, [appId, folderId] { + FavoritesModel::instance().addAppToFolder(appId, QString::number(folderId)); + }); + subMenu->addAction(subAction); + } + + action->setMenu(subMenu); + list << action; +} + } // UkuiMenu diff --git a/src/extension/favorite/favorite-context-menu.h b/src/extension/favorite/favorite-context-menu.h index 7ae19fa..3712305 100644 --- a/src/extension/favorite/favorite-context-menu.h +++ b/src/extension/favorite/favorite-context-menu.h @@ -30,6 +30,10 @@ public: QList actions(const DataEntity &data, QMenu *parent, const MenuInfo::Location &location, const QString &locationId) override; + +private: + void appendActionsForAppsInFolder(QObject *parent, const QString &appId, QList &list); + void appendActionsForAppsOutsideFolder(QObject *parent, const QString &appId, QList &list); }; } // UkuiMenu diff --git a/src/extension/favorite/favorite-folder-helper.cpp b/src/extension/favorite/favorite-folder-helper.cpp new file mode 100644 index 0000000..9128f61 --- /dev/null +++ b/src/extension/favorite/favorite-folder-helper.cpp @@ -0,0 +1,354 @@ +/* + * Copyright (C) 2022, 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 "favorite-folder-helper.h" +#include "app-data-manager.h" +#include "model-manager.h" +#include "app-model.h" +#include "event-track.h" +#include "favorites-config.h" + +#include +#include +#include +#include +#include +#include +#include + +#define FOLDER_FILE_PATH ".config/ukui-menu/" +#define FOLDER_FILE_NAME "folder0.json" + +namespace UkuiMenu { + +QString FavoriteFolderHelper::s_folderConfigFile = QDir::homePath() + "/" + FOLDER_FILE_PATH + FOLDER_FILE_NAME; + +FavoriteFolderHelper *FavoriteFolderHelper::instance() +{ + static FavoriteFolderHelper FavoriteFolderHelper; + return &FavoriteFolderHelper; +} + +FavoriteFolderHelper::FavoriteFolderHelper() +{ + qRegisterMetaType("FavoritesFolder"); + + if (!QFile::exists(s_folderConfigFile)) { + QDir dir; + QString folderConfigDir(QDir::homePath() + "/" + FOLDER_FILE_PATH); + if (!dir.exists(folderConfigDir)) { + if (!dir.mkdir(folderConfigDir)) { + qWarning() << "Unable to create profile folder."; + return; + } + } + + QFile file(s_folderConfigFile); + file.open(QFile::WriteOnly); + file.close(); + } + + readData(); +} + +FavoriteFolderHelper::~FavoriteFolderHelper() +{ + saveData(); +} + +void FavoriteFolderHelper::insertFolder(const FavoritesFolder &folder) +{ + QMutexLocker locker(&m_mutex); + m_folders.insert(folder.id, folder); +} + +void FavoriteFolderHelper::addAppToFolder(const QString &appId, const int &folderId) +{ + if (appId.isEmpty()) { + return; + } + + { + QMutexLocker locker(&m_mutex); + if (!m_folders.contains(folderId)) { + return; + } + + FavoritesFolder &folder = m_folders[folderId]; + if (folder.apps.contains(appId)) { + return; + } + + folder.apps.append(appId); + } + + forceSync(); + Q_EMIT folderDataChanged(folderId,appId); + + EventTrack::instance()->sendDefaultEvent("add_app_to_folder", "AppView"); +} + +void FavoriteFolderHelper::addAppToNewFolder(const QString &appId, const QString &folderName) +{ + if (appId.isEmpty()) { + return; + } + + // TODO: max越界处理 + int max = m_folders.isEmpty() ? -1 : m_folders.lastKey(); + QString name = folderName; + if (name.isEmpty()) { + name = tr("New Folder %1").arg(m_folders.size() + 1); + } + + FavoritesFolder folder; + folder.id = ++max; + folder.name = name; + folder.apps.append(appId); + + insertFolder(folder); + forceSync(); + Q_EMIT folderAdded(folder.id, FavoritesConfig::instance().getOrderById(appId)); + + EventTrack::instance()->sendDefaultEvent("add_app_to_new_folder", "AppView"); +} + +void FavoriteFolderHelper::addAppsToNewFolder(const QString &idFrom, const QString &idTo, const QString &folderName) +{ + if (idFrom.isEmpty() || idTo.isEmpty()) { + return; + } + + // TODO: max越界处理 + int max = m_folders.isEmpty() ? -1 : m_folders.lastKey(); + QString name = folderName; + if (name.isEmpty()) { + name = tr("New Folder %1").arg(m_folders.size() + 1); + } + + FavoritesFolder folder; + folder.id = ++max; + folder.name = name; + folder.apps.append(idFrom); + folder.apps.append(idTo); + + insertFolder(folder); + Q_EMIT folderAdded(folder.id, FavoritesConfig::instance().getOrderById(idTo)); + forceSync(); +} + +void FavoriteFolderHelper::removeAppFromFolder(const QString& appId) +{ + if (appId.isEmpty()) { + return; + } + + int folderId; + + { + QMutexLocker locker(&m_mutex); + + for (const auto &folder: m_folders) { + if (folder.apps.contains(appId)) { + folderId = folder.getId(); + } + } + + if (!m_folders.contains(folderId)) { + return; + } + FavoritesFolder &folder = m_folders[folderId]; + if (!folder.apps.contains(appId)) { + return; + } + folder.apps.removeOne(appId); + } + + if (m_folders[folderId].getApps().isEmpty()) { + deleteFolder(folderId); + } + + forceSync(); + Q_EMIT folderDataChanged(folderId, appId); +} + +bool FavoriteFolderHelper::deleteFolder(const int& folderId) +{ + Q_EMIT folderToBeDeleted(folderId, m_folders[folderId].getApps()); + + { + QMutexLocker locker(&m_mutex); + if (!m_folders.contains(folderId)) { + return false; + } + + if (!m_folders.remove(folderId)) { + return false; + } + } + + forceSync(); + EventTrack::instance()->sendDefaultEvent("delete_folder", "AppView"); + return true; +} + +void FavoriteFolderHelper::renameFolder(const int &folderId, const QString &folderName) +{ + { + QMutexLocker locker(&m_mutex); + if (!m_folders.contains(folderId)) { + return; + } + if (m_folders[folderId].name == folderName) { + return; + } + m_folders[folderId].name = folderName; + } + + Q_EMIT folderDataChanged(folderId, ""); + forceSync(); +} + +QList FavoriteFolderHelper::folderData() +{ + QMutexLocker locker(&m_mutex); + return m_folders.values(); +} + +bool FavoriteFolderHelper::getFolderFromId(const int &folderId, FavoritesFolder& folder) +{ + QMutexLocker locker(&m_mutex); + if (!m_folders.contains(folderId)) { + return false; + } + + const FavoritesFolder &tmp = m_folders[folderId]; + folder = tmp; + + return true; +} + +bool FavoriteFolderHelper::containApp(const QString &appId) +{ + QMutexLocker locker(&m_mutex); + return std::any_of(m_folders.constBegin(), m_folders.constEnd(), [appId] (const FavoritesFolder &folder) { + return folder.apps.contains(appId); + }); +} + +void FavoriteFolderHelper::forceSync() +{ + saveData(); +} + +void FavoriteFolderHelper::readData() +{ + QFile file(s_folderConfigFile); + if (!file.open(QFile::ReadOnly)) { + return; + } + + // 读取json数据 + QByteArray byteArray = file.readAll(); + file.close(); + + QJsonDocument jsonDocument(QJsonDocument::fromJson(byteArray)); + if (jsonDocument.isNull() || jsonDocument.isEmpty() || !jsonDocument.isArray()) { + qWarning() << "FavoriteFolderHelper: Incorrect configuration files are ignored."; + return; + } + + { + QMutexLocker locker(&m_mutex); + m_folders.clear(); + } + + // 遍历json数据节点 + QJsonArray jsonArray = jsonDocument.array(); + for (const auto &value : jsonArray) { + QJsonObject object = value.toObject(); + if (object.contains("name") && object.contains("id") && object.contains("apps")) { + FavoritesFolder folder; + folder.name = object.value(QLatin1String("name")).toString(); + folder.id = object.value(QLatin1String("id")).toInt(); + + QJsonArray apps = object.value(QLatin1String("apps")).toArray(); + for (const auto &app : apps) { + folder.apps.append(app.toString()); + } + + if (!folder.apps.isEmpty()) { + insertFolder(folder); + } + } + } +} + +void FavoriteFolderHelper::saveData() +{ + QFile file(s_folderConfigFile); + if (!file.open(QFile::WriteOnly)) { + return; + } + + QJsonDocument jsonDocument; + QJsonArray folderArray; + + { + QMutexLocker locker(&m_mutex); + for (const auto &folder : m_folders) { + QJsonObject object; + QJsonArray apps; + + for (const auto &app : folder.apps) { + apps.append(app); + } + + object.insert("name", folder.name); + object.insert("id", folder.id); + object.insert("apps", apps); + + folderArray.append(object); + } + } + + jsonDocument.setArray(folderArray); + + if (file.write(jsonDocument.toJson()) == -1) { + qWarning() << "Error saving configuration file."; + } + file.flush(); + file.close(); +} + +QStringList FavoriteFolderHelper::folderIcon(const FavoritesFolder &folder) +{ + // TODO: 使用绘图API生成图片 + QStringList icons; + DataEntity app; + + int count = qMin(folder.apps.count(), FOLDER_MAX_ICON_NUM); + for (int i = 0; i < count; ++i) { + if (AppDataManager::instance()->getApp(folder.apps.at(i), app)) { + icons.append(app.icon()); + } + } + + return icons; +} +} // UkuiMenu diff --git a/src/extension/favorite/favorite-folder-helper.h b/src/extension/favorite/favorite-folder-helper.h new file mode 100644 index 0000000..af4e236 --- /dev/null +++ b/src/extension/favorite/favorite-folder-helper.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2022, 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_FAVORITE_FOLDER_HELPER_H +#define UKUI_MENU_FAVORITE_FOLDER_HELPER_H + +#include +#include +#include +#include +#include +#include + +namespace UkuiMenu { + +#define FOLDER_MAX_ICON_NUM 16 + +class FavoriteFolderHelper; + +class FavoritesFolder +{ +Q_GADGET + Q_PROPERTY(int id READ getId WRITE setId) + Q_PROPERTY(QString name READ getName) + Q_PROPERTY(QStringList apps READ getApps) + friend class FavoriteFolderHelper; +public: + void setId(int folderId) {id = folderId;} + int getId() const { return id; } + QString getName() const { return name; } + QStringList getApps() const { return apps; } + +private: + int id; // 文件夹唯一Id,文件夹排序值 + QString name; // 名称 + QStringList apps; // 应用列表 +}; + +class FavoriteFolderHelper : public QObject +{ + Q_OBJECT +public: + static FavoriteFolderHelper *instance(); + static QStringList folderIcon(const FavoritesFolder &folder); + ~FavoriteFolderHelper() override; + + bool getFolderFromId(const int& folderId, FavoritesFolder& folder); + bool containApp(const QString& appId); + + QList folderData(); + + void addAppToFolder(const QString& appId, const int& folderId); + void addAppToNewFolder(const QString& appId, const QString& folderName); + void addAppsToNewFolder(const QString& idFrom, const QString& idTo, const QString& folderName); + void removeAppFromFolder(const QString& appId); + bool deleteFolder(const int& folderId); + void renameFolder(const int& folderId, const QString& folderName); + + void forceSync(); + +Q_SIGNALS: + void folderAdded(int folderId, const int& order); + void folderToBeDeleted(int folderId, const QStringList& apps); + void folderDataChanged(int folderId, const QString& app); + +private: + FavoriteFolderHelper(); + void readData(); + void saveData(); + void insertFolder(const FavoritesFolder& folder); + // TODO 配置文件监听 + +private: + QMutex m_mutex; + //TODO 指针 + QMap m_folders; + static QString s_folderConfigFile; +}; + +} // UkuiMenu + +#endif //UKUI_MENU_FAVORITE_FOLDER_HELPER_H diff --git a/src/extension/favorite/favorite-widget.cpp b/src/extension/favorite/favorite-widget.cpp index 98509e4..36c4166 100644 --- a/src/extension/favorite/favorite-widget.cpp +++ b/src/extension/favorite/favorite-widget.cpp @@ -17,6 +17,8 @@ */ #include "favorite-widget.h" +#include "app-favorite-model.h" +#include "favorites-model.h" namespace UkuiMenu { @@ -31,6 +33,10 @@ FavoriteWidget::FavoriteWidget(QObject *parent) : WidgetExtension(parent) m_metadata.insert(WidgetMetadata::Main, "qrc:///qml/extensions/FavoriteExtension.qml"); m_metadata.insert(WidgetMetadata::Type, WidgetMetadata::Widget); m_metadata.insert(WidgetMetadata::Flag, WidgetMetadata::Normal); + + FavoritesModel::instance().setSourceModel(&AppFavoritesModel::instance()); + FavoritesModel::instance().sort(0); + m_data.insert("favoriteAppsModel", QVariant::fromValue(&FavoritesModel::instance())); } int FavoriteWidget::index() const @@ -45,7 +51,7 @@ MetadataMap FavoriteWidget::metadata() const QVariantMap FavoriteWidget::data() { - return WidgetExtension::data(); + return m_data; } void FavoriteWidget::receive(const QVariantMap &data) diff --git a/src/extension/favorite/favorite-widget.h b/src/extension/favorite/favorite-widget.h index c5ff8ab..17d8497 100644 --- a/src/extension/favorite/favorite-widget.h +++ b/src/extension/favorite/favorite-widget.h @@ -36,6 +36,7 @@ public: private: MetadataMap m_metadata; + QVariantMap m_data; }; } // UkuiMenu diff --git a/src/extension/favorite/favorites-config.cpp b/src/extension/favorite/favorites-config.cpp new file mode 100644 index 0000000..fc65bc3 --- /dev/null +++ b/src/extension/favorite/favorites-config.cpp @@ -0,0 +1,162 @@ +// +// Created by qiqi on 23-12-27. +// +#include +#include +#include +#include +#include +#include "favorites-config.h" + +#define FOLDER_FILE_PATH ".config/ukui-menu/" +#define FOLDER_FILE_NAME "favorite.json" + +namespace UkuiMenu { + +QString FavoritesConfig::s_favoritesConfigFile = QDir::homePath() + "/" + FOLDER_FILE_PATH + FOLDER_FILE_NAME; + +FavoritesConfig &FavoritesConfig::instance() +{ + static FavoritesConfig favoritesConfig; + return favoritesConfig; +} + +FavoritesConfig::FavoritesConfig(QObject *parent) +{ + +} + +QJsonObject FavoritesConfig::getValue(const int &index) const +{ + if (index < 0 || index > arrayFromConfigFile().count()) { + return {}; + } + + return arrayFromConfigFile().at(index).toObject(); +} + +void FavoritesConfig::insertValue(const QString &id, const int &index) +{ + QJsonArray array = arrayFromConfigFile(); + if (indexOfObject(id, array) > -1) { + return; + } + + QJsonObject object; + object.insert("id", id); + array.insert(index, object); + + setArrayToConfigFile(array); +} + +void FavoritesConfig::removeValueById(const QString &id) +{ + QJsonArray array = arrayFromConfigFile(); + int index = indexOfObject(id, array); + + if (index > -1 && index < array.size()) { + array.removeAt(index); + } + + setArrayToConfigFile(array); +} + +void FavoritesConfig::forceSync() +{ + +} + +QString FavoritesConfig::configFile() const +{ + return s_favoritesConfigFile; +} + +void FavoritesConfig::initConfig(const QStringList &apps) +{ + QJsonArray favoritesArray; + + for (const auto &appId : apps) { + QJsonObject object; + object.insert("id", appId); + favoritesArray.append(object); + } + + setArrayToConfigFile(favoritesArray); +} + +void FavoritesConfig::setArrayToConfigFile(const QJsonArray &array) +{ + QDir dir; + QString folderConfigDir(QDir::homePath() + "/" + FOLDER_FILE_PATH); + if (!dir.exists(folderConfigDir)) { + if (!dir.mkdir(folderConfigDir)) { + qWarning() << "Unable to create profile favorites."; + return; + } + } + + QFile file(s_favoritesConfigFile); + file.open(QFile::WriteOnly); + + QJsonDocument jsonDocument; + jsonDocument.setArray(array); + + if (file.write(jsonDocument.toJson()) == -1) { + qWarning() << "Error saving configuration file."; + } + + file.flush(); + file.close(); + + Q_EMIT configChanged(); +} + +QJsonArray FavoritesConfig::arrayFromConfigFile() const +{ + QFile file(s_favoritesConfigFile); + if (!file.open(QFile::ReadOnly)) { + return {}; + } + + QJsonDocument jsonDocument(QJsonDocument::fromJson(file.readAll())); + file.close(); + + if (jsonDocument.isNull() || jsonDocument.isEmpty() || !jsonDocument.isArray()) { + qWarning() << "AppFolderHelper: Incorrect configuration files are ignored."; + return {}; + } + + return jsonDocument.array(); +} + +int FavoritesConfig::indexOfObject(const QString &id, const QJsonArray &array) +{ + if (id.isEmpty()) { + qWarning() << "id is unavailable!"; + return -1; + } + + for (int i = 0; i < array.size(); i++) { + if (array.at(i).toObject().contains("id")) { + if (array.at(i).toObject().value("id").toString() == id) { + return i; + } + } + } + + return -1; +} + +int FavoritesConfig::getOrderById(const QString &id) +{ + return indexOfObject(id, arrayFromConfigFile()); +} + +void FavoritesConfig::changeOrder(const int &indexFrom, const int &indexTo) +{ + QVariantList list = arrayFromConfigFile().toVariantList(); + list.move(indexFrom, indexTo); + setArrayToConfigFile(QJsonArray::fromVariantList(list)); +} + +} // UkuiMenu diff --git a/src/extension/favorite/favorites-config.h b/src/extension/favorite/favorites-config.h new file mode 100644 index 0000000..eae8a8f --- /dev/null +++ b/src/extension/favorite/favorites-config.h @@ -0,0 +1,45 @@ +// +// Created by qiqi on 23-12-27. +// + +#ifndef UKUI_MENU_FAVORITES_CONFIG_H +#define UKUI_MENU_FAVORITES_CONFIG_H + +#include +#include +#include + +namespace UkuiMenu { + +class FavoritesConfig : public QObject +{ + Q_OBJECT +public: + static FavoritesConfig &instance(); + + QJsonObject getValue(const int &index) const; + void insertValue(const QString &id, const int &index = 0); + void removeValueById(const QString &id); + int getOrderById(const QString &id); + void changeOrder(const int &indexFrom, const int &indexTo); + + void forceSync(); + QString configFile() const; + void initConfig(const QStringList &apps); + +Q_SIGNALS: + void configChanged(); + +private: + explicit FavoritesConfig(QObject *parent = nullptr); + void setArrayToConfigFile(const QJsonArray &array); + QJsonArray arrayFromConfigFile() const; + int indexOfObject(const QString &id, const QJsonArray &array); + +private: + static QString s_favoritesConfigFile; +}; + +} // UkuiMenu + +#endif //UKUI_MENU_FAVORITES_CONFIG_H diff --git a/src/extension/favorite/favorites-model.cpp b/src/extension/favorite/favorites-model.cpp new file mode 100644 index 0000000..d7426b7 --- /dev/null +++ b/src/extension/favorite/favorites-model.cpp @@ -0,0 +1,95 @@ +// +// Created by qiqi on 23-12-28. +// +#include + +#include "../context-menu-manager.h" +#include "favorites-model.h" +#include "app-favorite-model.h" +#include "favorite-folder-helper.h" + +namespace UkuiMenu { + +FavoritesModel &FavoritesModel::instance() +{ + static FavoritesModel favoritesModel; + return favoritesModel; +} + +FavoritesModel::FavoritesModel(QObject *parent) : QSortFilterProxyModel(parent) +{ + connect(&FavoritesConfig::instance(), &FavoritesConfig::configChanged, this, &FavoritesModel::invalidate); +} + +bool FavoritesModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const +{ + QVariant leftId = sourceModel()->data(source_left, DataEntity::Id); + QVariant rightId = sourceModel()->data(source_right, DataEntity::Id); + + int leftIndex = -1; + int rightIndex = -1; + for (int i = 0; i < sourceModel()->rowCount(); i++) { + QJsonObject object = FavoritesConfig::instance().getValue(i); + if (object.contains("id")) { + if (object.value(QLatin1String("id")).toString() == leftId) { + leftIndex = i; + } else if (object.value(QLatin1String("id")).toString() == rightId) { + rightIndex = i; + } + } + + if ((leftIndex != -1) && (rightIndex != -1)) { + return leftIndex < rightIndex; + } + } + + // 对应Id没有在配置文件中找到 + return true; +} + +void FavoritesModel::openMenu(const int &row) +{ + if (row < 0 || row >= sourceModel()->rowCount()) { + return; + } + + DataEntity data; + data.setId(sourceModel()->data(mapToSource(index(row, 0)), DataEntity::Id).toString()); + data.setFavorite(sourceModel()->data(mapToSource(index(row, 0)), DataEntity::Favorite).toInt()); + data.setType(sourceModel()->data(mapToSource(index(row, 0)), DataEntity::Type).value()); + + ContextMenuManager::instance()->showMenu(data, MenuInfo::Extension, "favorite"); +} + +void FavoritesModel::addAppToFavorites(const QString &id, const int &index) +{ + AppFavoritesModel::instance().changeAppState(id, index); +} + +void FavoritesModel::removeAppFromFavorites(const QString &id) +{ + AppFavoritesModel::instance().changeAppState(id, 0); +} + +void FavoritesModel::exchangedAppsOrder(const int &indexFrom, const int &indexTo) +{ + FavoritesConfig::instance().changeOrder(indexFrom, indexTo); +} + +void FavoritesModel::addAppsToNewFolder(const QString &idFrom, const QString &idTo) +{ + FavoriteFolderHelper::instance()->addAppsToNewFolder(idFrom, idTo, ""); +} + +void FavoritesModel::addAppToFolder(const QString &appId, const QString &folderId) +{ + if (folderId == "") { + FavoriteFolderHelper::instance()->addAppToNewFolder(appId, ""); + return; + } + + FavoriteFolderHelper::instance()->addAppToFolder(appId, folderId.toInt()); +} + + +} // UkuiMenu diff --git a/src/extension/favorite/favorites-model.h b/src/extension/favorite/favorites-model.h new file mode 100644 index 0000000..c14e421 --- /dev/null +++ b/src/extension/favorite/favorites-model.h @@ -0,0 +1,51 @@ +// +// Created by qiqi on 23-12-28. +// + +#ifndef UKUI_MENU_FAVORITES_MODEL_H +#define UKUI_MENU_FAVORITES_MODEL_H + +#include +#include "favorites-config.h" +#include "app-favorite-model.h" + +namespace UkuiMenu { + +class FavoritesModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + static FavoritesModel &instance(); + + Q_INVOKABLE void openMenu(const int &row); + Q_INVOKABLE void addAppToFavorites(const QString &id, const int &index = 1); + Q_INVOKABLE void removeAppFromFavorites(const QString &id); + /** + * 拖拽交换位置。 + * @param indexFrom + * @param indexTo + */ + Q_INVOKABLE void exchangedAppsOrder(const int &indexFrom, const int &indexTo); + /** + * 两个应用推拽合并为应用组。 + * @param idFrom + * @param idTo 拖拽至某一应用,并在该位置创建应用组 + */ + Q_INVOKABLE void addAppsToNewFolder(const QString &idFrom, const QString &idTo); + /** + * 添加应用到应用组,包括新建应用组。 + * @param appId + * @param folderId id为""时,新建应用组;id为数值时,添加至对应应用组 + */ + Q_INVOKABLE void addAppToFolder(const QString &appId, const QString& folderId); + +protected: + bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override; + +private: + explicit FavoritesModel(QObject *parent = nullptr); +}; + +} // UkuiMenu + +#endif //UKUI_MENU_FAVORITES_MODEL_H diff --git a/src/extension/menu/app-menu-plugin.cpp b/src/extension/menu/app-menu-plugin.cpp index 6cee589..f1bd012 100644 --- a/src/extension/menu/app-menu-plugin.cpp +++ b/src/extension/menu/app-menu-plugin.cpp @@ -71,7 +71,7 @@ QList AppContentMenu::actions(const DataEntity &data, QMenu *parent, case MenuInfo::Extension: case MenuInfo::FolderPage: case MenuInfo::FullScreen: - case MenuInfo::FullScreenFolder: + case MenuInfo::Folder: // 卸载 addToPanelAction(parent, appId, list); // 添加到任务栏 diff --git a/src/libappdata/app-database-interface.cpp b/src/libappdata/app-database-interface.cpp index c8bc35a..a8d0f26 100644 --- a/src/libappdata/app-database-interface.cpp +++ b/src/libappdata/app-database-interface.cpp @@ -38,6 +38,7 @@ class AppDatabaseWorkerPrivate : public QObject public: explicit AppDatabaseWorkerPrivate(AppDatabaseInterface *parent = nullptr); DataEntityVector getAllApps(); + bool getApp(const QString &appid, DataEntity &app); // 数据库操作函数 void setAppProperty(const QString &appid, const UkuiSearch::ApplicationPropertyMap &propertyMap); @@ -317,6 +318,17 @@ void AppDatabaseWorkerPrivate::setAppProperty(const QString &appid, const UkuiSe } } +bool AppDatabaseWorkerPrivate::getApp(const QString &appid, DataEntity &app) +{ + if (appid.isEmpty()) { + return false; + } + + const UkuiSearch::ApplicationPropertyMap appInfo = appDatabase->getInfo(appid, properties); + addInfoToApp(appInfo, app); + return true; +} + // ====== AppDatabaseInterface ====== // AppDatabaseInterface::AppDatabaseInterface(QObject *parent) : QObject(parent), d(new AppDatabaseWorkerPrivate(this)) { @@ -328,7 +340,7 @@ DataEntityVector AppDatabaseInterface::apps() const return d->getAllApps(); } -void AppDatabaseInterface::fixAppToTop(const QString &appid, int index) +void AppDatabaseInterface::fixAppToTop(const QString &appid, int index) const { if (index < 0) { index = 0; @@ -337,7 +349,7 @@ void AppDatabaseInterface::fixAppToTop(const QString &appid, int index) d->setAppProperty(appid, UkuiSearch::ApplicationProperty::Top, index); } -void AppDatabaseInterface::fixAppToFavorite(const QString &appid, int index) +void AppDatabaseInterface::fixAppToFavorite(const QString &appid, int index) const { if (index < 0) { index = 0; @@ -346,11 +358,16 @@ void AppDatabaseInterface::fixAppToFavorite(const QString &appid, int index) d->setAppProperty(appid, UkuiSearch::ApplicationProperty::Favorites, index); } -void AppDatabaseInterface::updateApLaunchedState(const QString &appid, bool state) +void AppDatabaseInterface::updateApLaunchedState(const QString &appid, bool state) const { d->setAppProperty(appid, UkuiSearch::ApplicationProperty::Launched, state); } +bool AppDatabaseInterface::getApp(const QString &appid, DataEntity &app) const +{ + return d->getApp(appid, app); +} + } // UkuiMenu #include "app-database-interface.moc" diff --git a/src/libappdata/app-database-interface.h b/src/libappdata/app-database-interface.h index c43cf0a..c6d5146 100644 --- a/src/libappdata/app-database-interface.h +++ b/src/libappdata/app-database-interface.h @@ -45,26 +45,32 @@ public: * @return */ DataEntityVector apps() const; + /** + * 从数据库获取单个应用 + * @param appid 应用id + * @param app 获取应用 + */ + bool getApp(const QString &appid, DataEntity &app) const; /** * 置顶应用 * @param appid 应用id * @param index 置顶后的位置,小于或等于0将会取消置顶 */ - void fixAppToTop(const QString &appid, int index); + void fixAppToTop(const QString &appid, int index) const; /** * 收藏应用 * @param appid 应用id * @param index 收藏后的位置,小于或等于0将会取消收藏 */ - void fixAppToFavorite(const QString &appid, int index); + void fixAppToFavorite(const QString &appid, int index) const; /** * 设置应用是否已经被启动过 * @param state 状态值,true已被启动,false未被启动 */ - void updateApLaunchedState(const QString &appid, bool state = true); + void updateApLaunchedState(const QString &appid, bool state = true) const; Q_SIGNALS: /** diff --git a/src/libappdata/basic-app-model.cpp b/src/libappdata/basic-app-model.cpp index 38cf2fa..ecd2ca9 100644 --- a/src/libappdata/basic-app-model.cpp +++ b/src/libappdata/basic-app-model.cpp @@ -136,7 +136,7 @@ void BasicAppModel::onAppUpdated(const QVector > QVector roles = pair.second; if (!roles.isEmpty()) { for (const auto &role : roles) { - app.setValue(static_cast(role), static_cast(role)); + app.setValue(static_cast(role), pair.first.getValue(static_cast(role))); } } else { app = pair.first; diff --git a/src/libappdata/basic-app-model.h b/src/libappdata/basic-app-model.h index 50f617f..511c898 100644 --- a/src/libappdata/basic-app-model.h +++ b/src/libappdata/basic-app-model.h @@ -41,6 +41,7 @@ public: */ const AppDatabaseInterface *databaseInterface() const; DataEntity appOfIndex(int row) const; + int indexOfApp(const QString &appid) const; int rowCount(const QModelIndex &parent) const override; int columnCount(const QModelIndex &parent) const override; @@ -55,7 +56,6 @@ private Q_SLOTS: private: explicit BasicAppModel(QObject *parent = nullptr); - int indexOfApp(const QString &appid) const; AppDatabaseInterface *m_databaseInterface {nullptr}; QVector m_apps; diff --git a/src/model/folder-model.cpp b/src/model/folder-model.cpp index 656d9f8..523676b 100644 --- a/src/model/folder-model.cpp +++ b/src/model/folder-model.cpp @@ -19,13 +19,15 @@ #include "folder-model.h" #include "app-folder-helper.h" #include "app-data-manager.h" +#include "favorite/favorite-folder-helper.h" +#include "context-menu-manager.h" namespace UkuiMenu { FolderModel::FolderModel(QObject *parent) : QAbstractListModel(parent) { - connect(AppFolderHelper::instance(), &AppFolderHelper::folderDataChanged, this, &FolderModel::loadFolderData); - connect(AppFolderHelper::instance(), &AppFolderHelper::folderDeleted, this, [this] (int id) { + connect(FavoriteFolderHelper::instance(), &FavoriteFolderHelper::folderDataChanged, this, &FolderModel::loadFolderData); + connect(FavoriteFolderHelper::instance(), &FavoriteFolderHelper::folderToBeDeleted, this, [this] (int id) { if (id == m_folderId) { beginResetModel(); m_folderId = -1; @@ -48,13 +50,13 @@ void FolderModel::setFolderId(const QString &folderId) void FolderModel::renameFolder(const QString &folderName) { - AppFolderHelper::instance()->renameFolder(m_folderId, folderName); + FavoriteFolderHelper::instance()->renameFolder(m_folderId, folderName); } void FolderModel::loadFolderData(int id) { - Folder folder; - if (!AppFolderHelper::instance()->searchFolder(id, folder)) { + FavoritesFolder folder; + if (!FavoriteFolderHelper::instance()->getFolderFromId(id, folder)) { return; }