feat: 添加应用列表插件接口,搜索插件和分类插件
This commit is contained in:
parent
f3e9858b88
commit
1e34114387
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024, 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Authors: hxf <hewenfei@kylinos.cn>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "app-category-plugin.h"
|
||||||
|
#include "combined-list-model.h"
|
||||||
|
#include "app-category-model.h"
|
||||||
|
#include "recently-installed-model.h"
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
namespace UkuiMenu {
|
||||||
|
|
||||||
|
AppCategoryPlugin::AppCategoryPlugin(QObject *parent) : AppListPluginInterface(parent)
|
||||||
|
, m_dataModel(new CombinedListModel(this))
|
||||||
|
{
|
||||||
|
auto categoryModel = new AppCategoryModel(this);
|
||||||
|
auto recentlyModel = new RecentlyInstalledModel(this);
|
||||||
|
|
||||||
|
m_dataModel->insertSubModel(recentlyModel);
|
||||||
|
m_dataModel->insertSubModel(categoryModel);
|
||||||
|
|
||||||
|
auto categoryAction = new QAction(QIcon::fromTheme("applications-utilities-symbolic"), tr("Category"), this);
|
||||||
|
auto firstLatterAction = new QAction(QIcon::fromTheme("ukui-capslock-symbolic"), tr("Letter Sort"), this);
|
||||||
|
|
||||||
|
categoryAction->setCheckable(true);
|
||||||
|
firstLatterAction->setCheckable(true);
|
||||||
|
|
||||||
|
connect(categoryAction, &QAction::triggered, this, [=] {
|
||||||
|
categoryModel->setMode(AppCategoryModel::Category);
|
||||||
|
categoryAction->setChecked(true);
|
||||||
|
firstLatterAction->setChecked(false);
|
||||||
|
setTitle(categoryAction->text());
|
||||||
|
});
|
||||||
|
connect(firstLatterAction, &QAction::triggered, this, [=] {
|
||||||
|
categoryModel->setMode(AppCategoryModel::FirstLatter);
|
||||||
|
categoryAction->setChecked(false);
|
||||||
|
firstLatterAction->setChecked(true);
|
||||||
|
setTitle(firstLatterAction->text());
|
||||||
|
});
|
||||||
|
|
||||||
|
m_actions.append(categoryAction);
|
||||||
|
m_actions.append(firstLatterAction);
|
||||||
|
|
||||||
|
categoryAction->setChecked(true);
|
||||||
|
setTitle(categoryAction->text());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AppCategoryPlugin::name()
|
||||||
|
{
|
||||||
|
return QStringLiteral("AppCategoryPlugin");
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QAction *> AppCategoryPlugin::actions()
|
||||||
|
{
|
||||||
|
return m_actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
QAbstractItemModel *AppCategoryPlugin::dataModel()
|
||||||
|
{
|
||||||
|
return m_dataModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
AppListPluginGroup::Group AppCategoryPlugin::group()
|
||||||
|
{
|
||||||
|
return AppListPluginGroup::Display;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AppCategoryPlugin::title()
|
||||||
|
{
|
||||||
|
return m_title;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppCategoryPlugin::setTitle(const QString &title)
|
||||||
|
{
|
||||||
|
if (title == m_title) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_title = title;
|
||||||
|
Q_EMIT titleChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // UkuiMenu
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024, 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Authors: hxf <hewenfei@kylinos.cn>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UKUI_MENU_APP_CATEGORY_PLUGIN_H
|
||||||
|
#define UKUI_MENU_APP_CATEGORY_PLUGIN_H
|
||||||
|
|
||||||
|
#include "app-list-plugin.h"
|
||||||
|
|
||||||
|
namespace UkuiMenu {
|
||||||
|
|
||||||
|
class CombinedListModel;
|
||||||
|
|
||||||
|
class AppCategoryPlugin : public AppListPluginInterface
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit AppCategoryPlugin(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
AppListPluginGroup::Group group() override;
|
||||||
|
QString name() override;
|
||||||
|
QString title() override;
|
||||||
|
QList<QAction *> actions() override;
|
||||||
|
QAbstractItemModel *dataModel() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setTitle(const QString &title);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_title;
|
||||||
|
QList<QAction *> m_actions;
|
||||||
|
CombinedListModel *m_dataModel {nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // UkuiMenu
|
||||||
|
|
||||||
|
#endif //UKUI_MENU_APP_CATEGORY_PLUGIN_H
|
|
@ -0,0 +1,154 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024, 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Authors: hxf <hewenfei@kylinos.cn>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "app-list-model.h"
|
||||||
|
#include "data-entity.h"
|
||||||
|
#include "context-menu-manager.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
namespace UkuiMenu {
|
||||||
|
|
||||||
|
AppListHeader::AppListHeader(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AppListHeader::title() const
|
||||||
|
{
|
||||||
|
return m_title;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppListHeader::setTitle(const QString &title)
|
||||||
|
{
|
||||||
|
if (title == m_title) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_title = title;
|
||||||
|
Q_EMIT titleChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QAction*> AppListHeader::actions() const
|
||||||
|
{
|
||||||
|
return m_actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppListHeader::addAction(QAction *action)
|
||||||
|
{
|
||||||
|
if (m_actions.indexOf(action) >= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_actions.append(action);
|
||||||
|
Q_EMIT actionsChanged();
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AppListHeader::visible() const
|
||||||
|
{
|
||||||
|
return m_visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppListHeader::setVisible(bool visible)
|
||||||
|
{
|
||||||
|
if (m_visible == visible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_visible = visible;
|
||||||
|
Q_EMIT visibleChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppListHeader::removeAction(QAction *action)
|
||||||
|
{
|
||||||
|
if (m_actions.removeOne(action)) {
|
||||||
|
Q_EMIT actionsChanged();
|
||||||
|
setVisible(!m_actions.isEmpty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppListHeader::removeAllAction()
|
||||||
|
{
|
||||||
|
m_actions.clear();
|
||||||
|
Q_EMIT actionsChanged();
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====== //
|
||||||
|
AppListModel::AppListModel(QObject *parent) : QSortFilterProxyModel(parent), m_header(new AppListHeader(this))
|
||||||
|
{
|
||||||
|
qRegisterMetaType<UkuiMenu::AppListModel*>();
|
||||||
|
qRegisterMetaType<UkuiMenu::AppListHeader*>();
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> AppListModel::roleNames() const
|
||||||
|
{
|
||||||
|
return DataEntity::AppRoleNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
AppListHeader *AppListModel::getHeader() const
|
||||||
|
{
|
||||||
|
return m_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppListModel::installPlugin(AppListPluginInterface *plugin)
|
||||||
|
{
|
||||||
|
if (!plugin || m_plugin == plugin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unInstallPlugin();
|
||||||
|
|
||||||
|
m_plugin = plugin;
|
||||||
|
QSortFilterProxyModel::setSourceModel(plugin->dataModel());
|
||||||
|
|
||||||
|
for (const auto &action : plugin->actions()) {
|
||||||
|
m_header->addAction(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_header->setTitle(plugin->title());
|
||||||
|
connect(m_plugin, &AppListPluginInterface::titleChanged, this, [this, plugin] {
|
||||||
|
m_header->setTitle(plugin->title());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppListModel::unInstallPlugin()
|
||||||
|
{
|
||||||
|
if (!m_plugin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_header->setTitle("");
|
||||||
|
m_header->removeAllAction();
|
||||||
|
QSortFilterProxyModel::setSourceModel(nullptr);
|
||||||
|
disconnect(m_plugin, nullptr, this, nullptr);
|
||||||
|
m_plugin = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppListModel::openMenu(const int &index, MenuInfo::Location location) const
|
||||||
|
{
|
||||||
|
QModelIndex idx = AppListModel::index(index, 0);
|
||||||
|
if (checkIndex(idx, CheckIndexOption::IndexIsValid)) {
|
||||||
|
ContextMenuManager::instance()->showMenu(idx.data(DataEntity::Entity).value<DataEntity>(), location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // UkuiMenu
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024, 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Authors: hxf <hewenfei@kylinos.cn>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UKUI_MENU_APP_LIST_MODEL_H
|
||||||
|
#define UKUI_MENU_APP_LIST_MODEL_H
|
||||||
|
|
||||||
|
#include "app-list-plugin.h"
|
||||||
|
#include "context-menu-extension.h"
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
|
namespace UkuiMenu {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class AppListHeader
|
||||||
|
*
|
||||||
|
* 应用列表顶部功能区域
|
||||||
|
* 显示当前插件的操作选项,如果插件的action为空,那么不显示header.
|
||||||
|
*/
|
||||||
|
class AppListHeader : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(bool visible READ visible NOTIFY visibleChanged)
|
||||||
|
Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
|
||||||
|
Q_PROPERTY(QList<QAction*> actions READ actions NOTIFY actionsChanged)
|
||||||
|
friend class AppListModel;
|
||||||
|
public:
|
||||||
|
explicit AppListHeader(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
bool visible() const;
|
||||||
|
void setVisible(bool visible);
|
||||||
|
|
||||||
|
QString title() const;
|
||||||
|
void setTitle(const QString &title);
|
||||||
|
|
||||||
|
QList<QAction*> actions() const;
|
||||||
|
void addAction(QAction *actions);
|
||||||
|
void removeAction(QAction *actions);
|
||||||
|
void removeAllAction();
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void titleChanged();
|
||||||
|
void actionsChanged();
|
||||||
|
void visibleChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_visible {false};
|
||||||
|
QString m_title;
|
||||||
|
QList<QAction*> m_actions;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AppListModel : public QSortFilterProxyModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(UkuiMenu::AppListHeader *header READ getHeader NOTIFY headerChanged)
|
||||||
|
public:
|
||||||
|
explicit AppListModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 覆盖全部roles,子model必须返回相同的roles
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
|
AppListHeader *getHeader() const;
|
||||||
|
|
||||||
|
void installPlugin(AppListPluginInterface *plugin);
|
||||||
|
// reset
|
||||||
|
void unInstallPlugin();
|
||||||
|
|
||||||
|
Q_INVOKABLE void openMenu(const int &index, MenuInfo::Location location) const;
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void headerChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
AppListHeader *m_header {nullptr};
|
||||||
|
AppListPluginInterface *m_plugin {nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // UkuiMenu
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(UkuiMenu::AppListModel*)
|
||||||
|
Q_DECLARE_METATYPE(UkuiMenu::AppListHeader*)
|
||||||
|
|
||||||
|
#endif //UKUI_MENU_APP_LIST_MODEL_H
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024, 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Authors: hxf <hewenfei@kylinos.cn>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "app-list-plugin.h"
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
namespace UkuiMenu {
|
||||||
|
|
||||||
|
// ====== AppListPluginInterface ====== //
|
||||||
|
AppListPluginInterface::AppListPluginInterface(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppListPluginInterface::search(const QString &keyword)
|
||||||
|
{
|
||||||
|
Q_UNUSED(keyword)
|
||||||
|
}
|
||||||
|
|
||||||
|
} // UkuiMenu
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024, 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Authors: hxf <hewenfei@kylinos.cn>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UKUI_MENU_APP_LIST_PLUGIN_H
|
||||||
|
#define UKUI_MENU_APP_LIST_PLUGIN_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
class QAction;
|
||||||
|
class QAbstractItemModel;
|
||||||
|
|
||||||
|
namespace UkuiMenu {
|
||||||
|
|
||||||
|
class AppListPluginGroup
|
||||||
|
{
|
||||||
|
Q_GADGET
|
||||||
|
public:
|
||||||
|
enum Group {
|
||||||
|
Display, /**> 应用展示模式 */
|
||||||
|
Search /**> 应用搜索模式 */
|
||||||
|
};
|
||||||
|
Q_ENUM(Group)
|
||||||
|
};
|
||||||
|
|
||||||
|
class AppListPluginInterface : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit AppListPluginInterface(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
virtual AppListPluginGroup::Group group() = 0;
|
||||||
|
virtual QString name() = 0;
|
||||||
|
virtual QString title() = 0;
|
||||||
|
virtual QList<QAction*> actions() = 0;
|
||||||
|
virtual QAbstractItemModel *dataModel() = 0;
|
||||||
|
virtual void search(const QString &keyword);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void titleChanged();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // UkuiMenu
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(UkuiMenu::AppListPluginGroup::Group)
|
||||||
|
|
||||||
|
#endif //UKUI_MENU_APP_LIST_PLUGIN_H
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024, 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Authors: hxf <hewenfei@kylinos.cn>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "app-page-backend.h"
|
||||||
|
|
||||||
|
#include "app-list-model.h"
|
||||||
|
#include "app-category-plugin.h"
|
||||||
|
#include "app-search-plugin.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
namespace UkuiMenu {
|
||||||
|
|
||||||
|
AppPageBackend::AppPageBackend(QObject *parent) : QObject(parent), m_appModel(new AppListModel(this))
|
||||||
|
{
|
||||||
|
auto searchPlugin = new AppSearchPlugin(this);
|
||||||
|
auto categoryPlugin = new AppCategoryPlugin(this);
|
||||||
|
|
||||||
|
m_plugins.insert(searchPlugin->group(), searchPlugin);
|
||||||
|
m_plugins.insert(categoryPlugin->group(), categoryPlugin);
|
||||||
|
|
||||||
|
switchGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
AppListModel *AppPageBackend::appModel() const
|
||||||
|
{
|
||||||
|
return m_appModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppPageBackend::startSearch(const QString &keyword)
|
||||||
|
{
|
||||||
|
if (m_group != AppListPluginGroup::Search) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto plugin = m_plugins.value(m_group, nullptr);
|
||||||
|
if (plugin) {
|
||||||
|
plugin->search(keyword);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AppListPluginGroup::Group AppPageBackend::group() const
|
||||||
|
{
|
||||||
|
return AppListPluginGroup::Display;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppPageBackend::setGroup(AppListPluginGroup::Group group)
|
||||||
|
{
|
||||||
|
if (m_group == group) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_group = group;
|
||||||
|
switchGroup();
|
||||||
|
Q_EMIT groupChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppPageBackend::switchGroup()
|
||||||
|
{
|
||||||
|
const auto plugin = m_plugins.value(m_group, nullptr);
|
||||||
|
if (plugin) {
|
||||||
|
m_appModel->installPlugin(plugin);
|
||||||
|
} else {
|
||||||
|
m_appModel->unInstallPlugin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // UkuiMenu
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024, 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Authors: hxf <hewenfei@kylinos.cn>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UKUI_MENU_APP_PAGE_BACKEND_H
|
||||||
|
#define UKUI_MENU_APP_PAGE_BACKEND_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QAction>
|
||||||
|
class QAbstractItemModel;
|
||||||
|
class QSortFilterProxyModel;
|
||||||
|
|
||||||
|
#include "app-list-plugin.h"
|
||||||
|
|
||||||
|
namespace UkuiMenu {
|
||||||
|
|
||||||
|
class AppListModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 此类管理开始菜单的主体功能和接口
|
||||||
|
*
|
||||||
|
* 提供:应用搜索,应用分类模式的切换功能
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* AppPage
|
||||||
|
* |
|
||||||
|
* AppListHeader
|
||||||
|
* AppList
|
||||||
|
* / \
|
||||||
|
* Search Display
|
||||||
|
* | \
|
||||||
|
* (Model Title Actions) (Model Title Actions)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class AppPageBackend : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QAbstractItemModel *appModel READ appModel NOTIFY appModelChanged)
|
||||||
|
Q_PROPERTY(UkuiMenu::AppListPluginGroup::Group group READ group WRITE setGroup NOTIFY groupChanged)
|
||||||
|
public:
|
||||||
|
explicit AppPageBackend(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
// 开始菜单主要功能,显示应用列表
|
||||||
|
AppListModel *appModel() const;
|
||||||
|
Q_INVOKABLE void startSearch(const QString &keyword);
|
||||||
|
|
||||||
|
AppListPluginGroup::Group group() const;
|
||||||
|
void setGroup(AppListPluginGroup::Group group);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void appModelChanged();
|
||||||
|
void groupChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void switchGroup();
|
||||||
|
|
||||||
|
private:
|
||||||
|
AppListPluginGroup::Group m_group {AppListPluginGroup::Display};
|
||||||
|
AppListModel *m_appModel {nullptr};
|
||||||
|
QMap<AppListPluginGroup::Group, AppListPluginInterface*> m_plugins;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // UkuiMenu
|
||||||
|
|
||||||
|
#endif //UKUI_MENU_APP_PAGE_BACKEND_H
|
|
@ -0,0 +1,228 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024, 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Authors: hxf <hewenfei@kylinos.cn>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "app-search-plugin.h"
|
||||||
|
#include "data-entity.h"
|
||||||
|
|
||||||
|
#include <UkuiSearchTask>
|
||||||
|
#include <QThread>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
namespace UkuiMenu {
|
||||||
|
|
||||||
|
// ====== AppSearchPluginPrivate ======
|
||||||
|
class AppSearchPluginPrivate : public QThread
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit AppSearchPluginPrivate(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void searchedOne(DataEntity app);
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void startSearch(const 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<UkuiSearch::ResultItem> *m_dataQueue{nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
|
AppSearchPluginPrivate::AppSearchPluginPrivate(QObject *parent) : QThread(parent), m_appSearchTask(new UkuiSearch::UkuiSearchTask(this))
|
||||||
|
{
|
||||||
|
m_dataQueue = m_appSearchTask->init();
|
||||||
|
|
||||||
|
m_appSearchTask->initSearchPlugin(UkuiSearch::SearchProperty::SearchType::Application);
|
||||||
|
m_appSearchTask->setSearchOnlineApps(false);
|
||||||
|
|
||||||
|
UkuiSearch::SearchResultProperties searchResultProperties;
|
||||||
|
searchResultProperties << UkuiSearch::SearchProperty::SearchResultProperty::ApplicationDesktopPath
|
||||||
|
<< UkuiSearch::SearchProperty::SearchResultProperty::ApplicationLocalName
|
||||||
|
<< UkuiSearch::SearchProperty::SearchResultProperty::ApplicationIconName;
|
||||||
|
m_appSearchTask->setResultProperties(UkuiSearch::SearchProperty::SearchType::Application, searchResultProperties);
|
||||||
|
|
||||||
|
m_timer = new QTimer;
|
||||||
|
m_timer->setInterval(3000);
|
||||||
|
m_timer->moveToThread(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppSearchPluginPrivate::startSearch(const QString &keyword)
|
||||||
|
{
|
||||||
|
if (!this->isRunning()) {
|
||||||
|
this->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_appSearchTask->clearKeyWords();
|
||||||
|
m_appSearchTask->addKeyword(keyword);
|
||||||
|
m_searchId = m_appSearchTask->startSearch(UkuiSearch::SearchProperty::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.getAllValue().isEmpty()) {
|
||||||
|
if(!m_timer->isActive()) {
|
||||||
|
// 超时退出
|
||||||
|
m_timer->start();
|
||||||
|
}
|
||||||
|
msleep(100);
|
||||||
|
} else {
|
||||||
|
m_timer->stop();
|
||||||
|
if (result.getSearchId() == m_searchId) {
|
||||||
|
DataEntity app;
|
||||||
|
app.setType(DataType::Normal);
|
||||||
|
app.setId(result.getValue(UkuiSearch::SearchProperty::ApplicationDesktopPath).toString());
|
||||||
|
app.setName(result.getValue(UkuiSearch::SearchProperty::ApplicationLocalName).toString());
|
||||||
|
app.setIcon("image://appicon/" + result.getValue(UkuiSearch::SearchProperty::ApplicationIconName).toString());
|
||||||
|
|
||||||
|
Q_EMIT this->searchedOne(app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_timer->isActive() && m_timer->remainingTime() < 0.01 && m_dataQueue->isEmpty()) {
|
||||||
|
this->requestInterruption();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====== AppSearchModel ====== //
|
||||||
|
class AppSearchModel : public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit AppSearchModel(QObject *parent = nullptr);
|
||||||
|
int rowCount(const QModelIndex &parent) const override;
|
||||||
|
int columnCount(const QModelIndex &parent) const override;
|
||||||
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
|
||||||
|
void appendApp(const DataEntity &app);
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QVector<DataEntity> m_apps;
|
||||||
|
};
|
||||||
|
|
||||||
|
AppSearchModel::AppSearchModel(QObject *parent) : QAbstractListModel(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int AppSearchModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
return m_apps.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int AppSearchModel::columnCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant AppSearchModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (!checkIndex(index, CheckIndexOption::IndexIsValid)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const DataEntity &app = m_apps[index.row()];
|
||||||
|
return app.getValue(static_cast<DataEntity::PropertyName>(role));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppSearchModel::appendApp(const DataEntity &app)
|
||||||
|
{
|
||||||
|
beginInsertRows(QModelIndex(), m_apps.size(), m_apps.size());
|
||||||
|
m_apps.append(app);
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppSearchModel::clear()
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
m_apps.clear();
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====== AppSearchPlugin ====== //
|
||||||
|
AppSearchPlugin::AppSearchPlugin(QObject *parent) : AppListPluginInterface(parent)
|
||||||
|
, m_searchPluginPrivate(new AppSearchPluginPrivate(this)), m_model(new AppSearchModel(this))
|
||||||
|
{
|
||||||
|
connect(m_searchPluginPrivate, &AppSearchPluginPrivate::searchedOne, m_model, &AppSearchModel::appendApp);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppListPluginGroup::Group AppSearchPlugin::group()
|
||||||
|
{
|
||||||
|
return AppListPluginGroup::Search;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AppSearchPlugin::name()
|
||||||
|
{
|
||||||
|
return "Search";
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AppSearchPlugin::title()
|
||||||
|
{
|
||||||
|
return "Search";
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QAction *> AppSearchPlugin::actions()
|
||||||
|
{
|
||||||
|
// TODO: 搜索结果排序选项
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QAbstractItemModel *AppSearchPlugin::dataModel()
|
||||||
|
{
|
||||||
|
return m_model;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppSearchPlugin::search(const QString &keyword)
|
||||||
|
{
|
||||||
|
m_model->clear();
|
||||||
|
if (keyword.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_searchPluginPrivate->startSearch(keyword);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppSearchPlugin::~AppSearchPlugin()
|
||||||
|
{
|
||||||
|
m_searchPluginPrivate->stopSearch();
|
||||||
|
m_searchPluginPrivate->quit();
|
||||||
|
m_searchPluginPrivate->wait();
|
||||||
|
m_searchPluginPrivate->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // UkuiMenu
|
||||||
|
|
||||||
|
#include "app-search-plugin.moc"
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024, 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Authors: hxf <hewenfei@kylinos.cn>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UKUI_MENU_APP_SEARCH_PLUGIN_H
|
||||||
|
#define UKUI_MENU_APP_SEARCH_PLUGIN_H
|
||||||
|
|
||||||
|
#include "app-list-plugin.h"
|
||||||
|
|
||||||
|
namespace UkuiMenu {
|
||||||
|
|
||||||
|
class AppSearchPluginPrivate;
|
||||||
|
class AppSearchModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class AppSearchPlugin
|
||||||
|
* 应用搜索插件,调用搜索接口进行应用搜索
|
||||||
|
*/
|
||||||
|
class AppSearchPlugin : public AppListPluginInterface
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit AppSearchPlugin(QObject *parent = nullptr);
|
||||||
|
~AppSearchPlugin() override;
|
||||||
|
|
||||||
|
AppListPluginGroup::Group group() override;
|
||||||
|
QString name() override;
|
||||||
|
QString title() override;
|
||||||
|
QList<QAction *> actions() override;
|
||||||
|
QAbstractItemModel *dataModel() override;
|
||||||
|
void search(const QString &keyword) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
AppSearchModel *m_model {nullptr};
|
||||||
|
AppSearchPluginPrivate * m_searchPluginPrivate {nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // UkuiMenu
|
||||||
|
|
||||||
|
#endif //UKUI_MENU_APP_SEARCH_PLUGIN_H
|
Loading…
Reference in New Issue