Skip to content

Conversation

@deepin-ci-robot
Copy link
Contributor

@deepin-ci-robot deepin-ci-robot commented Feb 9, 2026

Synchronize source files from linuxdeepin/dde-session-shell.

Source-pull-request: linuxdeepin/dde-session-shell#56

Summary by Sourcery

Enhancements:

  • Render long placeholder text in DLineEditEx as a single line with right-side ellipsis instead of wrapping, and show the full text in a tooltip when it is elided.

Synchronize source files from linuxdeepin/dde-session-shell.

Source-pull-request: linuxdeepin/dde-session-shell#56
@sourcery-ai
Copy link

sourcery-ai bot commented Feb 9, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adjusts DLineEditEx placeholder text rendering to prevent wrapping, add ellipsis when truncated, and show a tooltip with the full placeholder when truncation occurs.

Flow diagram for DLineEditEx::paintEvent placeholder rendering

flowchart TD
    A[paintEvent called] --> B{lineEdit has no text and placeholder is visible}
    B -->|No| Z[Call base QWidget::paintEvent and return]
    B -->|Yes| C[Create QPainter and set pen color]
    C --> D[Create QTextOption]
    D --> E[Set alignment to Qt::AlignCenter]
    E --> F[Set wrap mode to QTextOption::NoWrap]
    F --> G[Create QFontMetrics from painter font]
    G --> H[Get placeholderText from lineEdit]
    H --> I[Compute elidedText using fm.elidedText with Qt::ElideRight and rect width]
    I --> J[Draw text in rect with Qt::AlignCenter and Qt::TextSingleLine using elidedText]
    J --> K{elidedText != placeholderText}
    K -->|Yes| L[setToolTip with full placeholderText]
    K -->|No| M[setToolTip with empty QString]
    L --> N[Call base QWidget::paintEvent]
    M --> N[Call base QWidget::paintEvent]
    N --> O[Return from paintEvent]
Loading

File-Level Changes

Change Details Files
Update placeholder text painting logic to ellide long text and expose full content via tooltip when truncated.
  • Disable text wrapping and enforce single-line placeholder rendering.
  • Compute an elided version of the placeholder text using QFontMetrics with right-side ellipsis based on available width.
  • Draw the placeholder text with explicit alignment and TextSingleLine flag using the elided string.
  • Conditionally set a tooltip to the full placeholder text only when elision occurs, clearing it otherwise.
src/widgets/dlineeditex.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

Copy link

@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 left some high level feedback:

  • Avoid mutating widget state (setting tooltips) inside paintEvent; consider updating the tooltip only when the placeholder text or geometry changes (e.g., in resizeEvent or when the placeholder changes) and caching the elision result to keep paintEvent side-effect free and cheaper.
  • The QTextOption instance is no longer used after switching to drawText with flags, so it can be removed to simplify the paintEvent implementation.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Avoid mutating widget state (setting tooltips) inside paintEvent; consider updating the tooltip only when the placeholder text or geometry changes (e.g., in resizeEvent or when the placeholder changes) and caching the elision result to keep paintEvent side-effect free and cheaper.
- The QTextOption instance is no longer used after switching to drawText with flags, so it can be removed to simplify the paintEvent implementation.

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.

@deepin-ci-robot
Copy link
Contributor Author

deepin pr auto review

这段代码主要针对 DLineEditExpaintEvent 方法进行了改进,目的是优化占位符文本的显示方式,防止文本过长时换行,并增加了 Tooltip 功能。以下是对这段代码的详细审查和改进建议:

1. 语法逻辑审查

  • 整体逻辑正确:代码成功实现了获取字体度量、计算省略文本、绘制文本以及根据是否省略来设置 Tooltip 的逻辑。
  • Qt 绘制标志一致性
    • 代码中显式设置了 option.setWrapMode(QTextOption::NoWrap),但在调用 drawText 时使用了 Qt::TextSingleLine 标志。
    • 建议:既然使用了 Qt::TextSingleLine 标志,QTextOption 中的 NoWrap 设置其实是冗余的(因为 Qt::TextSingleLine 已经隐含了不换行)。虽然保留它没有害处,但为了代码简洁,可以考虑移除 option.setWrapMode(...) 这一行,或者保留 option 并移除 drawText 中的 Qt::TextSingleLine。鉴于 drawText 直接传标志更直观,建议移除 option 相关的换行设置代码。

2. 代码质量审查

  • 可读性:代码结构清晰,注释准确解释了修改的目的。
  • Tooltip 设置逻辑
    • paintEvent 中频繁调用 setToolTip 可能会导致不必要的性能开销或信号触发。
    • 潜在问题:如果 placeholderText 很长但没有被省略(例如宽度刚好够),代码会清空 Tooltip (setToolTip(QString()))。如果用户之前手动设置了 Tooltip,这个操作会意外清除用户的设置。
    • 建议:仅在 Tooltip 内容发生变化时才调用 setToolTip。此外,最好检查一下当前的 Tooltip 是否已经是目标文本,避免重复设置。

