Skip to content

feat: add applet visibility control to DAppletItemModel and - #1676

Open
wjyrich wants to merge 1 commit into
linuxdeepin:masterfrom
wjyrich:task-393299-1
Open

feat: add applet visibility control to DAppletItemModel and#1676
wjyrich wants to merge 1 commit into
linuxdeepin:masterfrom
wjyrich:task-393299-1

Conversation

@wjyrich

@wjyrich wjyrich commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

DPluginLoader

Implement a framework-level hidden applets mechanism that allows suppressing individual applet root objects from the containment model without destroying them. The DAppletItemModel now maintains both a complete root objects list and a filtered visible subset. A new setRootObjectVisible method enables toggling visibility while preserving the original insertion order upon restoration. The DPluginLoader exposes hiddenApplets, isAppletHidden, and setHiddenApplets APIs, and the shell synchronizes these with a DConfig key hiddenApplets. Hidden applets remain loaded but their root objects are reparented to the applet and removed from the visual model. Unit tests verify order preservation and removal semantics.

Log: Added applet visibility control API and DConfig integration

Influence:

  1. Test applet hiding and showing via DConfig changes
  2. Verify that hidden applets remain loaded and their root objects are properly reparented
  3. Test that removing a plugin ID from the hidden list restores the applet in its original model order
  4. Verify that the model signals emit correctly on visibility changes
  5. Test interaction with applet creation, deletion, and root object changes
  6. Verify that the API works for multiple containments simultaneously

feat: 为 DAppletItemModel 和 DPluginLoader 添加 Applet 显隐控制

实现框架级隐藏 Applet 机制,可在不销毁实例的前提下将其根对象从容
器模型中移除。DAppletItemModel 维护完整的根对象列表和可见子集,
新增 setRootObjectVisible 方法支持按需切换显隐,恢复时保持原有
插入顺序。DPluginLoader 提供 hiddenAppletsisAppletHiddensetHiddenApplets 接口,Shell 通过 DConfig 键 hiddenApplets 同步配 置。隐藏的 Applet 仍保持加载,其根对象重新挂载到 Applet 自身并从视觉模型
中移除。单元测试验证了顺序保持和移除语义。

Log: 新增 Applet 显隐控制接口和 DConfig 集成

Influence:

  1. 通过 DConfig 变更测试 Applet 的隐藏和显示
  2. 验证隐藏的 Applet 依然保持加载,根对象正确重新挂载
  3. 测试从隐藏列表中移除插件 ID 后 Applet 按原有顺序恢复
  4. 验证模型信号在可见性变更时正确发出
  5. 测试与 Applet 创建、删除及根对象变更的交互
  6. 验证该 API 能同时作用于多个容器

PMS: TASK-393299

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @wjyrich, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: wjyrich

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Comment thread shell/shell.cpp Outdated
}

