Skip to content

refactor: migrate to shared dde-shell app model - #791

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
wjyrich:task-393709
Aug 11, 2026
Merged

refactor: migrate to shared dde-shell app model#791
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
wjyrich:task-393709

Conversation

@wjyrich

@wjyrich wjyrich commented Aug 5, 2026

Copy link
Copy Markdown
Contributor
  1. Replace direct AppMgr/AppItem usage with shared dde-shell application model
  2. Add LauncherItem::load() to bridge with org.deepin.ds.dde-apps applet
  3. Refactor AppsModel to adapt source model roles instead of owning app data
  4. Remove direct D-Bus interface generation for ApplicationManager1
  5. Fix QML role references from AppItem to AppsModel namespace
  6. Set apps applet as data source for DesktopIntegration operations
  7. Update QML to use new AppsModel.ddeCategories for category names
  8. Fix category sorting signal ordering to avoid duplicate layout changes

Log: Unified application data source with dde-shell shared model

Influence:

  1. Verify launcher still displays all installed applications correctly
  2. Test application launch through launcher and dock
  3. Test app category browsing and filtering
  4. Test sending/removing apps from desktop
  5. Test autostart toggle functionality
  6. Test disable scale functionality for legacy apps
  7. Test search functionality with pinyin, jianpin, and Chinese
  8. Test recently installed and frequently used sections
  9. Verify icon loading and caching behavior

refactor: 迁移到 dde-shell 共享应用模型

  1. 用共享的 dde-shell 应用模型替换直接的 AppMgr/AppItem 使用
  2. 添加 LauncherItem::load() 与 org.deepin.ds.dde-apps applet 桥接
  3. 重构 AppsModel 适配源模型角色而非拥有应用数据
  4. 移除 ApplicationManager1 的直接 D-Bus 接口生成
  5. 修复 QML 中角色引用从 AppItem 到 AppsModel 命名空间的变更
  6. 设置应用 qml 作为 DesktopIntegration 操作的数据源
  7. 更新 QML 使用新的 AppsModel.ddeCategories 获取分类名称
  8. 修复分类排序信号顺序避免重复的布局变更

Log: 应用数据源统一为 dde-shell 共享模型

Influence:

  1. 验证启动器仍能正确显示所有已安装应用
  2. 测试通过启动器和任务栏启动应用
  3. 测试应用分类浏览和过滤功能
  4. 测试发送/移除应用到桌面
  5. 测试开机自启动开关功能
  6. 测试旧应用的禁用缩放功能
  7. 测试拼音、简拼和中文搜索功能
  8. 测试最近安装和常用应用区域
  9. 验证图标加载和缓存行为

PMS: TASK-393709

Summary by Sourcery

Adapt launcher to use the shared dde-shell application model and applet instead of its own AppMgr-based app model.

New Features:

  • Bridge the launcher applet to the org.deepin.ds.dde-apps applet, wiring its shared application model and category metadata into AppsModel and DesktopIntegration.

Bug Fixes:

  • Ensure category-based sorting and QML section updates emit signals in a stable order to avoid redundant layout changes and duplicate updates.
  • Normalize desktop IDs and guard against empty transliteration data to prevent mismatches and errors in search and navigation logic.

Enhancements:

  • Refactor AppsModel into a QAbstractListModel adapter over an external source model, exposing standardized roles and category metadata expected by QML.
  • Update DesktopIntegration to route launch, desktop, autostart, and scale operations through the shared dde-apps applet instead of direct D-Bus/AppMgr calls.
  • Adjust proxy models, item arrangement logic, and QML views/tests to depend on AppsModel roles and the shared model instead of AppItem/AppMgr, including stronger readiness handling and section/category utilities.

@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

@sourcery-ai

sourcery-ai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Reviewer's Guide

Refactors the launcher’s AppsModel and integration layer to consume the shared dde-shell application model (dde-apps applet) instead of the local AppMgr/AppItem stack, updates DesktopIntegration to route operations through the apps applet, and aligns QML/tests/proxies with the new role IDs, category handling, and sorting/signaling behavior.

