Skip to content

fix: 修复 setNewResolutionList 排序不一致导致分辨率索引错位#477

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:release/eaglefrom
Resurgamz:release/eagle
May 28, 2026
Merged

fix: 修复 setNewResolutionList 排序不一致导致分辨率索引错位#477
deepin-bot[bot] merged 1 commit into
linuxdeepin:release/eaglefrom
Resurgamz:release/eagle

Conversation

@Resurgamz
Copy link
Copy Markdown

@Resurgamz Resurgamz commented May 28, 2026

setNewResolutionList 排序条件使用了 <=,相同宽度时无条件交换,
导致排序结果与 settingDialog 不一致。摄像头重连后保存的索引值
在重新打开设置界面时映射到了错误的分辨率(如 640x480 显示为 640x360)。

Log: 修复 setNewResolutionList 排序不一致导致分辨率索引错位
Bug: https://pms.uniontech.com/bug-view-363077.html

Summary by Sourcery

Bug Fixes:

  • Fix resolution sorting comparison so resolutions with the same width are ordered by height, avoiding index mismatches after camera reconnection.

  setNewResolutionList 排序条件使用了 <=,相同宽度时无条件交换,
  导致排序结果与 settingDialog 不一致。摄像头重连后保存的索引值
  在重新打开设置界面时映射到了错误的分辨率(如 640x480 显示为 640x360)。

Log: 修复 setNewResolutionList 排序不一致导致分辨率索引错位
Bug: https://pms.uniontech.com/bug-view-363077.html
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 28, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Refines the sorting logic in Settings::setNewResolutionList so that resolutions are ordered deterministically by width then height, preventing index misalignment between stored resolution indices and the settings dialog.

Flow diagram for updated resolution comparison in Settings::setNewResolutionList

flowchart TD
    A[resolutiontemp1 width < resolutiontemp2 width?] -->|yes| B[Swap resolutions]
    A -->|no| C[resolutiontemp1 width == resolutiontemp2 width?]
    C -->|no| D[Keep order]
    C -->|yes| E[resolutiontemp1 height < resolutiontemp2 height?]
    E -->|yes| B[Swap resolutions]
    E -->|no| D[Keep order]
Loading

File-Level Changes

Change Details Files
Make resolution sorting stable and consistent by sorting first by width, then by height when widths are equal, to match the settings dialog order and avoid index mismatch after camera reconnection.
  • Changed the primary comparison from less-than-or-equal on width to strict less-than on width.
  • Added an explicit tie-breaker condition that, when widths are equal, compares heights using strict less-than.
  • Kept the swap behavior the same so only the comparison logic is modified while the sorting mechanism remains unchanged.
src/src/Settings.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
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 1 issue, and left some high level feedback:

  • The comparison condition inside setNewResolutionList is now quite long and repetitive; consider extracting the width/height parsing into local int width1, height1, width2, height2 variables (or a small helper) to improve readability and avoid multiple toInt() calls on the same values.
  • Given this is performing a sort, it might be clearer and less error-prone to replace the manual swap-and-loop logic with std::sort (or std::stable_sort) using a well-defined comparator that orders by width first, then height.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The comparison condition inside `setNewResolutionList` is now quite long and repetitive; consider extracting the width/height parsing into local `int width1, height1, width2, height2` variables (or a small helper) to improve readability and avoid multiple `toInt()` calls on the same values.
- Given this is performing a sort, it might be clearer and less error-prone to replace the manual swap-and-loop logic with `std::sort` (or `std::stable_sort`) using a well-defined comparator that orders by width first, then height.

## Individual Comments

### Comment 1
<location path="src/src/Settings.cpp" line_range="139-140" />
<code_context>

