feat: 修改插件接口,增加Factory整合widget和菜单插件接口

This commit is contained in:
hewenfei 2023-12-11 10:38:02 +08:00
parent 0e8d4782ae
commit 6a45e4dfc9
15 changed files with 929 additions and 99 deletions

View File

@ -121,7 +121,13 @@ set(SOURCE_FILES
src/menu/menu-manager.cpp src/menu/menu-manager.h
src/items/theme-icon.h src/items/theme-icon.cpp
src/settings/user-config.cpp src/settings/user-config.h
)
src/extension/widget-extension.cpp src/extension/widget-extension.h
src/extension/context-menu-extension.cpp src/extension/context-menu-extension.h
src/extension/menu-extension-loader.cpp src/extension/menu-extension-loader.h
src/extension/menu-extension-plugin.cpp src/extension/menu-extension-plugin.h
src/extension/widget-extension-model.cpp src/extension/widget-extension-model.h
src/extension/widget-model.cpp src/extension/widget-model.h
)
if(COMMAND qt_add_dbus_adaptor)
@ -141,6 +147,9 @@ set(LIBRARY_HEADERS
src/data-entity.h
src/menu/menu-provider.h
src/extension/menu-extension-iface.h
src/extension/menu-extension-plugin.h
src/extension/widget-extension.h
src/extension/context-menu-extension.h
)
# qrc

View File