Sequence diagram for launching an app via shared dde-apps applet

sequenceDiagram
    actor User
    participant LauncherUI
    participant LauncherController
    participant DesktopIntegration
    participant XdgActivation as XdgActivation
    participant AppsApplet

    User->>LauncherUI: activate app item
    LauncherUI->>LauncherController: requestLaunch(desktopId)
    LauncherController->>DesktopIntegration: launchByDesktopId(desktopId)
    DesktopIntegration->>XdgActivation: requestToken()
    XdgActivation-->>DesktopIntegration: tokenReady(token)
    DesktopIntegration->>AppsApplet: launchApp(desktopId, token)
    AppsApplet-->>DesktopIntegration: bool launched
    alt [launch failed]
        DesktopIntegration-->>LauncherController: [log failure]
    end
Loading

File-Level Changes

Change Details Files
Replace internal AppMgr/AppItem-based AppsModel with an adapter over the shared dde-shell app model, including new roles, filtering, and icon handling.
  • Reimplemented AppsModel as a QAbstractListModel adapter that wraps a configurable QAbstractItemModel source instead of owning AppItem objects.
  • Introduced role mapping from shared model roles (desktopId, name, iconName, categories, ddeCategory, etc.) to launcher-specific Roles, including transliteration and pinyin-based search roles.
  • Implemented source model wiring (rowsInserted/Removed, dataChanged, modelReset, layoutChanged) with an internal row list, normalized desktop IDs, exclusion list, and noDisplay filtering.
  • Added icon cache watching via DFileWatcherManager and a timer that refreshes icon data by calling IconUtils::tryUpdateIconCache().
  • Added ready and ddeCategories Q_PROPERTIES with signals to indicate when the adapter is usable and to expose category enums to QML.
src/models/appsmodel.cpp
src/models/appsmodel.h
Wire launcher to org.deepin.ds.dde-apps: load shared applet, bind its model into AppsModel, and route desktop integration operations through it instead of AppMgr.
  • Added LauncherItem::load() that uses DAppletBridge("org.deepin.ds.dde-apps") to obtain the apps applet, reads its appModel/appModelReady/ddeCategories, and configures AppsModel plus DesktopIntegration accordingly.
  • Changed DesktopIntegration methods (launchByDesktopId, disableScale, setDisableScale, isOnDesktop, sendToDesktop, removeFromDesktop, isAutoStart, setAutoStart) to invoke methods on the apps applet via QMetaObject instead of using AppMgr/AppInfo and removed local desktop file path handling.
  • Added DesktopIntegration::setAppsApplet and stored the applet via QPointer for safe reuse in helper invocations.
shell-launcher-applet/launcheritem.cpp
shell-launcher-applet/launcheritem.h
desktopintegration.cpp
desktopintegration.h
Update proxy models, item arrangement, and QML to use AppsModel roles and ddeCategories instead of AppItem, and to handle new category/sort semantics safely.
  • Adjusted CategorizedSortProxyModel to sort by AppsModel::TransliteratedRole or AppsModel::DDECategoryRole, reordered sectionRoleName and sort updates to avoid duplicate or out-of-order layout changes, and fixed DDECategorySections to read AppsModel roles.
  • Refactored ItemArrangementProxyModel to use AppsModel::DesktopIdRole/IconNameRole/DDECategoryRole for folder IDs, icons, and inferred category-based folder names; gated syncing on AppsModel::ready and ensured it listens to modelReset.
  • Updated QML views (AppListView, AnalysisView, launcheritem.qml) to reference AppsModel roles instead of AppItem, use AppsModel.ddeCategories for category enums, guard against empty sections, and reset list view state on category type changes.
  • Switched various proxy models (SearchFilterProxyModel, FavoritedProxyModel, RecentlyInstalledProxyModel, frequently-used/recently-installed views) from AppItem roles to AppsModel roles and normalized desktop IDs with ".desktop" suffix in tests and logic.
