diff --git a/CMakeLists.txt b/CMakeLists.txt index 425b2ad..1ec3410 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,14 +90,15 @@ set(SOURCE_FILES src/appdata/app-icon-provider.cpp src/appdata/app-icon-provider.h src/appdata/data-provider-manager.cpp src/appdata/data-provider-manager.h src/appdata/plugin/all-app-data-provider.cpp src/appdata/plugin/all-app-data-provider.h + src/appdata/plugin/app-search-plugin.cpp src/appdata/plugin/app-search-plugin.h src/extension/menu-extension-iface.h src/extension/menu-extension.cpp src/extension/menu-extension.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 + src/extension/extensions/favorite-extension.cpp src/extension/extensions/favorite-extension.h src/utils/app-page-header-utils.cpp src/utils/app-page-header-utils.h src/utils/power-button.cpp src/utils/power-button.h src/utils/app-manager.cpp src/utils/app-manager.h - src/extension/extensions/favorite-extension.cpp src/extension/extensions/favorite-extension.h ) # qrc文件 diff --git a/src/appdata/data-provider-manager.cpp b/src/appdata/data-provider-manager.cpp index a121060..4f8ead8 100644 --- a/src/appdata/data-provider-manager.cpp +++ b/src/appdata/data-provider-manager.cpp @@ -18,6 +18,7 @@ #include "data-provider-manager.h" #include "plugin/all-app-data-provider.h" +#include "plugin/app-search-plugin.h" namespace UkuiMenu { @@ -33,6 +34,7 @@ DataProviderManager *DataProviderManager::instance() DataProviderManager::DataProviderManager() { + qRegisterMetaType("DataUpdateMode::Mode"); m_worker.start(); initProviders(); } @@ -42,8 +44,12 @@ void DataProviderManager::initProviders() auto *allProvider = new AllAppDataProvider; registerProvider(allProvider); + auto *search = new AppSearchPlugin; + registerProvider(search); + activateProvider(allProvider->id()); allProvider->moveToThread(&m_worker); + search->moveToThread(&m_worker); } void DataProviderManager::registerProvider(DataProviderPluginIFace *provider) @@ -58,13 +64,14 @@ void DataProviderManager::registerProvider(DataProviderPluginIFace *provider) } m_providers.insert(provider->id(), provider); - connect(provider, &AllAppDataProvider::dataChanged, this, [this, provider](const QVector &data) { + connect(provider, &AllAppDataProvider::dataChanged, this, + [this, provider](const QVector &data, DataUpdateMode::Mode mode, quint32 index) { //qDebug() << "==DataProviderManager dataChanged:" << provider->name() << QThread::currentThreadId(); if (m_activatedPlugin != provider->id()) { return; } - Q_EMIT dataChanged(data); + Q_EMIT dataChanged(data, mode, index); }); } diff --git a/src/appdata/data-provider-manager.h b/src/appdata/data-provider-manager.h index f0b6de6..e05ac3c 100644 --- a/src/appdata/data-provider-manager.h +++ b/src/appdata/data-provider-manager.h @@ -55,7 +55,7 @@ public: Q_SIGNALS: void pluginChanged(const QString &id, PluginGroup::Group group); - void dataChanged(QVector data); + void dataChanged(QVector data, DataUpdateMode::Mode mode, quint32 index); private: DataProviderManager(); diff --git a/src/appdata/data-provider-plugin-iface.h b/src/appdata/data-provider-plugin-iface.h index 1a1444c..5193e34 100644 --- a/src/appdata/data-provider-plugin-iface.h +++ b/src/appdata/data-provider-plugin-iface.h @@ -41,6 +41,19 @@ public: Q_ENUM(Group) }; +class DataUpdateMode +{ + Q_GADGET +public: + enum Mode { + Reset = 0, + Append, + Prepend, + Insert + }; + Q_ENUM(Mode) +}; + class DataProviderPluginIFace : public QObject { Q_OBJECT @@ -69,9 +82,11 @@ Q_SIGNALS: /** * 数据变化 */ - void dataChanged(QVector newData); + void dataChanged(QVector data, DataUpdateMode::Mode mode = DataUpdateMode::Reset, quint32 index = 0); }; } // UkuiMenu +//Q_DECLARE_METATYPE(UkuiMenu::DataUpdateMode::Mode) + #endif //UKUI_MENU_DATA_PROVIDER_PLUGIN_IFACE_H diff --git a/src/appdata/plugin/app-search-plugin.cpp b/src/appdata/plugin/app-search-plugin.cpp new file mode 100644 index 0000000..62f27d8 --- /dev/null +++ b/src/appdata/plugin/app-search-plugin.cpp @@ -0,0 +1,183 @@ +/* + * 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-search-plugin.h" + +#include + +namespace UkuiMenu { + +class AppSearchPluginPrivate : public QThread +{ + Q_OBJECT +public: + AppSearchPluginPrivate(); + +Q_SIGNALS: + void searchedOne(DataEntity app); + +public Q_SLOTS: + void startSearch(QString &keyword); + void stopSearch(); + +protected: + void run() override; + +private: + size_t m_searchId{0}; + QTimer *m_timer{nullptr}; + UkuiSearch::UkuiSearchTask *m_appSearchTask{nullptr}; + UkuiSearch::DataQueue *m_dataQueue{nullptr}; +}; + +AppSearchPluginPrivate::AppSearchPluginPrivate() : QThread(nullptr) +{ + m_appSearchTask = new UkuiSearch::UkuiSearchTask(this); + m_dataQueue = m_appSearchTask->init(); + + m_appSearchTask->initSearchPlugin(UkuiSearch::SearchType::Application); + m_appSearchTask->setSearchOnlineApps(false); + m_appSearchTask->setResultDataType(UkuiSearch::SearchType::Application, + UkuiSearch::ApplicationDesktopPath | UkuiSearch::ApplicationLocalName | UkuiSearch::ApplicationIconName); + + m_timer = new QTimer; + m_timer->setInterval(3000); + m_timer->moveToThread(this); +} + +void AppSearchPluginPrivate::startSearch(QString &keyword) +{ + if (!this->isRunning()) { + this->start(); + } + + m_appSearchTask->clearKeyWords(); + m_appSearchTask->addKeyword(keyword); + m_searchId = m_appSearchTask->startSearch(UkuiSearch::SearchType::Application); +} + +void AppSearchPluginPrivate::stopSearch() +{ + m_appSearchTask->stop(); + this->requestInterruption(); +} + +void AppSearchPluginPrivate::run() +{ + while (!isInterruptionRequested()) { + UkuiSearch::ResultItem result = m_dataQueue->tryDequeue(); + if(result.getSearchId() == 0 && result.getItemKey().isEmpty() && result.getExtral().isEmpty()) { + if(!m_timer->isActive()) { + // 超时退出 + m_timer->start(); + } + msleep(100); + } else { + m_timer->stop(); + if (result.getSearchId() == m_searchId) { + QVariantList list = result.getExtral(); + DataEntity app; + app.setType(DataType::Normal); + app.setId(list.at(0).toString()); + app.setName(list.at(1).toString()); + app.setIcon("image://appicon/" + list.at(2).toString()); + + Q_EMIT this->searchedOne(app); + } + } + + if(m_timer->isActive() && m_timer->remainingTime() < 0.01 && m_dataQueue->isEmpty()) { + this->requestInterruption(); + } + } +} + +// ========AppSearchPlugin======== // +AppSearchPlugin::AppSearchPlugin() +{ + m_searchPluginPrivate = new AppSearchPluginPrivate; + connect(m_searchPluginPrivate, &AppSearchPluginPrivate::searchedOne, this, &AppSearchPlugin::onSearchedOne); +} + +int AppSearchPlugin::index() +{ + return 0; +} + +QString AppSearchPlugin::id() +{ + return "search"; +} + +QString AppSearchPlugin::name() +{ + return tr("Search"); +} + +QString AppSearchPlugin::icon() +{ + return "image://appicon/search-symbolic"; +} + +QString AppSearchPlugin::title() +{ + return ""; +} + +PluginGroup::Group AppSearchPlugin::group() +{ + return PluginGroup::Button; +} + +QVector AppSearchPlugin::data() +{ + return {}; +} + +void AppSearchPlugin::forceUpdate() +{ + +} + +void AppSearchPlugin::forceUpdate(QString &key) +{ +// qDebug() << "==AppSearchPlugin key:" << key; + Q_EMIT dataChanged({}); + if (key.isEmpty()) { + return; + } + + m_searchPluginPrivate->startSearch(key); +} + +void AppSearchPlugin::onSearchedOne(const DataEntity &app) +{ + Q_EMIT dataChanged({1, app}, DataUpdateMode::Append); +} + +AppSearchPlugin::~AppSearchPlugin() +{ + m_searchPluginPrivate->stopSearch(); + m_searchPluginPrivate->quit(); + m_searchPluginPrivate->wait(); + m_searchPluginPrivate->deleteLater(); +} + +} // UkuiMenu + +#include "app-search-plugin.moc" diff --git a/src/appdata/plugin/app-search-plugin.h b/src/appdata/plugin/app-search-plugin.h new file mode 100644 index 0000000..3250d9c --- /dev/null +++ b/src/appdata/plugin/app-search-plugin.h @@ -0,0 +1,54 @@ +/* + * 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_SEARCH_PLUGIN_H +#define UKUI_MENU_APP_SEARCH_PLUGIN_H + +#include "data-provider-plugin-iface.h" + +namespace UkuiMenu { + +class AppSearchPluginPrivate; + +class AppSearchPlugin : public DataProviderPluginIFace +{ + Q_OBJECT +public: + AppSearchPlugin(); + ~AppSearchPlugin() override; + + int index() override; + QString id() override; + QString name() override; + QString icon() override; + QString title() override; + PluginGroup::Group group() override; + QVector data() override; + void forceUpdate() override; + void forceUpdate(QString &key) override; + +private Q_SLOTS: + void onSearchedOne(const DataEntity &app); + +private: + AppSearchPluginPrivate *m_searchPluginPrivate{nullptr}; +}; + +} // UkuiMenu + +#endif //UKUI_MENU_APP_SEARCH_PLUGIN_H diff --git a/src/model/model.cpp b/src/model/model.cpp index fb22bd2..f243c55 100644 --- a/src/model/model.cpp +++ b/src/model/model.cpp @@ -18,7 +18,6 @@ #include "model.h" #include "app-manager.h" -#include "data-provider-manager.h" #include #include @@ -101,14 +100,69 @@ void AppModel::appClicked(const int &index) void AppModel::reloadPluginData() { - onPluginDataChanged(DataProviderManager::instance()->data()); + QVector data = DataProviderManager::instance()->data(); + resetModel(data); } -void AppModel::onPluginDataChanged(QVector data) +void AppModel::onPluginDataChanged(QVector data, DataUpdateMode::Mode mode, quint32 index) +{ + switch (mode) { + default: + case DataUpdateMode::Reset: { + resetModel(data); + break; + } + case DataUpdateMode::Append: { + appendData(data); + break; + } + case DataUpdateMode::Prepend: { + prependData(data); + break; + } + case DataUpdateMode::Insert: { + insertData(data, static_cast(index)); + break; + } + } +} + +void AppModel::resetModel(QVector &data) { Q_EMIT beginResetModel(); m_apps.swap(data); Q_EMIT endResetModel(); } +void AppModel::appendData(QVector &data) +{ + Q_EMIT beginInsertRows(QModelIndex(), m_apps.size(), (m_apps.size() + data.size() - 1)); + m_apps.append(data); + Q_EMIT endInsertRows(); +} + +void AppModel::prependData(QVector &data) +{ + Q_EMIT beginInsertRows(QModelIndex(), 0, data.size() - 1); + data.append(m_apps); + m_apps.swap(data); + Q_EMIT endInsertRows(); +} + +void AppModel::insertData(QVector &data, int index) +{ + if (index < 0 || (!m_apps.isEmpty() && index >= m_apps.size())) { + return; + } + + Q_EMIT beginInsertRows(QModelIndex(), index, index + data.size() - 1); + + for (const auto &item : data) { + m_apps.insert(index, item); + ++index; + } + + Q_EMIT endInsertRows(); +} + } // UkuiMenu diff --git a/src/model/model.h b/src/model/model.h index 60fcb4e..0dae383 100644 --- a/src/model/model.h +++ b/src/model/model.h @@ -23,6 +23,7 @@ #include #include "commons.h" +#include "data-provider-manager.h" namespace UkuiMenu { @@ -40,9 +41,15 @@ public: Q_INVOKABLE void appClicked(const int &index); private Q_SLOTS: - void onPluginDataChanged(QVector data); + void onPluginDataChanged(QVector data, DataUpdateMode::Mode mode, quint32 index); void reloadPluginData(); +private: + void resetModel(QVector &data); + void appendData(QVector &data); + void prependData(QVector &data); + void insertData(QVector &data, int index); + private: QVector m_apps; };