Skip to content

fix: update trash icon dynamically based on trash state - #1701

Open
wjyrich wants to merge 1 commit into
linuxdeepin:masterfrom
wjyrich:fix-bug-285725
Open

fix: update trash icon dynamically based on trash state#1701
wjyrich wants to merge 1 commit into
linuxdeepin:masterfrom
wjyrich:fix-bug-285725

Conversation

@wjyrich

@wjyrich wjyrich commented Aug 14, 2026

Copy link
Copy Markdown
Contributor
  1. Add TrashMonitor class that uses GIO to monitor trash directory changes
  2. Connect trash monitor signals to update trash app icon in real-time
  3. Switch icon between "user-trash" and "user-trash-full" based on trash emptiness
  4. Handle dataChanged signal to refresh icon when app item properties change
  5. Add GLIB2/GIO dependency and Qt Concurrent library to build configuration

Log: Trash icon now updates dynamically when trash is emptied or filled

Influence:

  1. Test trash icon displays correctly when trash is empty (user-trash icon)
  2. Delete a file and verify icon changes to full state (user-trash- full icon)
  3. Empty the trash and verify icon changes back to empty state
  4. Test multiple files being deleted simultaneously
  5. Verify trash icon updates when files are restored from trash
  6. Test with slow file systems to ensure no UI lag during updates
  7. Verify no memory leaks during extended monitoring

fix: 根据回收站状态动态更新回收站图标

  1. 添加 TrashMonitor 类,使用 GIO 监控回收站目录变化
  2. 连接回收站监控信号,实时更新回收站应用图标
  3. 根据回收站是否为空在 "user-trash" 和 "user-trash-full" 图标间切换
  4. 处理 dataChanged 信号,在应用项属性变化时刷新图标
  5. 在构建配置中添加 GLIB2/GIO 依赖和 Qt Concurrent 库

Log: 回收站图标会随回收站清空或填充状态动态更新

Influence:

  1. 测试回收站为空时图标显示正常(user-trash 图标)
  2. 删除文件后验证图标是否变为满状态(user-trash-full 图标)
  3. 清空回收站后验证图标是否恢复为空状态
  4. 测试同时删除多个文件的情况
  5. 验证从回收站恢复文件后图标是否正确更新
  6. 在慢速文件系统上测试,确保更新过程中无 UI 卡顿
  7. 验证长时间监控过程中无内存泄漏

PMS: BUG-285725

Summary by Sourcery

Monitor the system trash directory and update the trash app icon in the apps applet according to whether the trash is empty or contains items.

New Features:

  • Add a TrashMonitor component that tracks trash:/// changes via GIO and exposes an emptiness state signal.
  • Update AMAppItemModel to adjust the dde-trash app icon between empty and full variants based on the monitored trash state in real time.

Enhancements:

  • Ensure the trash icon is initialized correctly once application items are loaded and refreshed when item data changes affect the trash entry.

Build:

  • Add GLIB2/GIO and Qt Concurrent as required dependencies and link them into the dde-apps module.

1. Add TrashMonitor class that uses GIO to monitor trash directory
changes
2. Connect trash monitor signals to update trash app icon in real-time
3. Switch icon between "user-trash" and "user-trash-full" based on trash
emptiness
4. Handle dataChanged signal to refresh icon when app item properties
change
5. Add GLIB2/GIO dependency and Qt Concurrent library to build
configuration

Log: Trash icon now updates dynamically when trash is emptied or filled

Influence:
1. Test trash icon displays correctly when trash is empty (user-trash
icon)
2. Delete a file and verify icon changes to full state (user-trash-
full icon)
3. Empty the trash and verify icon changes back to empty state
4. Test multiple files being deleted simultaneously
5. Verify trash icon updates when files are restored from trash
6. Test with slow file systems to ensure no UI lag during updates
7. Verify no memory leaks during extended monitoring

fix: 根据回收站状态动态更新回收站图标

1. 添加 TrashMonitor 类,使用 GIO 监控回收站目录变化
2. 连接回收站监控信号,实时更新回收站应用图标
3. 根据回收站是否为空在 "user-trash" 和 "user-trash-full" 图标间切换
4. 处理 dataChanged 信号,在应用项属性变化时刷新图标
5. 在构建配置中添加 GLIB2/GIO 依赖和 Qt Concurrent 库

Log: 回收站图标会随回收站清空或填充状态动态更新

Influence:
1. 测试回收站为空时图标显示正常(user-trash 图标)
2. 删除文件后验证图标是否变为满状态(user-trash-full 图标)
3. 清空回收站后验证图标是否恢复为空状态
4. 测试同时删除多个文件的情况
5. 验证从回收站恢复文件后图标是否正确更新
6. 在慢速文件系统上测试,确保更新过程中无 UI 卡顿
7. 验证长时间监控过程中无内存泄漏

PMS: BUG-285725

@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

@sourcery-ai

sourcery-ai Bot commented Aug 14, 2026

Copy link
Copy Markdown

Reviewer's Guide

This PR introduces a GIO-based TrashMonitor that tracks trash:/// item count and wires it into AMAppItemModel so the launcher’s trash app icon switches between "user-trash" and "user-trash-full" in real time based on trash emptiness, with build configuration updated to include GLIB2/GIO and Qt Concurrent dependencies.

Sequence diagram for dynamic trash icon updates

sequenceDiagram
    participant GIO
    participant TrashMonitor
    participant AMAppItemModel
    participant AMAppItem

    GIO->>TrashMonitor: onTrashChanged(eventType)
    TrashMonitor->>TrashMonitor: updateState()
    TrashMonitor-->>AMAppItemModel: emptyChanged(empty)
    AMAppItemModel->>AMAppItemModel: updateTrashIcon()
    AMAppItemModel->>AMAppItem: setAppIconName(iconName)
Loading

File-Level Changes

Change Details Files
Integrate trash state awareness into AMAppItemModel so the trash app icon updates automatically when trash contents or app item properties change.
  • Instantiate a TrashMonitor in AMAppItemModel and store it as a member pointer.
  • Invoke updateTrashIcon when new app items are appended and after the initial app list is populated.
  • Connect TrashMonitor::emptyChanged to AMAppItemModel::updateTrashIcon for real-time icon updates.
  • Add a dataChanged handler that locates the "dde-trash" item and triggers updateTrashIcon when its icon-related data changes.
  • Implement updateTrashIcon to query trash emptiness via TrashMonitor and set appIconName to either "user-trash" or "user-trash-full" only when a change is needed.
applets/dde-apps/amappitemmodel.cpp
applets/dde-apps/amappitemmodel.h
Add a TrashMonitor helper class that uses GLib/GIO to monitor the trash:/// URI and emit a Qt signal when its emptiness state changes.
  • Create the TrashMonitor QObject class with an emptyChanged(bool) signal and an isEmpty() accessor.
  • Initialize a GFile for "trash:///" and call updateState in the constructor to establish initial state.
  • Set up a GFileMonitor via g_file_monitor_file and connect its "changed" signal to a static callback.
  • Implement updateState to query G_FILE_ATTRIBUTE_TRASH_ITEM_COUNT, derive emptiness, and emit emptyChanged when the state flips.
  • Implement the onTrashChanged static callback to filter relevant GFileMonitorEvent values and call updateState.
  • Ensure proper cleanup of GFile and GFileMonitor in the TrashMonitor destructor.
applets/dde-apps/trashmonitor.cpp
applets/dde-apps/trashmonitor.h
Update build configuration and licensing metadata to support the new trash monitoring functionality.
  • Add GLIB2 with GIO component to the dde-apps CMake configuration and link against GLIB2::GIO.
  • Link Qt Concurrent (Qt::Concurrent) in target_link_libraries for dde-apps.
  • Include trashmonitor.cpp and trashmonitor.h in the dde-apps library sources.
  • Adjust SPDX-FileCopyrightText year range in AMAppItemModel header to cover 2024–2026 and declare the TrashMonitor forward class declaration.
applets/dde-apps/CMakeLists.txt
applets/dde-apps/amappitemmodel.h

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

@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

★ 总体评分:85分

■ 【总体评价】

代码实现了基于GLib GIO的回收站状态动态监测与图标联动更新功能,整体架构合理且无安全风险
逻辑正确但因dataChanged信号处理中存在不必要的O(N)遍历性能问题扣15分

■ 【详细分析】

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

代码在TrashMonitor构造函数中正确初始化GFile对象并调用updateState,析构函数中使用g_object_unref安全释放了GFile与GFileMonitor资源,避免了内存泄漏。onTrashChanged静态回调函数通过static_cast正确转换userData指针并调用成员函数。AMAppItemModel中通过appItem获取指针后进行了严格的空指针校验,match返回无效索引时也能被isValid()正确拦截。

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

代码遵循了Qt与C++的编码规范,使用Q_LOGGING_CATEGORY进行日志分类管理。通过#undef signals与#define signals Q_SIGNALS巧妙解决了Qt与GLib的signals宏冲突问题。updateTrashIcon内部通过比较iconName避免了无意义的属性重复设置与信号触发,逻辑严密。
潜在问题:amappitemmodel.cpp第83-85行存在多余空行
建议:删除多余空行保持代码整洁

  • 3.代码性能(存在性能问题)✕

在amappitemmodel.cpp中连接QAbstractItemModel::dataChanged信号的lambda表达式内,每次任何应用的数据发生改变都会无条件执行match函数。match函数的时间复杂度为O(N),当系统内安装大量应用且频繁发生数据变更时,会产生不必要的全量模型遍历开销。
潜在问题:高频触发的dataChanged信号导致O(N)复杂度的match函数被频繁调用,造成CPU资源浪费
建议:引入行号缓存机制,在lambda中优先通过缓存的行号与topLeft、bottomRight进行O(1)的范围比较,仅在缓存失效或范围命中时才执行match查找

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

漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个
代码未涉及外部不可信输入处理,监听的trash:///为系统固定安全URI。GError错误对象通过g_clear_error正确清理,未发现命令注入、路径遍历或内存越界等安全风险。

■ 【改进建议代码示例】

// amappitemmodel.h
namespace apps
{
class AMAppItem;
class TrashMonitor;
class AMAppItemModel : public AppItemModel
{
    Q_OBJECT
    // ... 其他代码
private:
    void updateTrashIcon();

    bool m_ready;
    ObjectManager *m_manager;
    TrashMonitor *m_trashMonitor;
    int m_trashRow = -1; // 新增:缓存回收站行号
};
}
// amappitemmodel.cpp
AMAppItemModel::AMAppItemModel(QObject *parent)
    : AppItemModel(parent)
    , m_manager(new ObjectManager("org.desktopspec.ApplicationManager1", "/org/desktopspec/ApplicationManager1", QDBusConnection::sessionBus(), this))
    , m_trashMonitor(new TrashMonitor(this))
    , m_ready(false)
    , m_trashRow(-1)
{
    // ... 其他初始化代码
    
    connect(m_trashMonitor, &TrashMonitor::emptyChanged, this, &AMAppItemModel::updateTrashIcon);
    connect(this, &QAbstractItemModel::dataChanged, this,
            [this](const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList<int> &roles) {
        // O(1) 范围预判,避免每次 dataChanged 都执行 O(N) 的 match
        if (m_trashRow >= 0 && (m_trashRow < topLeft.row() || m_trashRow > bottomRight.row()))
            return;
            
        const auto trashIndex = match(index(0, 0), AppItemModel::DesktopIdRole,
                                      QStringLiteral("dde-trash"), 1, Qt::MatchExactly).value(0);
        if (trashIndex.isValid()) {
            m_trashRow = trashIndex.row(); // 更新缓存
            if (m_trashRow >= topLeft.row() && m_trashRow <= bottomRight.row()
                && (roles.isEmpty() || roles.contains(AppItemModel::IconNameRole))) {
                updateTrashIcon();
            }
        } else {
            m_trashRow = -1; // 缓存失效重置
        }
    });
    
    // ... 其他代码
}

void AMAppItemModel::updateTrashIcon()
{
    auto *trash = appItem(QStringLiteral("dde-trash"));
    if (!trash) {
        m_trashRow = -1;
        return;
    }

    const QString iconName = m_trashMonitor->isEmpty()
            ? QStringLiteral("user-trash")
            : QStringLiteral("user-trash-full");
    if (trash->appIconName() != iconName)
        trash->setAppIconName(iconName);
        
    // 同步更新缓存行号
    m_trashRow = trash->index().row();
}

@BLumia BLumia left a comment

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.

如果 #1700 对应的问题得到解决后,是不是可以用这套 dconfig 的方案?这样的话我们就不再需要针对性处理了。

@18202781743

Copy link
Copy Markdown
Contributor

如果 #1700 对应的问题得到解决后,是不是可以用这套 dconfig 的方案?这样的话我们就不再需要针对性处理了。

让文管改一下,更新那个Icon么?

@BLumia

BLumia commented Aug 14, 2026

Copy link
Copy Markdown
Member

如果 #1700 对应的问题得到解决后,是不是可以用这套 dconfig 的方案?这样的话我们就不再需要针对性处理了。

让文管改一下,更新那个Icon么?

对,或者即便是我们也就都可以走同一套方案,不用在 amappitemmodel 里特判了。

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