src/models/categorizedsortproxymodel.cpp
src/models/itemarrangementproxymodel.cpp
src/models/itemarrangementproxymodel.h
src/models/searchfilterproxymodel.cpp
src/models/favoritedproxymodel.cpp
src/models/recentlyinstalledproxymodel.cpp
qml/windowed/AppListView.qml
qml/windowed/AnalysisView.qml
shell-launcher-applet/package/launcheritem.qml
Replace unit tests’ direct AppItem/AppMgr usage with a synthetic shared model to validate the new AppsModel adapter and category-sorting signal order.
  • Reworked searchfilterproxymodeltest to build a QStandardItemModel with custom role names (SourceDesktopIdRole, SourceNameRole, etc.), attach it as AppsModel::sourceModel, and set AppsModel::ready(), instead of mutating AppsModel::instance() via AppItem.
  • Adapted tests to expect normalized desktop IDs with ".desktop" suffix and AppsModel::DesktopIdRole; updated helper factory to fill new source roles including ddeCategory.
  • Added testSharedModelAdapter to verify that noDisplay filtering, desktopId normalization, dataChanged role mapping, and row insertion/removal all behave correctly when the source model changes.
  • Added testCategorySortSignalOrder to enforce the signal ordering for sectionRoleNameChanged, layout changes, and categoryTypeChanged in CategorizedSortProxyModel.
tests/searchfilterproxymodeltest.cpp
Remove legacy ApplicationManager1/AppMgr D-Bus integration and AppItem implementation from the build.
  • Deleted appmgr.cpp/appmgr.h and associated D-Bus type helpers (amglobaltypes.h, objectmap.h, propmap.h, qstringmap.h) plus ApplicationManager1/ObjectManager1 XMLs.
  • Dropped D-Bus code generation for ApplicationManager1/ObjectManager1 from ddeintegration CMake, removed appmgr sources/headers from dde-integration-dbus and launcher-models targets, and removed the dde-integration-dbus link where no longer needed.
  • Cleaned up unused includes (AppMgr, AppItem, categoryutils, DDBusSender) across models and DesktopIntegration, and adjusted SPDX headers to updated years.
src/ddeintegration/CMakeLists.txt
src/models/CMakeLists.txt
src/ddeintegration/appmgr.cpp
src/ddeintegration/appmgr.h
src/ddeintegration/types/amglobaltypes.h
src/ddeintegration/types/objectmap.h
src/ddeintegration/types/propmap.h
src/ddeintegration/types/qstringmap.h
src/ddeintegration/xml/org.desktopspec.ApplicationManager1.Application.xml
src/ddeintegration/xml/org.desktopspec.ObjectManager1.xml
src/models/appitem.cpp
src/models/appitem.h
desktopintegration.cpp
various source files removing includes

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Comment thread src/models/appsmodel.h Outdated
Comment on lines +50 to +51
static AppsModel instance;
return instance;

Copy link
Copy Markdown
Member

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-393709 branch 3 times, most recently from 603ad16 to 927047b Compare August 7, 2026 06:50
@wjyrich

wjyrich commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

/test github-pr-review-ci

1 similar comment
@wjyrich

wjyrich commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

/test github-pr-review-ci