3. 代码性能审查

  • QFontMetrics 的创建QFontMetrics fm(pa.font()); 在每次 paintEvent(即重绘)时都会创建。虽然 QFontMetrics 构造开销不大,但在高频重绘场景下(如窗口调整大小、动画),频繁构造对象会有微小损耗。
    • 建议:如果 font() 不经常变化,可以考虑将 QFontMetrics 缓存为类成员变量,或者在字体改变时更新它。不过,考虑到 QLineEdit 的字体可能动态变化,保持现状也是可以接受的,属于微优化。
  • setToolTip 的开销:如前所述,setToolTip 可能会触发事件或重绘。在绘制函数中修改控件属性不是最佳实践。
    • 建议:将 Tooltip 的更新逻辑移出 paintEvent。例如,监听 resizeEvent 或者当 placeholderText 属性改变时去更新 Tooltip。

4. 代码安全审查

  • 空指针检查lineEdit()->placeholderText()。假设 lineEdit() 在这个上下文中总是返回有效的指针(通常在 DLineEditEx 这种封装控件中是成立的),则是安全的。如果 lineEdit() 可能返回空指针,则需要增加判空逻辑。
  • 引用有效性const QString &placeholderText = ... 是安全的,因为 placeholderText() 返回的是 const QString&,生命周期在语句结束前有效。

改进后的代码建议

结合以上分析,建议对代码进行如下调整。为了性能和最佳实践,我们将 Tooltip 的逻辑移出 paintEvent,或者至少在 paintEvent 中增加判断以减少不必要的设置。

方案 A:最小改动(保留在 paintEvent 中,但增加判断)

void DLineEditEx::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    // ... 其他绘制逻辑 ...

    if (!lineEdit()->text().isEmpty()) {
        QWidget::paintEvent(event);
        return;
    }

    QPainter pa(this);
    // ... 设置颜色等 ...

    QTextOption option;
    option.setAlignment(Qt::AlignCenter);
    
    QFontMetrics fm(pa.font());
    const QString &placeholderText = lineEdit()->placeholderText();
    
    // 计算省略文本
    QString elidedText = fm.elidedText(placeholderText, Qt::ElideRight, rect().width());
    
    // 绘制文本:使用 Qt::TextSingleLine 标志即可,不需要 option.setWrapMode
    pa.drawText(rect(), Qt::AlignCenter | Qt::TextSingleLine, elidedText);

    // 优化:仅当 Tooltip 内容确实需要改变时才设置
    // 注意:toolTip() 返回的是当前显示的 tooltip,如果用户手动设置了其他 tooltip,这里可能会覆盖
    // 更好的做法是检查是否是因为 placeholder 引起的 tooltip,但这需要额外的成员变量标记
    const QString currentToolTip = toolTip();
    if (elidedText != placeholderText) {
        if (currentToolTip != placeholderText) {
            setToolTip(placeholderText);
        }
    } else {
        // 只有当当前的 tooltip 确实是我们之前设置的 placeholder 时才清空
        // 这里的逻辑比较复杂,简单起见,如果不想覆盖用户设置,可以不做清空操作,或者只在特定条件下清空
        if (currentToolTip == placeholderText) { 
            setToolTip(QString());
        }
    }
    
    QWidget::paintEvent(event);
}

方案 B:最佳实践(将逻辑分离,推荐)

建议在类中增加一个槽函数或私有方法来处理 Tooltip,在 resizeEvent 或设置 placeholderText 时调用,而不是在 paintEvent 中。

// 在头文件中声明
protected:
    void resizeEvent(QResizeEvent *event) override;
    // 如果 placeholderText 是动态设置的,还需要重写相关 set 方法或监听信号
private:
    void updatePlaceholderTooltip();

// 在源文件中实现

void DLineEditEx::updatePlaceholderTooltip()
{
    if (lineEdit()->text().isEmpty()) {
        QFontMetrics fm(font());
        const QString &placeholderText = lineEdit()->placeholderText();
        QString elidedText = fm.elidedText(placeholderText, Qt::ElideRight, width());
        
        if (elidedText != placeholderText) {
            setToolTip(placeholderText);
        } else {
            setToolTip(QString());
        }
    } else {
        // 如果有文本,通常不需要显示 placeholder 的 tooltip
        // 除非你想保留用户手动设置的 tooltip
        if (toolTip() == lineEdit()->placeholderText()) {
             setToolTip(QString());
        }
    }
}

void DLineEditEx::resizeEvent(QResizeEvent *event)
{
    QLineEdit::resizeEvent(event);
    updatePlaceholderTooltip();
}

void DLineEditEx::paintEvent(QPaintEvent *event)
{
    // ... 原有的绘制逻辑 ...
    
    if (!lineEdit()->text().isEmpty()) {
        QWidget::paintEvent(event);
        return;
    }

    QPainter pa(this);
    // ... 设置颜色 ...

    // 简化的绘制逻辑
    QFontMetrics fm(pa.font());
    const QString &placeholderText = lineEdit()->placeholderText();
    QString elidedText = fm.elidedText(placeholderText, Qt::ElideRight, rect().width());
    
    pa.drawText(rect(), Qt::AlignCenter | Qt::TextSingleLine, elidedText);

    QWidget::paintEvent(event);
}

总结

原代码在功能上是可以工作的,但在性能(频繁计算和设置属性)和架构(在绘制函数中处理逻辑)上有改进空间。采用方案 B 将 Tooltip 更新逻辑移至 resizeEvent 是更符合 Qt 事件驱动模型的做法,能避免不必要的重绘和属性设置。

@deepin-ci-robot
Copy link
Contributor Author

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: deepin-ci-robot, yixinshark

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

@yixinshark yixinshark merged commit 8722531 into master Feb 9, 2026
25 of 28 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.

2 participants