Skip to content

fix: normalize decimal point input#211

Merged
deepin-bot[bot] merged 2 commits into
linuxdeepin:masterfrom
JWWTSL:master
Jul 23, 2026
Merged

fix: normalize decimal point input#211
deepin-bot[bot] merged 2 commits into
linuxdeepin:masterfrom
JWWTSL:master

Conversation

@JWWTSL

@JWWTSL JWWTSL commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

log: 修复小数点输入和粘贴容错异常

pms: bug-361443

Summary by Sourcery

Normalize numeric input by applying decimal point fault tolerance before further processing and improving handling of locale-specific decimal and grouping symbols.

Bug Fixes:

  • Fix incorrect handling of pasted or entered decimals when using non-dot decimal symbols and locale-specific digit grouping.
  • Ensure multiple decimal points in a number are reduced to a single valid decimal point while preserving cursor position.
  • Correct splitting of expressions around arithmetic operators so decimal normalization works reliably across different inputs.
  • Support normalization of full-width Chinese decimal characters to standard decimals in the input field.

@sourcery-ai

sourcery-ai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Normalizes decimal point and digit grouping input more robustly by routing text through pointFaultTolerance, improving handling of locale-specific symbols, multiple decimal points, and various operators, including pasted expressions.

Sequence diagram for decimal and grouping normalization in InputEdit

sequenceDiagram
    participant InputEdit
    participant Settings

    InputEdit->>InputEdit: handleTextChanged text
    InputEdit->>InputEdit: pointFaultTolerance text
    InputEdit->>Settings: Settings::instance
    Settings-->>InputEdit: getSystemDecimalSymbol
    Settings-->>InputEdit: getSystemDigitGroupingSymbol
    InputEdit->>InputEdit: replace locale grouping with groupingPlaceholder
    InputEdit->>InputEdit: replace locale decimal with decimalPlaceholder
    InputEdit->>InputEdit: normalize operators and multiple decimal points
    InputEdit->>InputEdit: restore groupingPlaceholder to grouping symbol
    InputEdit->>InputEdit: restore decimalPlaceholder to decimal symbol
    InputEdit-->>InputEdit: normalizedExpr
Loading

File-Level Changes

Change Details Files
Route input normalization through pointFaultTolerance and enhance its handling of decimal and grouping symbols with placeholder-based conversion.
  • Use pointFaultTolerance when normalizing text in handleTextChanged instead of directly using the raw text.
  • Introduce non-printable placeholder characters for decimal and grouping symbols to avoid collisions during replacement.
  • Add bidirectional conversion of system-specific decimal and digit grouping symbols to a canonical internal representation and back, including Chinese full-stop handling.
  • Normalize any temporary commas back to the system grouping symbol and dots back to the system decimal symbol at the end of processing.
src/widgets/inputedit.cpp
Improve fault tolerance around decimal point usage within expressions, including operator-aware splitting, leading-decimal correction, and multi-decimal sanitization.
  • Expand the regular expression used to split the expression so it covers ASCII operators (+, -, *, /) in addition to the existing symbols.
  • Ensure items starting with a decimal point receive a leading zero and consistently propagate those changes back into the full text.
  • Preserve the rule that a decimal point cannot follow ')' or '%' by removing such points and updating the full expression when modifications occur.
  • When multiple decimal points exist in a number, remove all but the first, restore cursor position, and replace the original segment only when it has changed.
src/widgets/inputedit.cpp
Minor cleanup of InputEdit implementation.
  • Remove an obsolete trailing blank line at the end of the file.
src/widgets/inputedit.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

@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.

Hey - I've reviewed your changes and they look great!


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.

@JWWTSL
JWWTSL force-pushed the master branch 2 times, most recently from e4fbe95 to 78e150e Compare July 23, 2026 08:51
log: 修复小数点输入和粘贴容错异常

pms: bug-361443
@deepin-ci-robot

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

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

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

@deepin-ci-robot

Copy link
Copy Markdown
Contributor

deepin pr auto review

★ 总体评分:92分

■ 【总体评价】

代码重构了小数点容错处理逻辑,修复了字符串替换导致的错乱问题,提升了系统符号兼容性
逻辑正确且修复了潜在缺陷,因代码注释不足及部分细节可优化扣8分

■ 【详细分析】

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