-                    if ((resolutiontemp1[0].toInt() <= resolutiontemp2[0].toInt())
-                            || (resolutiontemp1[1].toInt() < resolutiontemp2[1].toInt())) {
+                    if ((resolutiontemp1[0].toInt() < resolutiontemp2[0].toInt()) ||
+                            (resolutiontemp1[0].toInt() == resolutiontemp2[0].toInt() && (resolutiontemp1[1].toInt() < resolutiontemp2[1].toInt()))) {
                         QString resolutionstr = resolutionDatabase[j + 1];
                         resolutionDatabase[j + 1] = resolutionDatabase[j];
</code_context>
<issue_to_address>
**suggestion:** Avoid repeated toInt() calls and simplify the comparison expression.

Extract the int values before the condition and compare those instead:

```cpp
int w1 = resolutiontemp1[0].toInt();
int h1 = resolutiontemp1[1].toInt();
int w2 = resolutiontemp2[0].toInt();
int h2 = resolutiontemp2[1].toInt();

if (w1 < w2 || (w1 == w2 && h1 < h2)) {
    ...
}
```
This avoids repeated conversions inside the loop and makes the sort logic easier to follow.
</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/src/Settings.cpp
Comment on lines +139 to +140
if ((resolutiontemp1[0].toInt() < resolutiontemp2[0].toInt()) ||
(resolutiontemp1[0].toInt() == resolutiontemp2[0].toInt() && (resolutiontemp1[1].toInt() < resolutiontemp2[1].toInt()))) {
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: Avoid repeated toInt() calls and simplify the comparison expression.

Extract the int values before the condition and compare those instead:

int w1 = resolutiontemp1[0].toInt();
int h1 = resolutiontemp1[1].toInt();
int w2 = resolutiontemp2[0].toInt();
int h2 = resolutiontemp2[1].toInt();

if (w1 < w2 || (w1 == w2 && h1 < h2)) {
    ...
}

This avoids repeated conversions inside the loop and makes the sort logic easier to follow.

@deepin-ci-robot
Copy link
Copy Markdown

deepin pr auto review

你好!我是CodeGeeX。我已仔细审查了你提供的Git Diff代码。这次修改的主要目的是修复分辨率排序的逻辑,将原本的“宽度小于等于高度小于”修改为标准的字典序比较(即“宽度小于宽度相等且高度小于”),这修复了原有的逻辑错误。

不过,这段代码在语法逻辑、代码质量、代码性能和代码安全方面仍有较大的改进空间。以下是详细的审查意见和改进建议:

1. 语法与逻辑

  • 逻辑修复正确性:你的修改方向是正确的。原代码使用 || 会导致即使宽度更大,只要高度更小也会触发交换,这会破坏排序的稳定性。修改后的逻辑符合标准的双关键字排序规则。
  • 变量命名不规范resolutiontemp1resolutiontemp2 命名带有缩写且冗长,建议改为更有意义的名称,如 res1res2,或者 currentResnextRes

2. 代码质量

  • 可读性差:修改后的 if 条件变得非常长,嵌套了多层括号,阅读和维护困难。
  • 魔法数字:代码中使用了 01 作为索引来获取宽度和高度,这是典型的“魔法数字”,读者无法直观理解 resolutiontemp1[0] 代表的是宽度还是高度。
  • 算法效率低:从上下文的 jj+1 以及交换逻辑可以看出,这是在手动实现冒泡排序。冒泡排序的时间复杂度为 $O(n^2)$,当分辨率列表较长时性能较差。C++ 标准库提供了 std::sort,建议使用它来替代手写排序。
  • 交换方式原始:使用第三个变量 resolutionstr 进行手动交换不够简洁,C++ 标准库提供了 std::swap,一行代码即可完成交换,且更加安全高效。

3. 代码安全

  • 数组越界风险resolutiontemp1[0]resolutiontemp1[1] 存在严重的越界隐患。如果 resolutionDatabase[j] 中的字符串格式不正确(例如缺少 "x",如 "1920" 或空字符串),split("x") 返回的列表长度将小于2,直接访问 [1] 会导致程序崩溃。
  • 隐式转换风险QString::toInt() 在转换失败时会默认返回 0。如果分辨率字符串包含非数字字符,程序不会报错,而是会默默按 0 进行排序,这可能导致难以排查的逻辑错误。

4. 代码性能

  • 重复计算:在原代码和修改后的代码中,resolutiontemp1[0].toInt() 等转换操作在 if 判断中可能被重复求值(虽然现代编译器可能会做优化,但书写上仍存在冗余)。
  • 频繁的字符串分割与转换:在排序的每一次比较中,都在执行 splittoInt 操作,这些涉及内存分配和字符串解析的操作开销很大。应该提前解析并缓存结果。

改进建议与重构代码

综合以上分析,我建议对这段代码进行彻底重构。最安全、最高效的做法是:先将字符串解析为安全的结构体并缓存,使用 std::sort 进行排序,然后再转换回字符串。

以下是改进后的代码示例:

#include <algorithm> // for std::sort
#include <vector>
#include <QSize>     // Qt中用于表示尺寸的类,非常适合此场景

void Settings::setNewResolutionList()
{
    // 假设 resolutionDatabase 是 QStringList 或 QList<QString>

    // 1. 预处理:安全解析并缓存,避免重复 split 和 toInt
    struct ResolutionItem {
        QSize size;  // 使用QSize存储宽高,语义清晰
        QString originalStr; // 保留原始字符串,防止解析丢失信息
    };

    std::vector<ResolutionItem> items;
    items.reserve(resolutionDatabase.size());

    for (const QString& str : resolutionDatabase) {
        QStringList parts = str.split("x");
        bool widthOk = false, heightOk = false;
        
        // 安全检查:确保分割后有两个部分,并且都能正确转换为数字
        if (parts.size() == 2) {
            int width = parts[0].toInt(&widthOk);
            int height = parts[1].toInt(&heightOk);
            
            if (widthOk && heightOk) {
                items.push_back({QSize(width, height), str});
                continue; // 解析成功,处理下一个
            }
        }
        
        // 解析失败的异常数据,可以选择记录警告日志,这里依然保留原始字符串并赋予默认值以防丢失
        qWarning() << "Invalid resolution format:" << str;
        items.push_back({QSize(0, 0), str}); 
    }

    // 2. 使用 std::sort 进行高效排序,逻辑清晰且无越界风险
    std::sort(items.begin(), items.end(), [](const ResolutionItem& a, const ResolutionItem& b) {
        if (a.size.width() != b.size.width()) {
            return a.size.width() < b.size.width(); // 宽度升序
        }
        return a.size.height() < b.size.height();   // 宽度相同,按高度升序
    });

    // 3. 将排序后的结果写回原列表
    resolutionDatabase.clear();
    for (const ResolutionItem& item : items) {
        resolutionDatabase.append(item.originalStr);
    }
}

重构代码的优势:

  1. 安全性极高:通过 parts.size() == 2toInt(&ok) 彻底杜绝了数组越界和隐式转换带来的逻辑错误。
  2. 性能优异:将 $O(n^2)$ 的冒泡排序替换为 $O(n \log n)$ 的快速排序/内省排序;且 splittoInt 只在预处理阶段执行一次,排序阶段直接比较整数,速度大幅提升。
  3. 可读性强:排序的 Lambda 表达式清晰地表达了“先按宽度排,宽度相同按高度排”的逻辑,消除了冗长的 if 嵌套和魔法数字。
  4. 健壮性:对于格式错误的数据,不会导致程序崩溃,而是给出了默认值并保留了原始字符串,方便后续调试。

@deepin-ci-robot
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: max-lvs, Resurgamz

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

@Resurgamz
Copy link
Copy Markdown
Author

/merge

@deepin-bot deepin-bot Bot merged commit 8061c9d into linuxdeepin:release/eagle May 28, 2026
22 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