diff --git a/README.md b/README.md index bca2c143a9c1bbb99d0636295d42507fa519074c..eae0639106e64fb43d671c06412fe05867ac6b5d 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,55 @@ items是qml import的主要入口点,用于向qml应用程序提供ukui-quick WidgetInterface是一个插件接口定义,插件可以选择实现这个接口以实现某些特性功能,如增加自定义右键菜单项等.这是一个可选接口,但可以脱离qmlUI单独加载,即可以实现一个不包含UI的插件,仅包含一个动态库的插件. +##### 2.1.4.1 WidgetBridge 与 WidgetFeatureProvider + + WidgetBridge用于在QML侧访问widget相关的领域能力对象(feature object),它本身不定义具体业务状态类型,而是只定义“按key查询QObject能力对象”的桥接协议。具体的状态对象或功能对象应当定义在宿主应用或插件自身仓库中,而不是定义在ukui-quick里。 + + WidgetFeatureProvider是这个桥接协议的provider接口。provider既可以由插件动态库提供,也可以由宿主应用在运行时为某个widget注册: + +- 插件侧通过 `WidgetInterface::featureProviders()` 返回provider对象列表 +- 宿主侧通过 `WidgetBridge::setFeatureProvider(widget, provider)` 注册provider +- QML侧通过 `WidgetBridge.feature("feature.key")` 或 `WidgetBridge.hasFeature("feature.key")` 访问功能 + + 当多个provider声明同一个feature key时,解析顺序如下: + +- 插件侧provider优先于宿主侧provider +- 同一来源内部,后注册或后返回的provider优先 + + 一个最小示例如下: + +```c++ +class SearchFeatureProvider : public QObject, public UkuiQuick::WidgetFeatureProvider +{ + Q_OBJECT + +public: + bool hasFeature(const QString &key) const override + { + return key == QStringLiteral("org.ukui.search.state"); + } + + QObject *feature(const QString &key) override + { + return hasFeature(key) ? m_stateObject : nullptr; + } + + QStringList availableFeatures() const override + { + return {QStringLiteral("org.ukui.search.state")}; + } + +private: + QObject *m_stateObject = nullptr; +}; +``` + +```qml +WidgetItem { + readonly property var searchState: WidgetBridge.feature("org.ukui.search.state") +} +``` + ##### 2.1.5 WidgetMetadata WidgetMetadata表示一个插件的原始元数据信息,所谓原始元数据,就是插件在打包时安装的metadata.json文件中提供的信息.原始元数据在插件框架中非常重要,它用于描述一个插件,包括插件的名称,ID,介绍等基础信息,还有插件的类型(Host),国际化,UI入口等信息.实际上,他可以类比为原生linux应用的"desktop"文件. @@ -388,7 +437,6 @@ Island在加载mainView(主Container)时,会根据mainView的Id在配置文件 [实现一个任务栏插件的步骤](https://yayqg9ul2g.feishu.cn/docx/GBq9dVTmLodP7ExXr6kc8yLsnDf?from=from_copylink) - ### [platform](platform) ukui桌面环境特有组件库,提供一些能够与ukui桌面环境进行交互的组件。 diff --git a/framework/CMakeLists.txt b/framework/CMakeLists.txt index d9306b20942cf406a71b124a16480f849db10894..6e2bfdb500331e2c03a6d8c3636c2db27db2c84b 100644 --- a/framework/CMakeLists.txt +++ b/framework/CMakeLists.txt @@ -21,6 +21,8 @@ set(PROJECT_SOURCES widget/widget-content.cpp widget/widget-content.h widget/widget-container.cpp widget/widget-container.h widget/widget-interface.h + widget-ui/widget-bridge.cpp widget-ui/widget-bridge.h + widget-ui/widget-feature-provider.h widget-ui/widget-item.cpp widget-ui/widget-item.h widget-ui/widget-item-engine.cpp widget-ui/widget-item-engine.h widget-ui/widget-item-context.cpp widget-ui/widget-item-context.h @@ -40,6 +42,8 @@ set(HEADERS widget/widget-container.h widget/widget-content.h widget/widget-interface.h + widget-ui/widget-bridge.h + widget-ui/widget-feature-provider.h widget-ui/widget-item.h widget-ui/widget-container-item.h config/config.h diff --git a/framework/widget-ui/widget-bridge.cpp b/framework/widget-ui/widget-bridge.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1b3866fe799c49ba0f7a47d3775a1a6b360f9c42 --- /dev/null +++ b/framework/widget-ui/widget-bridge.cpp @@ -0,0 +1,430 @@ +/* + * Copyright (C) 2026, 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 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 . + * Authors: iaom + */ + +#include "widget-bridge.h" + +#include +#include +#include +#include + +#include "widget-feature-provider.h" +#include "widget-item-context.h" +#include "widget-item.h" +#include "widget.h" + +namespace UkuiQuick { +class WidgetBridgePrivate +{ +public: + explicit WidgetBridgePrivate(QObject *owner) + : owner(owner) + { + } + + QObject *owner {nullptr}; + QString lastError; + mutable QPointer cachedWidget; + mutable bool providersDirty {true}; + mutable QList> cachedProviderObjects; + mutable QStringList cachedAvailableFeatures; +}; + +namespace { + +QHash>> &hostFeatureProviders() +{ + static QHash>> providers; + return providers; +} + +QHash>> &bridgeInstances() +{ + static QHash>> instances; + return instances; +} + +Widget *resolveWidget(QObject *object) +{ + if (!object) { + return nullptr; + } + + if (auto *widgetItem = qobject_cast(object)) { + return widgetItem->widget(); + } + + QQmlContext *context = QQmlEngine::contextForObject(object); + while (context) { + context = context->parentContext(); + if (auto *widgetContext = qobject_cast(context)) { + return widgetContext->widget(); + } + } + + return nullptr; +} + +QList resolveProviders(const Widget *widget) +{ + QList providers; + if (!widget) { + return providers; + } + + const auto pluginProviders = widget->plugin() ? widget->plugin()->featureProviders() : QList {}; + for (auto it = pluginProviders.crbegin(); it != pluginProviders.crend(); ++it) { + if (auto *provider = dynamic_cast(*it)) { + providers.append(provider); + } + } + + auto &hostProviders = hostFeatureProviders(); + auto hostIt = hostProviders.find(widget); + if (hostIt != hostProviders.end()) { + QList> alive; + alive.reserve(hostIt->size()); + for (auto it = hostIt->crbegin(); it != hostIt->crend(); ++it) { + if (!*it) { + continue; + } + + alive.prepend(*it); + if (auto *provider = dynamic_cast((*it).data())) { + providers.append(provider); + } + } + + if (alive.isEmpty()) { + hostProviders.erase(hostIt); + } else { + *hostIt = alive; + } + } + + return providers; +} + +QStringList collectAvailableFeatures(const QList> &providerObjects) +{ + QStringList features; + for (const auto &providerObject : providerObjects) { + auto *provider = dynamic_cast(providerObject.data()); + if (!provider) { + continue; + } + + const auto providerFeatures = provider->availableFeatures(); + for (const auto &featureKey : providerFeatures) { + if (!features.contains(featureKey)) { + features.append(featureKey); + } + } + } + + return features; +} + +void notifyBridges(const Widget *widget) +{ + auto &instances = bridgeInstances(); + auto it = instances.find(widget); + if (it == instances.end()) { + return; + } + + QList> alive; + alive.reserve(it->size()); + for (const auto &bridge : std::as_const(*it)) { + if (!bridge) { + continue; + } + bridge->notifyProviderChanged(); + alive.append(bridge); + } + + if (alive.isEmpty()) { + instances.erase(it); + return; + } + + *it = alive; +} + +} // namespace + +/*! + \class UkuiQuick::WidgetBridge + \inmodule UkuiQuickFramework + \inheaderfile widget-bridge.h + \brief widget 与 feature provider 之间的桥接对象. + + WidgetBridge 用于聚合当前 widget 关联的全部 WidgetFeatureProvider, + 并以统一的 feature key 查询接口向 C++ 和 QML 暴露领域能力对象。 + + provider 可以来自插件动态库, 也可以来自宿主应用。发生 key 冲突时: + \list + \li 插件侧 provider 的优先级高于宿主侧 provider + \li 同一来源内部, 后注册或后返回的 provider 优先级更高 + \endlist + + \sa UkuiQuick::WidgetFeatureProvider, UkuiQuick::WidgetInterface + */ + +/*! + \qmltype WidgetBridge + \inqmlmodule UkuiQuickFramework + \brief WidgetItem 的附加功能桥接对象. + + WidgetBridge 作为附加属性暴露在每个 \c WidgetItem 上, 用于在 QML 中访问当前 widget 的 feature object。 + + 常见用法如下: + \qml + import UkuiQuickFramework 1.0 + + WidgetItem { + readonly property var searchState: WidgetBridge.feature("org.ukui.search.state") + } + \endqml + */ + +WidgetBridge::WidgetBridge(QObject *owner) + : QObject(owner), d_ptr(new WidgetBridgePrivate(owner)) +{ + if (auto *bridgeWidget = widget()) { + bridgeInstances()[bridgeWidget].append(this); + } +} + +WidgetBridge::~WidgetBridge() +{ + const auto *bridgeWidget = widget(); + if (!bridgeWidget) { + return; + } + + auto it = bridgeInstances().find(bridgeWidget); + if (it == bridgeInstances().end()) { + return; + } + + it->removeAll(this); + if (it->isEmpty()) { + bridgeInstances().erase(it); + } +} + +WidgetBridge *WidgetBridge::qmlAttachedProperties(QObject *object) +{ + return new WidgetBridge(object); +} + +/*! + \fn static void WidgetBridge::setFeatureProvider(UkuiQuick::Widget *widget, QObject *provider) + + 为 \a widget 注册一个宿主侧 provider. + 如果 \a provider 实现了 WidgetFeatureProvider 接口, 其 feature 将通过 WidgetBridge 对外可见。 + */ +void WidgetBridge::setFeatureProvider(Widget *widget, QObject *provider) +{ + if (!widget || !provider) { + return; + } + + hostFeatureProviders()[widget].append(provider); + connect(widget, &QObject::destroyed, [] (QObject *obj) { + const auto *bridgeWidget = static_cast(obj); + hostFeatureProviders().remove(bridgeWidget); + bridgeInstances().remove(bridgeWidget); + }); + connect(provider, &QObject::destroyed, widget, [widget] { + notifyBridges(widget); + }); + notifyBridges(widget); +} + +/*! + \fn static void WidgetBridge::clearFeatureProvider(const UkuiQuick::Widget *widget) + + 清空 \a widget 上由宿主侧注册的 provider 列表。 + */ +void WidgetBridge::clearFeatureProvider(const Widget *widget) +{ + if (!widget) { + return; + } + + hostFeatureProviders().remove(widget); + notifyBridges(widget); +} + +/*! + \property WidgetBridge::widget + 当前附加属性所关联的 widget 对象. + */ +Widget *WidgetBridge::widget() const +{ + Q_D(const WidgetBridge); + if (d->cachedWidget) { + return d->cachedWidget; + } + + d->cachedWidget = resolveWidget(d->owner); + return d->cachedWidget; +} + +/*! + \property WidgetBridge::pluginObject + 当前 widget 加载的插件动态库对象。 + + 该属性仅用于直接访问插件对象本身, 更推荐通过 feature() 获取稳定的 feature object. + */ +QObject *WidgetBridge::pluginObject() const +{ + auto *bridgeWidget = widget(); + if (!bridgeWidget) { + return nullptr; + } + + return dynamic_cast(bridgeWidget->plugin()); +} + +/*! + \property WidgetBridge::lastError + 最近一次 feature 解析失败时的错误信息。 + + 成功解析 feature 或 provider 集合发生变化时, 该属性会被清空. + */ +QString WidgetBridge::lastError() const +{ + Q_D(const WidgetBridge); + return d->lastError; +} + +/*! + \property WidgetBridge::availableFeatures + 当前 widget 可用的 feature key 列表. + + 该列表会聚合插件侧与宿主侧 provider 的结果, 并按最终生效顺序去重。 + */ + +QStringList WidgetBridge::availableFeatures() const +{ + Q_D(const WidgetBridge); + if (d->providersDirty) { + d->cachedProviderObjects.clear(); + const auto providers = resolveProviders(widget()); + d->cachedProviderObjects.reserve(providers.size()); + for (auto *provider : providers) { + d->cachedProviderObjects.append(dynamic_cast(provider)); + } + d->cachedAvailableFeatures = collectAvailableFeatures(d->cachedProviderObjects); + d->providersDirty = false; + } + + return d->cachedAvailableFeatures; +} + +/*! + \fn QObject *WidgetBridge::feature(const QString &key) + + 返回 \a key 对应的 feature 对象。 + 如果当前 widget 没有可用 provider 或没有 provider 支持该 key, 则返回 \c nullptr, + 并更新 lastError 属性. + */ +QObject *WidgetBridge::feature(const QString &key) +{ + Q_D(WidgetBridge); + if (d->providersDirty) { + availableFeatures(); + } + + if (d->cachedProviderObjects.isEmpty()) { + updateError(tr("No feature provider registered for this widget.")); + return nullptr; + } + + for (const auto &providerObject : std::as_const(d->cachedProviderObjects)) { + auto *provider = dynamic_cast(providerObject.data()); + if (!provider) { + continue; + } + if (!provider->hasFeature(key)) { + continue; + } + + auto *resolvedFeature = provider->feature(key); + if (!resolvedFeature) { + continue; + } + + updateError({}); + return resolvedFeature; + } + + updateError(tr("Feature is unavailable: %1").arg(key)); + return nullptr; +} + +/*! + \fn bool WidgetBridge::hasFeature(const QString &key) const + + 返回当前 widget 是否存在支持 \a key 的 provider. + */ +bool WidgetBridge::hasFeature(const QString &key) const +{ + Q_D(const WidgetBridge); + if (d->providersDirty) { + availableFeatures(); + } + + for (const auto &providerObject : std::as_const(d->cachedProviderObjects)) { + auto *provider = dynamic_cast(providerObject.data()); + if (!provider) { + continue; + } + if (provider->hasFeature(key)) { + return true; + } + } + + return false; +} + +void WidgetBridge::updateError(const QString &error) +{ + Q_D(WidgetBridge); + if (d->lastError == error) { + return; + } + + d->lastError = error; + Q_EMIT lastErrorChanged(); +} + +void WidgetBridge::notifyProviderChanged() +{ + Q_D(WidgetBridge); + d->providersDirty = true; + d->cachedProviderObjects.clear(); + d->cachedAvailableFeatures.clear(); + updateError({}); + Q_EMIT availableFeaturesChanged(); +} + +} // namespace UkuiQuick diff --git a/framework/widget-ui/widget-bridge.h b/framework/widget-ui/widget-bridge.h new file mode 100644 index 0000000000000000000000000000000000000000..19cc7e60b28708a969ffc3151dc0c235efb3141b --- /dev/null +++ b/framework/widget-ui/widget-bridge.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2026, 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 . + * Authors: iaom + */ + +#ifndef UKUI_QUICK_WIDGET_BRIDGE_H +#define UKUI_QUICK_WIDGET_BRIDGE_H + +#include +#include +#include + +namespace UkuiQuick { + +class Widget; +class WidgetBridgePrivate; + +class WidgetBridge : public QObject +{ + Q_OBJECT + Q_PROPERTY(UkuiQuick::Widget *widget READ widget CONSTANT FINAL) + Q_PROPERTY(QObject *pluginObject READ pluginObject FINAL) + Q_PROPERTY(QString lastError READ lastError NOTIFY lastErrorChanged FINAL) + Q_PROPERTY(QStringList availableFeatures READ availableFeatures NOTIFY availableFeaturesChanged FINAL) +public: + explicit WidgetBridge(QObject *owner = nullptr); + ~WidgetBridge() override; + + static WidgetBridge *qmlAttachedProperties(QObject *object); + + static void setFeatureProvider(UkuiQuick::Widget *widget, QObject *provider); + static void clearFeatureProvider(const UkuiQuick::Widget *widget); + + Widget *widget() const; + QObject *pluginObject() const; + QString lastError() const; + QStringList availableFeatures() const; + + Q_INVOKABLE QObject *feature(const QString &key); + Q_INVOKABLE bool hasFeature(const QString &key) const; + void notifyProviderChanged(); + +Q_SIGNALS: + void lastErrorChanged(); + void availableFeaturesChanged(); + +private: + void updateError(const QString &error); + +private: + Q_DECLARE_PRIVATE(WidgetBridge) + friend class WidgetBridgePrivate; + QScopedPointer d_ptr; +}; + +} // namespace UkuiQuick + +QML_DECLARE_TYPEINFO(UkuiQuick::WidgetBridge, QML_HAS_ATTACHED_PROPERTIES) + +#endif // UKUI_QUICK_WIDGET_BRIDGE_H diff --git a/framework/widget-ui/widget-feature-provider.h b/framework/widget-ui/widget-feature-provider.h new file mode 100644 index 0000000000000000000000000000000000000000..d70b23c45c0bb1fd7652713aa056a3f162e9bc8a --- /dev/null +++ b/framework/widget-ui/widget-feature-provider.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2026, 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 . + * Authors: iaom + */ + +#ifndef UKUI_QUICK_WIDGET_FEATURE_PROVIDER_H +#define UKUI_QUICK_WIDGET_FEATURE_PROVIDER_H + +#include +#include + +namespace UkuiQuick { + +/*! + \class UkuiQuick::WidgetFeatureProvider + \inmodule UkuiQuickFramework + \inheaderfile widget-feature-provider.h + \brief 为 WidgetBridge 提供领域能力对象的 provider 接口. + + WidgetFeatureProvider 用于按 feature key 暴露 \c QObject 功能对象。 + 一个 provider 可以暴露一个或多个 feature,返回对象的生命周期由 provider 自身负责。 + + 该接口通常由插件动态库中的辅助对象或宿主应用中的桥接对象实现。 + 它们分别通过 WidgetInterface::featureProviders() 与 WidgetBridge::setFeatureProvider() + 暴露给 WidgetBridge。 + + \sa UkuiQuick::WidgetBridge, UkuiQuick::WidgetInterface + */ +class WidgetFeatureProvider +{ +public: + virtual ~WidgetFeatureProvider() = default; + /*! + \fn virtual QObject *WidgetFeatureProvider::feature(const QString &key) + + 返回 \a key 对应的 feature 对象。如果当前 provider 不支持该 key, 应返回 \c nullptr. + */ + virtual bool hasFeature(const QString &key) const = 0; + + /*! + \fn virtual QObject *WidgetFeatureProvider::feature(const QString &key) + + 返回 \a key 对应的 feature 对象。如果当前 provider 不支持该 key, 应返回 \c nullptr. + */ + virtual QObject *feature(const QString &key) = 0; + /*! + \fn virtual QStringList WidgetFeatureProvider::availableFeatures() const + + 返回当前 provider 对外暴露的全部 feature key 列表. + */ + virtual QStringList availableFeatures() const = 0; +}; +} // namespace UkuiQuick + +#endif // UKUI_QUICK_WIDGET_FEATURE_PROVIDER_H diff --git a/framework/widget-ui/widget-item.cpp b/framework/widget-ui/widget-item.cpp index bfb8880973af9fae17a8eda08b712afb9256ffa1..37d28f20f914e03650a3a0b4607fa3bd37bbc2a5 100644 --- a/framework/widget-ui/widget-item.cpp +++ b/framework/widget-ui/widget-item.cpp @@ -19,6 +19,7 @@ */ #include "widget-item.h" +#include "widget-bridge.h" #include "widget-item-engine.h" #include "widget-item-context.h" #include "widget-item-attached.h" @@ -157,6 +158,7 @@ void WidgetQuickItem::registerTypes() qmlRegisterType(uri, 1, 0, "WidgetItem"); qmlRegisterUncreatableType(uri, 1, 0, "Widget", "For widgetItem attached prop."); + qmlRegisterUncreatableType(uri, 1, 0, "WidgetBridge", "For widget bridge attached prop."); qmlRegisterType(containerUri, 1, 0, "WidgetContainerItem"); qmlRegisterUncreatableType(containerUri, 1, 0, "WidgetContainer", "For WidgetContainer attached prop."); diff --git a/framework/widget/widget-interface.h b/framework/widget/widget-interface.h index 03523885252ca4efd6d5dee356228cca84d7e33b..6f65ed660dadc148699b97cf08705c003ba685b1 100644 --- a/framework/widget/widget-interface.h +++ b/framework/widget/widget-interface.h @@ -24,6 +24,7 @@ #define WIDGET_INTERFACE_VERSION "1.0.0" #include #include +#include namespace UkuiQuick { /*! @@ -32,17 +33,39 @@ namespace UkuiQuick \inheaderfile widget-interface.h \brief 插件接口. - WidgetInterface 是一个插件接口定义,插件可以选择实现这个接口以实现某些特性功能,如增加自定义右键菜单项等. - 这是一个可选接口,但可以脱离qmlUI单独加载,即可以实现一个不包含UI的插件,仅包含一个动态库的插件. + WidgetInterface 是一个插件接口定义, 插件可以选择实现这个接口以实现某些特性功能, 如增加自定义右键菜单项、 + 向 QML 暴露 feature object 等。 + 这是一个可选接口, 但可以脱离 qml UI 单独加载, 即可以实现一个不包含 UI 的插件, 仅包含一个动态库的插件. */ class WidgetInterface { public: WidgetInterface()= default; + +/*! + \fn virtual QList WidgetInterface::actions() + + 返回插件希望追加到 widget 上下文操作中的动作列表. + */ virtual QList actions() { return {}; }; +/*! + \fn virtual QList WidgetInterface::featureProviders() + + 返回插件侧注册的 feature provider 列表。 + 列表中的对象如果实现了 WidgetFeatureProvider 接口, 将被 WidgetBridge 聚合后暴露给 QML. + + 当多个 provider 声明同一个 feature key 时, 插件侧 provider 的优先级高于宿主侧 provider; + 同一来源内部, 列表中靠后的 provider 优先级更高. + + \sa UkuiQuick::WidgetFeatureProvider, UkuiQuick::WidgetBridge + */ + virtual QList featureProviders() + { + return {}; + } }; } diff --git a/framework/widget/widget-metadata.cpp b/framework/widget/widget-metadata.cpp index 7dad19586cceb427b71190ed584943cb2922a72e..374de1b9261bc3136bf3ea88ea670b626caaa488 100644 --- a/framework/widget/widget-metadata.cpp +++ b/framework/widget/widget-metadata.cpp @@ -136,6 +136,7 @@ QString WidgetMetadataPrivate::localeKey(const QString& key) \value All 用于所有类型 \c container \value Wallpaper 桌面壁纸插件 \value DesktopView 桌面布局插件 + \value Search 全局搜索插件 */ /*! @@ -379,6 +380,8 @@ WidgetMetadata::Hosts WidgetMetadata::showIn() const hosts |= Wallpaper; } else if (host == QStringLiteral("DesktopView")) { hosts |= DesktopView; + } else if (host == QStringLiteral("Search")) { + hosts |= Search; } } return hosts; diff --git a/framework/widget/widget-metadata.h b/framework/widget/widget-metadata.h index aa3b1cd24d59a63363ba1ff3673fe12682c4aac4..eac54e4a3320d878172eb0eff92eedb6d7f21b4d 100644 --- a/framework/widget/widget-metadata.h +++ b/framework/widget/widget-metadata.h @@ -58,17 +58,21 @@ public: */ Shortcut = 0x00000010, /** - *@brief 用于所有类型container + * @brief 特殊类型,桌面壁纸插件 */ - All = Panel | SideBar | Desktop | TaskManager | Shortcut, + Wallpaper = 0x00000020, + /** + * @brief 特殊类型,桌面布局插件 + */ + DesktopView = 0x00000040, /** - * @brief 桌面壁纸插件 + * @brief 特殊类型,全局搜索插件 */ - Wallpaper, + Search = 0x00000080, /** - * @brief 桌面布局插件 + *@brief 用于所有类型container */ - DesktopView + All = Panel | SideBar | Desktop | TaskManager | Shortcut, }; Q_DECLARE_FLAGS(Hosts, Host); diff --git a/framework/widget/widget.cpp b/framework/widget/widget.cpp index 17fe0e42812a78c5cafb56a8b15d26cabf0868c0..44bc57e1db833b368e6347bf5b128adce2b081bf 100644 --- a/framework/widget/widget.cpp +++ b/framework/widget/widget.cpp @@ -493,6 +493,9 @@ void Widget::setVisible(bool visible) /*! \property Widget::plugin 该属性表示 \c widget 中加载的以动态库形式安装的插件. + + 当插件实现了 WidgetInterface 时, 它既可以通过 actions() 提供扩展动作, + 也可以通过 featureProviders() 向 WidgetBridge 暴露领域能力对象. */ WidgetInterface* Widget::plugin() const {