{
DAppletBridge bridge(QStringLiteral("org.deepin.ds.dde-apps"));
auto applet = bridge.applet();
if (!applet) {

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.

org.deepin.ds.dde-apps 这个 applet,与launchpad的applet加载顺序,能确定么,这里会不会拿不到啊,要不改到init里吧,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

能确定 ,dde-shell是先加载的根节点, launchpad 的节点在dock下面,而dde-apps是是根节点

@18202781743 18202781743 Aug 7, 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.

dde-apps也不是dock的节点,他们是平级的,而且dde-shell加载是一颗颗树加载的,没有进行广度优先加载呀,要是先加载的是dock,这会等到launchpad加载完后再去加载dde-apps的,
现在没问题可能是安装字典排序的吧,先加载的是d,dock的是o开头,
看之后dde-shell支持depends依赖吧,

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: BLumia, 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

1. Replace direct AppMgr/AppItem usage with shared dde-shell application
model
2. Add LauncherItem::load() to bridge with org.deepin.ds.dde-apps applet
3. Refactor AppsModel to adapt source model roles instead of owning
app data
4. Remove direct D-Bus interface generation for ApplicationManager1
5. Fix QML role references from AppItem to AppsModel namespace
6. Set apps applet as data source for DesktopIntegration operations
7. Update QML to use new AppsModel.ddeCategories for category names
8. Fix category sorting signal ordering to avoid duplicate layout
changes

Log: Unified application data source with dde-shell shared model

Influence:
1. Verify launcher still displays all installed applications correctly
2. Test application launch through launcher and dock
3. Test app category browsing and filtering
4. Test sending/removing apps from desktop
5. Test autostart toggle functionality
6. Test disable scale functionality for legacy apps
7. Test search functionality with pinyin, jianpin, and Chinese
8. Test recently installed and frequently used sections
9. Verify icon loading and caching behavior

refactor: 迁移到 dde-shell 共享应用模型

1. 用共享的 dde-shell 应用模型替换直接的 AppMgr/AppItem 使用
2. 添加 LauncherItem::load() 与 org.deepin.ds.dde-apps applet 桥接
3. 重构 AppsModel 适配源模型角色而非拥有应用数据
4. 移除 ApplicationManager1 的直接 D-Bus 接口生成
5. 修复 QML 中角色引用从 AppItem 到 AppsModel 命名空间的变更
6. 设置应用 qml 作为 DesktopIntegration 操作的数据源
7. 更新 QML 使用新的 AppsModel.ddeCategories 获取分类名称
8. 修复分类排序信号顺序避免重复的布局变更

Log: 应用数据源统一为 dde-shell 共享模型

Influence:
1. 验证启动器仍能正确显示所有已安装应用
2. 测试通过启动器和任务栏启动应用
3. 测试应用分类浏览和过滤功能
4. 测试发送/移除应用到桌面
5. 测试开机自启动开关功能
6. 测试旧应用的禁用缩放功能
7. 测试拼音、简拼和中文搜索功能
8. 测试最近安装和常用应用区域
9. 验证图标加载和缓存行为

PMS: TASK-393709
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

★ 总体评分:95分

■ 【总体评价】

代码将应用模型重构为适配器模式并优化了DBus调用逻辑,修复了多处空指针及数组越界崩溃问题
逻辑正确且有效提升了性能与可维护性,因极少量潜在健壮性瑕疵扣5分

■ 【详细分析】

  • 1.语法逻辑(完全正确)✓

qml/windowed/AppListView.qml 中的 scrollToAlphabetCategory 函数修复了直接对可能为空的数组取首字母导致的越界崩溃,增加了 !transliterated || transliterated.length === 0 的前置检查。appmgr.cpp 中的 launchApp 使用 QProcess::start 传递参数列表,避免了命令注入风险。
潜在问题:AppsModel::data 中获取拼音时,若 Dtk::Core::pinyin 返回非空但首元素为空字符串,后续 transliterated.at(0) 虽然安全,但逻辑分支可能产生非预期结果。
建议:保持现有逻辑,当前处理已足够健壮。

  • 2.代码质量(优秀)✓

重构将 AppsModelQStandardItemModel 改为 QAbstractListModel 适配器模式,移除了冗余的 AppItem 类和复杂的 DBus XML 生成代码,大幅降低了维护成本。代码结构清晰,信号槽连接管理规范,在 setSourceModel 中正确断开了旧的连接。
潜在问题:AppMgr::waitForIcon 中的轮询逻辑虽然设置了最大重试次数,但在极端情况下(如大量应用图标缺失)可能导致定时器频繁触发。
建议:可考虑结合文件系统监听(如 QFileSystemWatcher)替代纯定时器轮询,以进一步降低资源消耗。

  • 3.代码性能(高效)✓

适配器模式通过 QPersistentModelIndex 映射源模型数据,避免了数据的深拷贝,显著提升了内存和响应效率。CategorizedSortProxyModel::setCategoryType 优化了信号发射顺序和排序触发逻辑,避免了不必要的重复排序。
潜在问题:AppsModel::mappedRoles 在每次数据变更时都会被调用,内部包含多次 sourceRole 查询和列表去重操作,在高频更新场景下可能产生微小开销。
建议:可缓存角色映射关系,仅在 setSourceModel 时重建缓存。

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

漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个
代码通过参数列表形式调用外部进程 dde-am,杜绝了命令注入风险;DBus 对象路径使用 DUtil::escapeToObjectPath 进行了转义处理,防止了路径遍历或非法路径注入;未发现敏感信息泄露或内存越界风险。

  • 建议:无需额外修复,继续保持安全编码规范。

■ 【改进建议代码示例】

// src/models/appsmodel.cpp
// 优化 mappedRoles 性能,增加缓存机制

// 在 AppsModelPrivate 或 AppsModel 成员中添加缓存
// QHash<QByteArray, int> m_sourceRoleCache;

QList<int> AppsModel::mappedRoles(const QList<int> &sourceRoles) const
{
    if (sourceRoles.isEmpty())
        return {};

    QList<int> result;
    const auto appendIfChanged = [this, &sourceRoles, &result](int targetRole, const QByteArray &sourceName) {
        // 使用缓存替代每次查询
        int role = -1;
        if (m_sourceRoleCache.contains(sourceName)) {
            role = m_sourceRoleCache.value(sourceName);
        } else if (m_sourceModel) {
            role = m_sourceModel->roleNames().key(sourceName, -1);
            // const_cast 用于简化示例,实际应在非 const 方法中更新缓存
            const_cast<AppsModel*>(this)->m_sourceRoleCache.insert(sourceName, role);
        }
        
        if (sourceRoles.contains(role))
            result.append(targetRole);
    };

    appendIfChanged(AppsModel::DesktopIdRole, DesktopIdRoleName);
    appendIfChanged(AppsModel::CategoriesRole, CategoriesRoleName);
    appendIfChanged(AppsModel::DDECategoryRole, DDECategoryRoleName);
    appendIfChanged(AppsModel::IconNameRole, IconNameRoleName);
    appendIfChanged(AppsModel::InstalledTimeRole, InstalledTimeRoleName);
    appendIfChanged(AppsModel::LastLaunchedTimeRole, LastLaunchedTimeRoleName);
    appendIfChanged(AppsModel::LaunchedTimesRole, LaunchedTimesRoleName);
    appendIfChanged(AppsModel::IsAutoStartRole, AutoStartRoleName);
    appendIfChanged(AppsModel::VendorRole, VendorRoleName);
    appendIfChanged(AppsModel::GenericNameRole, GenericNameRoleName);

    int nameRole = -1;
    if (m_sourceRoleCache.contains(NameRoleName)) {
        nameRole = m_sourceRoleCache.value(NameRoleName);
    } else if (m_sourceModel) {
        nameRole = m_sourceModel->roleNames().key(NameRoleName, -1);
        const_cast<AppsModel*>(this)->m_sourceRoleCache.insert(NameRoleName, nameRole);
    }

    if (sourceRoles.contains(nameRole)) {
        result << Qt::DisplayRole << AppsModel::NameRole << AppsModel::TransliteratedRole << AppsModel::AllTransliteratedRole;
    }
    
    QList<int> uniqueRoles;
    for (int role : std::as_const(result)) {
        if (!uniqueRoles.contains(role))
            uniqueRoles.append(role);
    }
    return uniqueRoles;
}

// 在 setSourceModel 中清空缓存
void AppsModel::setSourceModel(QAbstractItemModel *model)
{
    // ... 前置逻辑
    m_sourceRoleCache.clear();
    // ... 后续逻辑
}

@wjyrich

wjyrich commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

/forcemerge

@deepin-bot

deepin-bot Bot commented Aug 11, 2026

Copy link
Copy Markdown

This pr force merged! (status: blocked)

@deepin-bot
deepin-bot Bot merged commit b3d8fbd into linuxdeepin:master Aug 11, 2026
9 checks passed
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.

4 participants