InputEdit::pointFaultTolerance 函数中,重构了多小数点过滤和分隔符重组逻辑。使用 QChar(0x1D)QChar(0x1C) 作为占位符有效避免了原长字符串占位符可能引发的冲突。正则表达式扩展为 "[+-×÷+*/()\\-]",覆盖了更多运算符,提升了拆分准确性。通过 separators 列表按顺序拼接字符串,替代了原有的 oldText.replace(list[i], item),彻底解决了因重复子串导致的错误替换问题。
潜在问题:若输入文本中本身包含 QChar(0x1D)QChar(0x1C),可能导致后续还原逻辑异常,但在计算器场景下概率极低。
建议:确保输入框限制不可见控制字符的输入,或在处理前过滤掉这些特殊字符。

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

代码结构清晰,变量命名合理,如 decimalPlaceholdergroupingPlaceholder。重构后的 for 循环逻辑层次分明,条件判断更加紧凑。去除了 cursorPosition() 的调用,使该纯函数不再产生副作用,职责更加单一。
潜在问题:关键逻辑处缺乏详细注释,如多小数点处理后的 insert 操作和占位符转换顺序,对新维护者不友好。
建议:在复杂的 if-else 分支和占位符替换逻辑处补充注释,说明算法意图。

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

函数内部主要涉及字符串替换、正则匹配和列表遍历,时间复杂度为 O(N)。对于计算器输入框的文本长度而言,性能开销可忽略不计。
潜在问题:无
建议:无

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

漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个
代码仅处理本地字符串的解析与重组,不涉及外部命令执行、数据库查询或文件路径操作,不存在注入风险。正则表达式为静态常量,不会引发 ReDoS。

  • 建议:无

■ 【改进建议代码示例】

QString InputEdit::pointFaultTolerance(const QString &text)
{
    const auto sys = Settings::instance();
    QString decSym = sys->getSystemDecimalSymbol();
    QString grpSym = sys->getSystemDigitGroupingSymbol();
    // 使用不可见控制字符作为占位符,避免与用户输入冲突
    const QString decimalPlaceholder = QString(QChar(0x1D));
    const QString groupingPlaceholder = QString(QChar(0x1C));

    QString workingText = text;
    // 统一系统符号为内部处理格式
    if (!grpSym.isEmpty() && grpSym != QLatin1String(","))
        workingText.replace(grpSym, groupingPlaceholder);
    if (!decSym.isEmpty() && decSym != QLatin1String("."))
        workingText.replace(decSym, decimalPlaceholder);
    workingText.replace(groupingPlaceholder, ",");
    workingText.replace(decimalPlaceholder, ".");
    // 兼容全角小数点
    workingText.replace(QString::fromUtf8(""), ".");

    QString exp = workingText;
    const QRegularExpression separatorExpression("[+-×÷+*/()\\-]");
    QStringList list = exp.split(separatorExpression);
    QStringList separators;
    QRegularExpressionMatchIterator matches = separatorExpression.globalMatch(exp);
    while (matches.hasNext())
        separators.append(matches.next().captured());

    QString oldText;
    // 逐段处理数字部分,并按原顺序拼接运算符
    for (int i = 0; i < list.size(); ++i) {
        QString item = list[i];
        int firstPoint = item.indexOf(".");
        if (firstPoint != -1) {
            // 处理小数点在首位的情况,补0
            if (firstPoint == 0) {
                item.insert(firstPoint, "0");
                ++firstPoint;
            } 
            // 处理右括号或百分号后跟小数点的情况,移除小数点
            else if (item.at(firstPoint - 1) == QChar(')') || item.at(firstPoint - 1) == QChar('%')) {
                item.remove(firstPoint, 1);
            }
            // 多小数点只保留第一个
            if (item.count(".") > 1) { 
                item.remove(".");
                item.insert(firstPoint, ".");
            }
        }
        oldText.append(item);
        // 追加对应的运算符
        if (i < separators.size())
            oldText.append(separators[i]);
    }

    // 将内部格式还原为系统显示格式
    QString result = oldText;
    if (!grpSym.isEmpty() && grpSym != QLatin1String(","))
        result.replace(",", groupingPlaceholder);
    if (!decSym.isEmpty() && decSym != QLatin1String(".")) {
        result.replace(".", decimalPlaceholder);
    }
    if (!grpSym.isEmpty() && grpSym != QLatin1String(","))
        result.replace(groupingPlaceholder, grpSym);
    if (!decSym.isEmpty() && decSym != QLatin1String("."))
        result.replace(decimalPlaceholder, decSym);
        
    return result;
}

@JWWTSL

JWWTSL commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

/forcemerge

@deepin-bot
deepin-bot Bot merged commit 8742cab into linuxdeepin:master Jul 23, 2026
20 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.

3 participants