if (m_dconfig && m_dconfig->isValid()) {
connect(m_dconfig, &Dtk::Core::DConfig::valueChanged,

@18202781743 18202781743 Jul 28, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

配置用subpath的方式去获取,而不是把所有插件都放在一个hiddenApplets里,每个插件都有一个单独的配置,方便后面override, https://github.com/18202781743/cskills/blob/4745ee77b82d808182f2a8681db135b0933fb2ba/dtk-development/references/config/concepts.md?plain=1#L74

Comment thread frame/appletitemmodel.cpp
{
}

QList<QObject *> DAppletItemModel::rootObjects() const

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里rootObjects要改成visibleRootObjects么,要不要加个新的visibleRootObjects属性,

Comment thread frame/appletitemmodel.h Outdated

QList<QObject *> rootObjects() const;
void append(QObject *rootObject);
void append(QObject *rootObject, bool visible = true);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个是公共接口,不能直接加,另外也不需要,在添加的地方去拦截比较合适,

@wjyrich
wjyrich force-pushed the task-393299-1 branch 2 times, most recently from f159ac7 to c07f118 Compare July 28, 2026 06:39
Comment thread docs/plugin/API_en.md Outdated
Q_PROPERTY(QString id READ id CONSTANT FINAL)
Q_PROPERTY(QString pluginId READ pluginId CONSTANT FINAL)
Q_PROPERTY(QObject *rootObject READ rootObject NOTIFY rootObjectChanged)
Q_PROPERTY(bool enable READ enable WRITE setEnable NOTIFY enableChanged FINAL)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个是不是不需要呀,disable了这个applet都不会有了,

@wjyrich
wjyrich force-pushed the task-393299-1 branch 8 times, most recently from ba4eb47 to dccc169 Compare July 29, 2026 03:31
Comment thread frame/pluginloader.cpp
Q_EMIT appletEnabledChanged(pluginId, enabled);
}

DApplet *DPluginLoader::loadApplet(const DAppletData &data)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

如果m_disabledPlugins只是在这里使用的话,可以不用加在pluginloader.cpp里,放在dde-shell的appletloader.cpp里,

Comment thread frame/pluginloader.h
QStringList pluginDirs() const;
void setPluginDirs(const QStringList &dirs);

QStringList disabledApplets() const;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不能删接口的,这个也不用删除吧,

@wjyrich
wjyrich force-pushed the task-393299-1 branch 2 times, most recently from 7e03ceb to e46752f Compare July 30, 2026 01:59
@wjyrich

wjyrich commented Jul 30, 2026

Copy link
Copy Markdown
Contributor Author

/test github-pr-review-ci

@wjyrich
wjyrich force-pushed the task-393299-1 branch 3 times, most recently from e1ca173 to f0c3eff Compare July 30, 2026 03:35
Add the ability to enable or disable DApplet instances via DConfig,
controlling whether their root objects appear in the parent containment
model.

The new `enable` property is exposed as a Q_PROPERTY on DApplet, backed
by a DConfig key `enable` under `org.deepin.dde.shell`. When loading,
DApplet reads this config and watches for changes.

Disabled applets remain loaded but their root objects are removed from
the containment's `appletItems` model; re-enabling re-inserts them.
This enables runtime toggling of applet visibility without unloading/
reloading plugins.

Unit tests are added for the DAppletItemModel (append/remove) and the
enable property change notification logic.

Log: Added DApplet enable/disable feature via DConfig

Influence:
1. Test creating an applet and verifying its enable property is true
by default
2. Set enable to false via dde-dconfig and verify the applet root object
is removed from the containment model
3. Set enable to true and verify the root object reappears
4. Verify that setEnable with the same value does not emit enableChanged
signal
5. Test loading a root plugin (like dock) - its enable should not be
affected (skipped)
6. Verify DConfig changes are watched and applied dynamically at runtime
7. Run unit tests: EnablePropertyNotifiesOnlyOnChange,
AppendsRootObjects, RemovesRootObject

feat: 添加支持通过 DConfig 启用/禁用 Applet 的接口

新增通过 DConfig 控制 DApplet 实例启用的能力,决定其根对象是否显示在父容
器模型中。

新的 `enable` 属性作为 DApplet 的 Q_PROPERTY 暴露,由
`org.deepin.dde.shell` 下的 DConfig 键 `enable` 驱动。加载时 DApplet 读
取该配置并监听变化。

被禁用的 Applet 实例仍保持加载,但根对象从容器的 `appletItems` 模型中
移除;重新启用后会重新追加。这实现了无需卸载/重新加载插件即可运行时切换
Applet 可见性。

新增了 DAppletItemModel(追加/移除)以及 enable 属性变更通知逻辑的单元
测试。

Log: 新增 DApplet 启用/禁用功能

Influence:
1. 测试创建 Applet 并验证其 enable 属性默认为 true
2. 通过 dde-dconfig 将 enable 设为 false,验证根对象已从容器模型中移除
3. 设为 true 后验证根对象重新出现
4. 验证 setEnable 相同值时不会触发 enableChanged 信号
5. 测试加载根插件(如 dock),其 enable 不应受影响(跳过)
6. 验证 DConfig 变化能被监听并在运行时动态生效
7. 运行单元测试:EnablePropertyNotifiesOnlyOnChange、
AppendsRootObjects、RemovesRootObject

PMS: TASK-393299
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

★ 总体评分:95分

■ 【总体评价】

代码实现了通过DConfig动态管理Applet启用状态的功能,逻辑清晰且包含完善的测试用例
代码质量良好,未发现安全漏洞,递归逻辑和生命周期管理正确

■ 【详细分析】

  • 1.语法逻辑(基本正确)✓

AppletConfigManager::ensureAppletConfigs() 正确处理了配置的创建、更新和移除逻辑。DAppletLoaderPrivate::createEnabledAppletsremoveDisabledApplets 的递归遍历逻辑正确,能够实现动态加载和卸载。AppletManagerexecquit 方法中通过拷贝列表避免了迭代器失效问题。
潜在问题:createEnabledApplets 中先创建目标 pluginId 的 applet,随后遍历子 applet 时跳过相同 pluginId 的项并继续递归,逻辑虽然正确但稍显复杂。
建议:可考虑添加注释进一步说明递归的意图,提升可读性。

  • 2.代码质量(良好)✓

新增代码遵循了项目的命名规范,使用了 DTK 的宏和日志分类。新增了对应的单元测试覆盖了核心逻辑,文档同步更新,整体质量高。
潜在问题:appletconfigmanager.cppconfig 对象在插入 m_appletConfigs 后才进行有效性检查,若无效则调用 setAppletEnabled(pluginId, true) 但未从 map 中移除无效的 config 指针。
建议:在检查 config->isValid() 失败时,应从 m_appletConfigs 中移除并清理该 config 对象。

  • 3.代码性能(无性能问题)✓

插件 ID 使用 QSet 进行查找,保证了去重和查找效率。递归操作在通常的插件层级深度下性能开销可忽略。
建议:无需额外优化。

  • 4.代码安全(存在0个安全漏洞)✓

漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个
代码中使用了 Qt 的父子对象树管理内存,DConfig 对象生命周期管理正确,未发现注入或越权风险。

  • 建议:无需修复。

■ 【改进建议代码示例】

diff --git a/shell/appletconfigmanager.cpp b/shell/appletconfigmanager.cpp
index 40804e723..111111111 100644
--- a/shell/appletconfigmanager.cpp
+++ b/shell/appletconfigmanager.cpp
@@ -81,6 +81,7 @@ void AppletConfigManager::ensureAppletConfigs()
         m_appletConfigs.insert(pluginId, config);
         if (!config || !config->isValid()) {
             qCWarning(dsLoaderLog) << "Unable to create applet DConfig; applet remains enabled:" << pluginId;
+            m_appletConfigs.remove(pluginId);
             setAppletEnabled(pluginId, true);
             continue;
         }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants