Skip to content

fix(editor): make tabbar and bottombar follow system font changes#446

Merged
deepin-bot[bot] merged 1 commit intolinuxdeepin:masterfrom
pengfeixx:fix/font-change-follow-system
Apr 22, 2026
Merged

fix(editor): make tabbar and bottombar follow system font changes#446
deepin-bot[bot] merged 1 commit intolinuxdeepin:masterfrom
pengfeixx:fix/font-change-follow-system

Conversation

@pengfeixx
Copy link
Copy Markdown
Contributor

@pengfeixx pengfeixx commented Apr 22, 2026

In Qt6, DDropdownMenu's eventFilter returned true for ApplicationFontChange, blocking the event filter chain and preventing Tabbar/BottomBar from receiving the event.

Fix by returning false instead, and adding ApplicationFontChange handling in Tabbar and BottomBar via qApp eventFilter.

Qt6下DDropdownMenu的eventFilter对ApplicationFontChange事件 返回true阻断了事件过滤器链,导致Tabbar和BottomBar无法接收
字体变化事件。修复为返回false,并在Tabbar和BottomBar中添加
ApplicationFontChange事件处理。

Log: 修复标签栏和底部工具栏不跟随系统字体变化的问题
PMS: BUG-358185
Influence: 标签栏文字、底部工具栏文字及下拉菜单文字现在能正确跟随系统字体变化,Qt5行为不受影响。

Summary by Sourcery

Ensure Tabbar, BottomBar, and dropdown menus respond correctly to system font change events, particularly under Qt6.

Bug Fixes:

  • Fix Tabbar text not updating when the system application font changes in Qt6.
  • Fix BottomBar labels not updating to follow system font changes in Qt6.
  • Fix dropdown menu button text not following application font changes due to event filtering issues in Qt6.

Enhancements:

  • Align font handling logic across Tabbar, BottomBar, and dropdown menu so Qt5 behavior remains unchanged while Qt6 correctly uses the application font.

@pengfeixx pengfeixx force-pushed the fix/font-change-follow-system branch from 78ba578 to 5fde7c1 Compare April 22, 2026 01:39
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Apr 22, 2026

Reviewer's Guide

Qt6-specific fix to ensure Tabbar, BottomBar, and DDropdownMenu respond correctly to application font changes by adjusting eventFilter behavior and explicitly updating widget fonts, while keeping Qt5 behavior unchanged.

Sequence diagram for ApplicationFontChange propagation with updated eventFilter behavior

sequenceDiagram
    actor User
    participant SystemSettings
    participant QtApp as qApp
    participant DDropdownMenu
    participant Tabbar
    participant BottomBar

    User->>SystemSettings: Change system font
    SystemSettings->>QtApp: Emit ApplicationFontChange

    QtApp->>DDropdownMenu: eventFilter(ApplicationFontChange)
    activate DDropdownMenu
    DDropdownMenu->>DDropdownMenu: OnFontChangedSlot(qApp.font())
    DDropdownMenu->>DDropdownMenu: m_pToolButton.setFont(m_font)
    DDropdownMenu->>DDropdownMenu: m_pToolButton.setIcon(createIcon())
    DDropdownMenu-->>QtApp: return false (do not block chain)
    deactivate DDropdownMenu

    QtApp->>Tabbar: eventFilter(ApplicationFontChange)
    activate Tabbar
    Tabbar->>Tabbar: setFont(qApp.font())
    Tabbar-->>QtApp: return false
    deactivate Tabbar

    QtApp->>BottomBar: eventFilter(ApplicationFontChange)
    activate BottomBar
    BottomBar->>BottomBar: m_pPositionLabel.setFont(qApp.font())
    BottomBar->>BottomBar: m_pCharCountLabel.setFont(qApp.font())
    BottomBar->>BottomBar: m_pCursorStatus.setFont(qApp.font())
    BottomBar->>BottomBar: m_scaleLabel.setFont(qApp.font())
    BottomBar->>BottomBar: m_progressLabel.setFont(qApp.font())
    BottomBar-->>QtApp: return false
    deactivate BottomBar
Loading

Updated class diagram for Tabbar, BottomBar, and DDropdownMenu font change handling

classDiagram
    class QWidget

    class BottomBar {
        +BottomBar(QWidget *parent)
        +DDropdownMenu *getHighlightMenu()
        +void paintEvent(QPaintEvent *event)
        +bool eventFilter(QObject *object, QEvent *event)
        -void initFormatMenu()
        -QLabel *m_pPositionLabel
        -QLabel *m_pCharCountLabel
        -QLabel *m_pCursorStatus
        -QLabel *m_scaleLabel
        -QLabel *m_progressLabel
        -DDropdownMenu *m_pHighlightMenu
    }

    class Tabbar {
        +Tabbar(QWidget *parent)
        +bool eventFilter(QObject *object, QEvent *event)
        +void handleDragActionChanged(Qt::DropAction action)
    }

    class DDropdownMenu {
        +bool eventFilter(QObject *object, QEvent *event)
        +void OnFontChangedSlot(const QFont &font)
        -QFont m_font
        -QToolButton *m_pToolButton
    }

    BottomBar --|> QWidget
    Tabbar --|> QWidget

    BottomBar --> DDropdownMenu
    DDropdownMenu --> QWidget
Loading

File-Level Changes

Change Details Files
Wire BottomBar into the global application event filter and update its labels when the application font changes in Qt6.
  • Install the BottomBar instance as a QApplication-level event filter for Qt6 builds.
  • Implement BottomBar::eventFilter to handle QEvent::ApplicationFontChange by applying qApp->font() to all relevant labels and status widgets, then allow the event filter chain to continue.
  • Fallback to QWidget::eventFilter for all other events.
src/widgets/bottombar.cpp
src/widgets/bottombar.h
Extend Tabbar event filtering so it also receives application-level font change events in Qt6 and updates its font accordingly.
  • Install the Tabbar instance as a QApplication-level event filter for Qt6 builds in addition to its existing local eventFilter installation.
  • In Tabbar::eventFilter, handle QEvent::ApplicationFontChange by calling setFont(qApp->font()) and returning false to not consume the event.
  • Preserve existing mouse and drag related eventFilter logic after the new ApplicationFontChange handling.
src/controls/tabbar.cpp
Adjust DDropdownMenu font change handling so it no longer blocks ApplicationFontChange propagation and better separates Qt5/Qt6 font sizing behavior.
  • In OnFontChangedSlot, wrap the pixel-size adjustment in a Qt < 6 conditional and always apply the updated font to the tool button before recreating the icon.
  • Change DDropdownMenu::eventFilter so that on QEvent::ApplicationFontChange it updates its font via OnFontChangedSlot but returns false to keep the event filter chain intact instead of consuming the event.
src/widgets/ddropdownmenu.cpp

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

@pengfeixx pengfeixx force-pushed the fix/font-change-follow-system branch from 5fde7c1 to 135dda9 Compare April 22, 2026 01:42
Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 2 issues, and left some high level feedback:

  • In BottomBar::eventFilter you ignore the watched object and call QWidget::eventFilter(nullptr, event); it would be safer to keep the QObject * parameter (e.g., as watched) and forward it to the base implementation instead of passing nullptr.
  • Tabbar::eventFilter is now being used as a global application event filter, so the unconditional qDebug() << "Enter eventFilter"; will generate a lot of noisy logging; consider removing or guarding it.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In BottomBar::eventFilter you ignore the watched object and call QWidget::eventFilter(nullptr, event); it would be safer to keep the QObject * parameter (e.g., as `watched`) and forward it to the base implementation instead of passing nullptr.
- Tabbar::eventFilter is now being used as a global application event filter, so the unconditional `qDebug() << "Enter eventFilter";` will generate a lot of noisy logging; consider removing or guarding it.

## Individual Comments

### Comment 1
<location path="src/widgets/bottombar.cpp" line_range="288-297" />
<code_context>
     return m_pHighlightMenu;
 }

+bool BottomBar::eventFilter(QObject *, QEvent *event)
+{
+#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
+    if (event->type() == QEvent::ApplicationFontChange) {
+        QFont font = qApp->font();
+        m_pPositionLabel->setFont(font);
+        m_pCharCountLabel->setFont(font);
+        m_pCursorStatus->setFont(font);
+        m_scaleLabel->setFont(font);
+        m_progressLabel->setFont(font);
+        return false;
+    }
+#endif
+    return QWidget::eventFilter(nullptr, event);
+}
+
</code_context>
<issue_to_address>
**issue (bug_risk):** Forward the watched object to the base implementation instead of passing nullptr, and consider using QObject::eventFilter as the base.

Passing nullptr to `QWidget::eventFilter` drops the `watched` object, which can break base-class assumptions and cause subtle bugs. Please change the signature to `bool BottomBar::eventFilter(QObject *watched, QEvent *event)` and call `return QWidget::eventFilter(watched, event);` (or `QObject::eventFilter(watched, event)`), so the event chain keeps the correct context.
</issue_to_address>

### Comment 2
<location path="src/controls/tabbar.cpp" line_range="62-63" />
<code_context>

     installEventFilter(this);

+#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
+    qApp->installEventFilter(this);
+#endif
+
</code_context>
<issue_to_address>
**suggestion (performance):** Installing an application-wide event filter on Tabbar may cause excessive event traffic and noisy logging.

With `qApp->installEventFilter(this);`, `Tabbar` now sees every application event in addition to its own (you already call `installEventFilter(this);`). Combined with `qDebug() << "Enter eventFilter";`, this will produce very noisy logs and extra overhead. Please either narrow the event filter to specific objects or remove/guard this generic debug log for Qt 6 builds.

Suggested implementation:

```cpp
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) && defined(QT_DEBUG)
    // In Qt 6, only install an application-wide event filter in debug builds
    // to avoid excessive event traffic and noisy logging in production.
    qApp->installEventFilter(this);
#endif

```

To fully implement the review comment, you should also:
1. Locate the `eventFilter` implementation in `src/controls/tabbar.cpp` (or its corresponding header/source).
2. Wrap the generic logging line `qDebug() << "Enter eventFilter";` with a debug-only guard, e.g.:
   ```cpp
   #if defined(QT_DEBUG)
       qDebug() << "Enter eventFilter";
   #endif
   ```
   or remove it entirely if it is no longer useful.
This will ensure that even in debug builds, the extra logging is controlled, and in release builds there is no unnecessary overhead or log noise.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/widgets/bottombar.cpp Outdated
Comment on lines +288 to +297
bool BottomBar::eventFilter(QObject *, QEvent *event)
{
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
if (event->type() == QEvent::ApplicationFontChange) {
QFont font = qApp->font();
m_pPositionLabel->setFont(font);
m_pCharCountLabel->setFont(font);
m_pCursorStatus->setFont(font);
m_scaleLabel->setFont(font);
m_progressLabel->setFont(font);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): Forward the watched object to the base implementation instead of passing nullptr, and consider using QObject::eventFilter as the base.

Passing nullptr to QWidget::eventFilter drops the watched object, which can break base-class assumptions and cause subtle bugs. Please change the signature to bool BottomBar::eventFilter(QObject *watched, QEvent *event) and call return QWidget::eventFilter(watched, event); (or QObject::eventFilter(watched, event)), so the event chain keeps the correct context.

Comment thread src/controls/tabbar.cpp
Comment on lines +62 to +63
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
qApp->installEventFilter(this);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (performance): Installing an application-wide event filter on Tabbar may cause excessive event traffic and noisy logging.

With qApp->installEventFilter(this);, Tabbar now sees every application event in addition to its own (you already call installEventFilter(this);). Combined with qDebug() << "Enter eventFilter";, this will produce very noisy logs and extra overhead. Please either narrow the event filter to specific objects or remove/guard this generic debug log for Qt 6 builds.

Suggested implementation:

#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) && defined(QT_DEBUG)
    // In Qt 6, only install an application-wide event filter in debug builds
    // to avoid excessive event traffic and noisy logging in production.
    qApp->installEventFilter(this);
#endif

To fully implement the review comment, you should also:

  1. Locate the eventFilter implementation in src/controls/tabbar.cpp (or its corresponding header/source).
  2. Wrap the generic logging line qDebug() << "Enter eventFilter"; with a debug-only guard, e.g.:
    #if defined(QT_DEBUG)
        qDebug() << "Enter eventFilter";
    #endif
    or remove it entirely if it is no longer useful.
    This will ensure that even in debug builds, the extra logging is controlled, and in release builds there is no unnecessary overhead or log noise.

@pengfeixx pengfeixx force-pushed the fix/font-change-follow-system branch 2 times, most recently from b63feba to 4956ada Compare April 22, 2026 01:57
In Qt6, DDropdownMenu's eventFilter returned true for
ApplicationFontChange, blocking the event filter chain and
preventing Tabbar/BottomBar from receiving the event.

Fix by returning false instead, and adding ApplicationFontChange
handling in Tabbar and BottomBar via qApp eventFilter.

Qt6下DDropdownMenu的eventFilter对ApplicationFontChange事件
返回true阻断了事件过滤器链,导致Tabbar和BottomBar无法接收
字体变化事件。修复为返回false,并在Tabbar和BottomBar中添加
ApplicationFontChange事件处理。

Log: 修复标签栏和底部工具栏不跟随系统字体变化的问题
PMS: BUG-358185
Influence: 标签栏文字、底部工具栏文字及下拉菜单文字现在能正确跟随系统字体变化,Qt5行为不受影响。
@pengfeixx pengfeixx force-pushed the fix/font-change-follow-system branch from 4956ada to 5771462 Compare April 22, 2026 02:00
@deepin-ci-robot
Copy link
Copy Markdown

deepin pr auto review

经过对提供的 Git diff 代码的审查,我发现这段代码主要目的是为了适配 Qt6,特别是针对字体变化事件(ApplicationFontChange)的处理。以下是对代码的语法逻辑、代码质量、代码性能和代码安全的详细审查及改进意见:

1. 语法逻辑审查

优点:

  • 版本宏使用正确:正确使用了 QT_VERSION_CHECK 宏来区分 Qt5 和 Qt6 的代码逻辑,这是处理跨版本兼容性的标准做法。
  • 事件过滤逻辑基本正确:在 eventFilter 中检查 QEvent::ApplicationFontChange 并更新字体,逻辑上符合需求。
  • 版权年份更新:将版权年份从 2023 更新至 2026,符合常规维护流程。

问题与改进建议:

  1. Tabbar.cpp 中事件过滤器的安装与移除(内存安全风险)

    • 问题:在 Tabbar 构造函数中调用了 qApp->installEventFilter(this)。这意味着 Tabbar 对象将自己安装为了全局应用程序事件过滤器。
    • 风险:如果 Tabbar 对象在 qApp 之前被销毁,或者 Tabbar 被多次创建和销毁而没有正确移除过滤器,会导致悬空指针,进而引发程序崩溃。
    • 改进:必须在 Tabbar 的析构函数中显式调用 qApp->removeEventFilter(this)
  2. BottomBar.cpp 中事件过滤器的安装与移除(内存安全风险)

    • 问题:与 Tabbar 类似,BottomBar 也调用了 qApp->installEventFilter(this),但代码片段中未显示析构函数。
    • 改进:同样必须在 BottomBar 的析构函数中添加 qApp->removeEventFilter(this)
  3. Tabbar.cpp 中移除了调试日志

    • 问题:代码删除了 qDebug() << "Enter eventFilter";
    • 建议:这通常是好的做法(减少发布版噪音),但建议确认该日志是否对调试特定问题至关重要。如果保留,应配合 qCDebug 和分类日志使用。
  4. DDropdownMenu.cpp 中 eventFilter 的返回值

    • 问题:代码将 return true; 修改为了 return false;
    • 分析
      • return true:表示事件已处理,停止传播。
      • return false:表示事件未处理,继续传播给其他过滤器或目标对象。
    • 建议:对于 ApplicationFontChange 这种全局通知事件,通常不需要拦截(即不需要 return true),允许其他组件也接收该事件是合理的。因此,改为 return false 是符合逻辑的改进。

2. 代码质量审查

优点:

  • 代码风格统一,缩进和格式规范。
  • 使用了 C++ 的 override 关键字(在 bottombar.h 中),有助于编译器检查函数签名是否正确。

改进建议:

  1. 重复代码(DRY 原则)

    • 问题:在 BottomBar::eventFilter 中,手动为 5 个不同的 Label 设置字体:
      m_pPositionLabel->setFont(font);
      m_pCharCountLabel->setFont(font);
      // ...
    • 改进:如果这些 Label 都需要统一更新字体,建议将它们存入一个 QList<QLabel*> 成员变量中,在构造函数初始化时加入列表,在 eventFilter 中遍历列表设置字体。这样如果以后增加新的 Label,只需在初始化列表中添加,无需修改 eventFilter 逻辑。
  2. DDropdownMenu.cpp 的逻辑简化

    • 问题:在 OnFontChangedSlot 中,针对 Qt6 移除了 setPixelSize 的逻辑。
    • 疑问:这意味着在 Qt6 下,m_font 将直接使用 qApp->font() 的大小。如果 DDropdownMenu 之前强制使用 T8 字体大小是有意为之(为了保持 UI 一致性),那么在 Qt6 下移除它可能会导致 UI 显示不一致。
    • 建议:确认 Qt6 下是否真的不需要强制设置像素大小。如果需要,请保留或寻找 Qt6 下对应的 DPI 缩放设置方法。

3. 代码性能审查

  • 全局事件过滤器的影响
    • TabbarBottomBar 都安装了全局事件过滤器。eventFilter 会在应用程序的每一个事件分发时被调用。
    • 当前逻辑:代码首先检查 event->type()。这是一个非常快的整数比较操作。
    • 结论:目前的性能开销是可以接受的,因为 type() 检查非常快,且大多数事件会立即返回 false。但应避免在 eventFilter 中进行复杂的计算或创建对象。

4. 代码安全审查

  1. 空指针解引用风险(低)

    • BottomBar::eventFilter 中直接访问了 m_pPositionLabel 等成员指针。虽然这些成员通常在构造函数中初始化,且 eventFilter 发生时对象必然已构造好,但在多线程环境下或复杂的对象生命周期管理中,保持警惕总是好的。
    • 建议:虽然在此场景下不是必须的,但添加断言 Q_ASSERT(m_pPositionLabel != nullptr); 可以在开发阶段捕获潜在的初始化错误。
  2. 类型转换安全

    • Tabbar::eventFilter 中使用了 static_cast<QMouseEvent *>(event)
    • 安全:由于这行代码在 if (event->type() == QEvent::MouseButtonPress) 块内部,类型是确定的,因此 static_cast 是安全且高效的。

总结与修改建议代码

核心修改建议:

  1. 必须:在 TabbarBottomBar 的析构函数中移除事件过滤器。
  2. 建议:优化 BottomBar 中设置字体的循环逻辑。

以下是针对 TabbarBottomBar 的修改建议:

1. src/controls/tabbar.h 和 tabbar.cpp

在头文件中添加析构函数声明(如果没有的话):

~Tabbar() override;

在 cpp 中实现析构函数:

Tabbar::~Tabbar()
{
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
    if (qApp) {
        qApp->removeEventFilter(this);
    }
#endif
}

2. src/widgets/bottombar.h 和 bottombar.cpp

在头文件中添加析构函数声明(如果没有的话):

~BottomBar() override;

在 cpp 中实现析构函数:

BottomBar::~BottomBar()
{
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
    if (qApp) {
        qApp->removeEventFilter(this);
    }
#endif
}

优化 BottomBar::eventFilter(可选,但推荐):
bottombar.h 中添加成员变量:

private:
    QList<QLabel*> m_fontAwareLabels; // 需要跟随系统字体变化的Label列表

bottombar.cpp 构造函数中初始化列表:

BottomBar::BottomBar(QWidget *parent)
    : QWidget(parent)
    , // ... 其他初始化
{
    // ... 原有代码 ...

    // 将需要更新字体的 Label 加入列表
    m_fontAwareLabels << m_pPositionLabel 
                      << m_pCharCountLabel 
                      << m_pCursorStatus 
                      << m_scaleLabel 
                      << m_progressLabel;
                      
    // ...
}

修改 eventFilter

bool BottomBar::eventFilter(QObject *watched, QEvent *event)
{
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
    if (event->type() == QEvent::ApplicationFontChange) {
        QFont font = qApp->font();
        // 使用循环减少重复代码
        for (auto label : m_fontAwareLabels) {
            if (label) {
                label->setFont(font);
            }
        }
        return false;
    }
#endif
    return QWidget::eventFilter(watched, event);
}

@deepin-ci-robot
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: lzwind, pengfeixx

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

@pengfeixx
Copy link
Copy Markdown
Contributor Author

/merge

@deepin-bot deepin-bot Bot merged commit 3ce1324 into linuxdeepin:master Apr 22, 2026
22 checks passed
@pengfeixx pengfeixx deleted the fix/font-change-follow-system branch April 22, 2026 02:37
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