@ -29,54 +29,103 @@ import org.ukui.menu.extension 1.0
Item {
ColumnLayout {
id: sidebarLayout
anchors.fill: parent
anchors.topMargin: 12
spacing: 0
spacing: 5
Item {
id: sidebarTopBar
// header
Layout.fillWidth: true
Layout.preferredHeight: 40
Layout.rightMargin: 12
Layout.leftMargin: 12
height: 40
RowLayout {
anchors.fill: parent
spacing: 4
anchors.leftMargin: 12
anchors.rightMargin:12
spacing: 0
ListView {
id: extensionInfoList
id: widgetList
Layout.fillWidth: true
Layout.fillHeight: true
Layout.leftMargin: 4
Layout.rightMargin: 4
clip: true
spacing: 24
interactive: false
orientation: ListView.Horizontal
model: extensionManager.extensionModel()
delegate: extensionInfoDelegate
function send(data) {
if (currentItem !== null) {
model.send(currentIndex, data);
}
}
onCurrentIndexChanged: {
if (currentItem !== null) {
currentItem.select();
}
}
model: WidgetModel {}
delegate: Component {
//
UkuiItems.StyleBackground {
useStyleTransparency: false
paletteRole: Palette.Highlight
alpha: 0
radius: UkuiItems.Theme.minRadius
borderColor: Palette.Highlight
border.width: activeFocus ? 2 : 0
property var extensionData: model.data
property var extensionOptions: model.options
width: styleText.width
height: ListView.view ? ListView.view.height : 0
activeFocusOnTab: true
KeyNavigation.down: widgetLoader
Keys.onPressed: {
if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) {
widgetList.currentIndex = model.index;
EventTrack.sendClickEvent("switch_plugin", "Sidebar", {"plugin": model.name});
}
}
onExtensionDataChanged: {
if (widgetLoader.source === model.main) {
widgetLoader.item.extensionData = extensionData;
}
}
function select() {
if (widgetLoader.source !== model.main) {
widgetLoader.setSource(model.main, {extensionData: extensionData});
}
}
UkuiItems.StyleText {
height: parent.height
id: styleText
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.bold: parent.ListView.isCurrentItem
paletteRole: parent.ListView.isCurrentItem ? UkuiItems.Theme.Highlight: UkuiItems.Theme.Text
text: model.name
}
MouseArea {
anchors.fill: parent
onClicked: {
normalUI.focusToFalse();
widgetList.currentIndex = model.index;
EventTrack.sendClickEvent("switch_plugin", "Sidebar", {"plugin": model.name});
}
}
}
}
}
Loader {
id: extensionMenuLoader
visible: sourceComponent !== undefined
id: widgetMenuLoader
Layout.preferredWidth: 34
Layout.preferredHeight: 34
Layout.alignment: Qt.AlignVCenter
@ -84,100 +133,39 @@ Item {
}
}
Item {
Loader {
id: widgetLoader
//
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
Loader {
id: extensionLoader
anchors.fill: parent
clip: true
onLoaded: {
item.send.connect(extensionInfoList.send);
// sidebarLayout.updateSidebarLayout(extensionInfoList.currentItem.extensionOptions);
updateMenu();
item.extensionMenuChanged.connect(updateMenu);
}
Keys.onTabPressed: {
extensionInfoList.focus = true
}
function updateMenu() {
if (item === null) {
return;
}
if (item.extensionMenu !== null) {
extensionMenuLoader.sourceComponent = item.extensionMenu;
} else {
extensionMenuLoader.sourceComponent = undefined;
}
}
onLoaded: {
item.send.connect(widgetList.send);
// sidebarLayout.updateSidebarLayout(widgetList.currentItem.extensionOptions);
updateMenu();
item.extensionMenuChanged.connect(updateMenu);
}
}
}
Component {
id: extensionInfoDelegate
AppControls2.StyleBackground {
useStyleTransparent: false
paletteRole: Palette.Highlight
alpha: 0
radius: UkuiItems.Theme.minRadius
borderColor: Palette.Highlight
border.width: activeFocus ? 2 : 0
property var extensionData: model.data
property var extensionOptions: model.options
width: styleText.width
height: ListView.view ? ListView.view.height : 0
activeFocusOnTab: true
KeyNavigation.down: extensionLoader
Keys.onPressed: {
if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) {
ListView.view.currentIndex = model.index;
EventTrack.sendClickEvent("switch_plugin", "Sidebar", {"plugin": model.name});
}
Keys.onTabPressed: {
widgetList.focus = true
}
onExtensionDataChanged: {
if (extensionLoader.source === model.url) {
extensionLoader.item.extensionData = extensionData;
function updateMenu() {
if (item === null) {
return;
}
}
function select() {
if (extensionLoader.source !== model.url) {
extensionLoader.setSource(model.url, {extensionData: extensionData});
}
}
UkuiItems.StyleText {
height: parent.height
id: styleText
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.bold: parent.ListView.isCurrentItem
paletteRole: parent.ListView.isCurrentItem ? UkuiItems.Theme.Highlight: UkuiItems.Theme.Text
text: model.name
}
MouseArea {
anchors.fill: parent
onClicked: {
normalUI.focusToFalse();
parent.ListView.view.currentIndex = model.index;
EventTrack.sendClickEvent("switch_plugin", "Sidebar", {"plugin": model.name});
if (item.extensionMenu !== null) {
widgetMenuLoader.sourceComponent = item.extensionMenu;
} else {
widgetMenuLoader.sourceComponent = undefined;
}
}
}
}
Component.onCompleted: {
if (extensionInfoList.count > 0) {
extensionInfoList.currentIndex = 0;
if (widgetList.count > 0) {
widgetList.currentIndex = 0;
}
}
}

View File

@ -0,0 +1,28 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
*/
#include "context-menu-extension.h"
namespace UkuiMenu {
int ContextMenuExtension::index() const
{
return -1;
}
} // UkuiMenu

View File

@ -0,0 +1,72 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
*/
#ifndef UKUI_MENU_CONTEXT_MENU_EXTENSION_H
#define UKUI_MENU_CONTEXT_MENU_EXTENSION_H
#include <QObject>
#include <QMenu>
#include "data-entity.h"
namespace UkuiMenu {
class MenuInfo
{
Q_GADGET
public:
enum Location {
AppList = 0, /**< 小屏幕的应用列表 */
Extension, /**< 扩展页 */
FolderPage, /**< 文件夹页面 */
FullScreen, /**< 全屏应用列表 */
FullScreenFolder, /**< 全屏文件夹页面 */
};
Q_ENUM(Location)
};
/**
* @class ContextMenuExtension
*
*
*/
class ContextMenuExtension
{
public:
virtual ~ContextMenuExtension() = default;
/**
*
* -1,1000
* @return -1
*/
virtual int index() const;
/**
* data生成action,
*
* @param data app信息
* @param parent action最终显示的QMenu
* @param location
* @param locationId all,category,letterSort和favorite等插件的id
* @return
*/
virtual QList<QAction*> actions(const DataEntity &data, QMenu *parent, const MenuInfo::Location &location, const QString &locationId) = 0;
};
} // UkuiMenu
#endif //UKUI_MENU_CONTEXT_MENU_EXTENSION_H

View File

@ -0,0 +1,137 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
*/
#include "menu-extension-loader.h"
#include "menu-extension-plugin.h"
#include <QDir>
#include <QPluginLoader>
namespace UkuiMenu {
QHash<QString, MenuExtensionPlugin*> MenuExtensionLoader::plugins = QHash<QString, MenuExtensionPlugin*>();
MenuExtensionLoader *MenuExtensionLoader::instance()
{
static MenuExtensionLoader loader;
return &loader;
}
MenuExtensionLoader::MenuExtensionLoader()
{
// setBlackList({});
load();
}
void MenuExtensionLoader::load()
{
loadInternalExtension();
loadExtensionFromDisk();
expand();
}
void MenuExtensionLoader::loadInternalExtension()
{
}
void MenuExtensionLoader::loadExtensionFromDisk()
{
QDir pluginsDir(UKUI_MENU_EXTENSION_DIR);
for(const QString& fileName : pluginsDir.entryList({"*.so"},QDir::Files)) {
QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
QJsonObject metaData = pluginLoader.metaData().value("MetaData").toObject();
QString type = metaData.value("Type").toString();
QString version = metaData.value("Version").toString();
if(type != UKUI_MENU_EXTENSION_I_FACE_TYPE) {
continue;
}
if(version != UKUI_MENU_EXTENSION_I_FACE_VERSION) {
qWarning() << "UKUI_MENU_EXTENSION version check failed:" << fileName << "version:" << version << "iface version : " << UKUI_MENU_EXTENSION_I_FACE_VERSION;
continue;
}
QObject *obj = pluginLoader.instance();
if (!obj) {
continue;
}
MenuExtensionPlugin *plugin = qobject_cast<MenuExtensionPlugin*>(obj);
if (!plugin) {
continue;
}
registerExtension(plugin);
}
}
void MenuExtensionLoader::expand()
{
for (const auto &plugin : MenuExtensionLoader::plugins) {
// qDebug() << "Expand Extension:" << plugin->id();
WidgetExtension *widget = plugin->createWidgetExtension();
if (widget) {
// register widget.
m_widgets.append(widget);
}
ContextMenuExtension *contextMenu = plugin->createContextMenuExtension();
if (contextMenu) {
// 注册菜单
m_menus.append(contextMenu);
}
}
std::sort(m_widgets.begin(), m_widgets.end(), [] (const WidgetExtension *a, const WidgetExtension *b) {
return a->index() <= b->index();
});
std::sort(m_menus.begin(), m_menus.end(), [] (const ContextMenuExtension *a, const ContextMenuExtension *b) {
return a->index() <= b->index();
});
}
void MenuExtensionLoader::setBlackList(const QStringList &blackList)
{
m_blackList = blackList;
}
QList<WidgetExtension *> MenuExtensionLoader::widgets() const
{
return m_widgets;
}
QList<ContextMenuExtension *> MenuExtensionLoader::menus() const
{
return m_menus;
}
void MenuExtensionLoader::registerExtension(MenuExtensionPlugin *plugin)
{
QString id = plugin->id();
if (m_blackList.contains(id) || MenuExtensionLoader::plugins.contains(id)) {
delete plugin;
return;
}
MenuExtensionLoader::plugins.insert(id, plugin);
}
} // UkuiMenu

View File

@ -0,0 +1,60 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
*/
#ifndef UKUI_MENU_MENU_EXTENSION_LOADER_H
#define UKUI_MENU_MENU_EXTENSION_LOADER_H
#include <QHash>
#include <QString>
#include "widget-extension.h"
#include "context-menu-extension.h"
namespace UkuiMenu {
class MenuExtensionPlugin;
class MenuExtensionLoader
{
public:
static MenuExtensionLoader *instance();
QList<WidgetExtension*> widgets() const;
QList<ContextMenuExtension*> menus() const;
private:
MenuExtensionLoader();
void loadInternalExtension();
void loadExtensionFromDisk();
void setBlackList(const QStringList &blackList);
void load();
void expand();
void registerExtension(MenuExtensionPlugin *plugin);
private:
QStringList m_blackList;
QList<WidgetExtension*> m_widgets;
QList<ContextMenuExtension*> m_menus;
static QHash<QString, MenuExtensionPlugin*> plugins;
};
} // UkuiMenu
#endif //UKUI_MENU_MENU_EXTENSION_LOADER_H

View File

@ -0,0 +1,26 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
*/
#include "menu-extension-plugin.h"
UkuiMenu::MenuExtensionPlugin::MenuExtensionPlugin(QObject *parent) : QObject(parent)
{
}
UkuiMenu::MenuExtensionPlugin::~MenuExtensionPlugin() = default;

View File

@ -0,0 +1,62 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
*/
#ifndef UKUI_MENU_MENU_EXTENSION_PLUGIN_H
#define UKUI_MENU_MENU_EXTENSION_PLUGIN_H
#define UKUI_MENU_EXTENSION_I_FACE_TYPE "UKUI_MENU_EXTENSION"
#define UKUI_MENU_EXTENSION_I_FACE_IID "org.ukui.menu.extension"
#define UKUI_MENU_EXTENSION_I_FACE_VERSION "1.0.2"
#include <QtPlugin>
namespace UkuiMenu {
class WidgetExtension;
class ContextMenuExtension;
class Q_DECL_EXPORT MenuExtensionPlugin : public QObject
{
public:
explicit MenuExtensionPlugin(QObject *parent = nullptr);
~MenuExtensionPlugin() override;
/**
* id
* @return id
*/
virtual QString id() = 0;
/**
* Widget扩展
* @return nullptr代表不生产此插件
*/
virtual WidgetExtension *createWidgetExtension() = 0;
/**
*
* @return nullptr代表不生产此插件
*/
virtual ContextMenuExtension *createContextMenuExtension() = 0;
};
} // UkuiMenu
Q_DECLARE_INTERFACE(UkuiMenu::MenuExtensionPlugin, UKUI_MENU_EXTENSION_I_FACE_IID)
#endif //UKUI_MENU_MENU_EXTENSION_PLUGIN_H

View File

@ -0,0 +1,123 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
*/
#include "widget-extension-model.h"
#include "menu-extension-loader.h"
#include <QDebug>
namespace UkuiMenu {
WidgetExtensionModel::WidgetExtensionModel(QObject *parent) : QAbstractListModel(parent)
{
m_widgets = MenuExtensionLoader::instance()->widgets();
for (int i = 0; i < m_widgets.size(); ++i) {
connect(m_widgets.at(i), &WidgetExtension::dataUpdated, this, [i, this] {
Q_EMIT dataChanged(QAbstractListModel::index(i), QAbstractListModel::index(i), {WidgetMetadata::Data});
});
}
}
QModelIndex WidgetExtensionModel::parent(const QModelIndex &child) const
{
return {};
}
int WidgetExtensionModel::rowCount(const QModelIndex &parent) const
{
return m_widgets.count();
}
int WidgetExtensionModel::columnCount(const QModelIndex &parent) const
{
return 1;
}
QVariant WidgetExtensionModel::data(const QModelIndex &index, int role) const
{
if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid)) {
return {};
}
int row = index.row();
WidgetExtension *widget = m_widgets.at(row);
auto key = WidgetMetadata::Key(role);
switch (key) {
case WidgetMetadata::Id:
case WidgetMetadata::Icon:
case WidgetMetadata::Name:
case WidgetMetadata::Tooltip:
case WidgetMetadata::Version:
case WidgetMetadata::Description:
case WidgetMetadata::Main:
case WidgetMetadata::Type:
case WidgetMetadata::Flag:
return widget->metadata().value(key, {});
case WidgetMetadata::Data:
return widget->data();
default:
break;
}
return {};
}
QHash<int, QByteArray> WidgetExtensionModel::roleNames() const
{
QHash<int, QByteArray> hash;
hash.insert(WidgetMetadata::Id, "id");
hash.insert(WidgetMetadata::Icon, "icon");
hash.insert(WidgetMetadata::Name, "name");
hash.insert(WidgetMetadata::Tooltip, "tooltip");
hash.insert(WidgetMetadata::Version, "version");
hash.insert(WidgetMetadata::Description, "description");
hash.insert(WidgetMetadata::Main, "main");
hash.insert(WidgetMetadata::Type, "type");
hash.insert(WidgetMetadata::Flag, "flag");
hash.insert(WidgetMetadata::Data, "data");
return hash;
}
WidgetExtension *WidgetExtensionModel::widgetAt(int index) const
{
if (index < 0 || index >= m_widgets.count()) {
return nullptr;
}
return m_widgets.at(index);
}
void WidgetExtensionModel::notify(int index, const QVariantMap &data) const
{
WidgetExtension *widget = widgetAt(index);
if (widget) {
widget->receive(data);
}
}
WidgetExtensionModel *WidgetExtensionModel::instance()
{
static WidgetExtensionModel model;
return &model;
}
} // UkuiMenu

View File

@ -0,0 +1,50 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
*/
#ifndef UKUI_MENU_WIDGET_EXTENSION_MODEL_H
#define UKUI_MENU_WIDGET_EXTENSION_MODEL_H
#include <QAbstractListModel>
namespace UkuiMenu {
class WidgetExtension;
class WidgetExtensionModel : public QAbstractListModel
{
Q_OBJECT
public:
static WidgetExtensionModel *instance();
explicit WidgetExtensionModel(QObject *parent = nullptr);
QModelIndex parent(const QModelIndex &child) const override;
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
QHash<int, QByteArray> roleNames() const override;
Q_INVOKABLE UkuiMenu::WidgetExtension *widgetAt(int index) const;
Q_INVOKABLE void notify(int index, const QVariantMap &data) const;
private:
QList<WidgetExtension*> m_widgets;
};
} // UkuiMenu
#endif //UKUI_MENU_WIDGET_EXTENSION_MODEL_H

View File

@ -0,0 +1,43 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
*/
#include "widget-extension.h"
namespace UkuiMenu {
WidgetExtension::WidgetExtension(QObject *parent) : QObject(parent)
{
qRegisterMetaType<UkuiMenu::MetadataMap>();
}
int WidgetExtension::index() const
{
return -1;
}
QVariantMap WidgetExtension::data()
{
return {};
}
void WidgetExtension::receive(const QVariantMap &data)
{
Q_UNUSED(data)
}
} // UkuiMenu

View File

@ -0,0 +1,88 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
*/
#ifndef UKUI_MENU_WIDGET_EXTENSION_H
#define UKUI_MENU_WIDGET_EXTENSION_H
#include <QObject>
#include <QVariant>
namespace UkuiMenu {
class WidgetMetadata
{
Q_GADGET
public:
enum Key {
Id = 0,
Icon,
Name,
Tooltip,
Version,
Description,
Main,
Type,
Flag,
Data
};
Q_ENUM(Key)
enum TypeValue {
Widget = 0x01, /**> 显示在插件区域 */
Button = 0x02, /**> 显示在侧边栏 */
AppList = 0x04 /**> 显示在应用列表,默认会显示在全屏界面 */
};
Q_ENUM(TypeValue)
Q_DECLARE_FLAGS(Types, TypeValue)
Q_FLAGS(Types)
enum FlagValue {
OnlySmallScreen = 0x01,
OnlyFullScreen = 0x02,
Normal = OnlySmallScreen | OnlyFullScreen
};
Q_ENUM(FlagValue)
Q_DECLARE_FLAGS(Flags, FlagValue)
Q_FLAGS(Flags)
};
typedef QMap<UkuiMenu::WidgetMetadata::Key, QVariant> MetadataMap;
class WidgetExtension : public QObject
{
Q_OBJECT
public:
explicit WidgetExtension(QObject *parent = nullptr);
virtual int index() const;
virtual MetadataMap metadata() const = 0;
// 兼容老版本
virtual QVariantMap data();
virtual void receive(const QVariantMap &data);
Q_SIGNALS:
void dataUpdated();
};
} // UkuiMenu
Q_DECLARE_METATYPE(UkuiMenu::MetadataMap)
Q_DECLARE_METATYPE(UkuiMenu::WidgetMetadata::TypeValue)
Q_DECLARE_METATYPE(UkuiMenu::WidgetMetadata::FlagValue)
#endif //UKUI_MENU_WIDGET_EXTENSION_H

View File

@ -0,0 +1,87 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
*/
#include "widget-model.h"
#include "widget-extension-model.h"
#include <QSortFilterProxyModel>
#include <QDebug>
namespace UkuiMenu {
// ====== WidgetModel ====== //
WidgetModel::WidgetModel(QObject *parent) : QSortFilterProxyModel(parent)
{
init();
}
WidgetMetadata::Types WidgetModel::types() const
{
return m_types;
}
void WidgetModel::setTypes(WidgetMetadata::Types types)
{
if (m_types == types) {
return;
}
m_types = types;
invalidateFilter();
}
WidgetMetadata::Flags WidgetModel::flags() const
{
return m_flags;
}
void WidgetModel::setFlags(WidgetMetadata::Flags flags)
{
if (m_flags == flags) {
return;
}
m_flags = flags;
invalidateFilter();
}
bool WidgetModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
QModelIndex index = sourceModel()->index(source_row, 0, source_parent);
bool acceptFlag = m_types.testFlag(index.data(WidgetMetadata::Type).value<WidgetMetadata::TypeValue>());
if (acceptFlag) {
return m_flags.testFlag(index.data(WidgetMetadata::Flag).value<WidgetMetadata::FlagValue>());
}
return false;
}
void WidgetModel::init()
{
QSortFilterProxyModel::setSourceModel(WidgetExtensionModel::instance());
// invalidateFilter();
}
void WidgetModel::send(int index, const QVariantMap &data)
{
auto sourceModel = qobject_cast<WidgetExtensionModel*>(QSortFilterProxyModel::sourceModel());
if (sourceModel) {
sourceModel->notify(index, data);
}
}
} // UkuiMenu

View File

@ -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 <https://www.gnu.org/licenses/>.
*
*/
#ifndef UKUI_MENU_WIDGET_MODEL_H
#define UKUI_MENU_WIDGET_MODEL_H
#include <QSortFilterProxyModel>
#include <QVariant>
#include "widget-extension.h"
namespace UkuiMenu {
class WidgetModel : public QSortFilterProxyModel
{
Q_OBJECT
Q_PROPERTY(UkuiMenu::WidgetMetadata::Types types READ types WRITE setTypes)
Q_PROPERTY(UkuiMenu::WidgetMetadata::Flags flags READ flags WRITE setFlags)
public:
explicit WidgetModel(QObject *parent = nullptr);
Q_INVOKABLE void init();
Q_INVOKABLE void send(int index, const QVariantMap &data);
WidgetMetadata::Types types() const;
void setTypes(WidgetMetadata::Types types);
WidgetMetadata::Flags flags() const;
void setFlags(WidgetMetadata::Flags flags);
protected:
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
private:
WidgetMetadata::Types m_types = WidgetMetadata::Widget;
WidgetMetadata::Flags m_flags = WidgetMetadata::Normal;
};
}
#endif //UKUI_MENU_WIDGET_MODEL_H

View File

@ -33,6 +33,7 @@
#include "data-provider-manager.h"
#include "event-track.h"
#include "sidebar-button-utils.h"
#include "extension/widget-model.h"
#include <QGuiApplication>
#include <QCommandLineParser>
@ -67,6 +68,8 @@ void UkuiMenuApplication::registerQmlTypes()
ModelManager::registerMetaTypes();
qmlRegisterType<WidgetModel>(uri, versionMajor, versionMinor, "WidgetModel");
// commons
qRegisterMetaType<UkuiMenu::DataType::Type>("DataType::Type");
qRegisterMetaType<UkuiMenu::DataEntity>("DataEntity");