Skip to content

Fix(cpu): Improve CPU header fallback and dynamic PageMultiInfo heade…#670

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:develop/eaglefrom
GongHeng2017:202605281613-dev-eagle-fix
May 28, 2026
Merged

Fix(cpu): Improve CPU header fallback and dynamic PageMultiInfo heade…#670
deepin-bot[bot] merged 1 commit into
linuxdeepin:develop/eaglefrom
GongHeng2017:202605281613-dev-eagle-fix

Conversation

@GongHeng2017
Copy link
Copy Markdown
Contributor

@GongHeng2017 GongHeng2017 commented May 28, 2026

…r sizing

--Use dmidecode Version and Manufacturer as fallback values for
missing CPU model name and vendor_id in DeviceGenerator::generatorCpuDevice
--Remove hard-coded PageMultiInfo header widget height and compute the height dynamically from row count, improving layout handling for varying header data

Log: fix issue
Bug: https://pms.uniontech.com/bug-view-363473.html

Summary by Sourcery

Improve CPU header information generation and make the multi-info page header height adapt to its content.

Bug Fixes:

  • Fill missing CPU model and vendor fields using DMI Version and Manufacturer data for systems with incomplete CPU information.

Enhancements:

  • Compute the PageMultiInfo header widget height dynamically from the number of rows instead of using a hard-coded default height.

@github-actions
Copy link
Copy Markdown

  • 检测到敏感词dmidecode变动
详情
    {
    "dmidecode": {
        "deepin-devicemanager/src/GenerateDevice/DeviceGenerator.cpp": [
            "        if (!baseCpuInfo.contains(\"model name\") && dmidecode.contains(\"Version\")) {",
            "            baseCpuInfo.insert(\"model name\", dmidecode[\"Version\"]); // \u9002\u914d\u7279\u6b8a\u673a\u578bCPU",
            "        if (!baseCpuInfo.contains(\"vendor_id\") && dmidecode.contains(\"Manufacturer\")) {",
            "            baseCpuInfo.insert(\"vendor_id\", dmidecode[\"Manufacturer\"]); // \u9002\u914d\u7279\u6b8a\u673a\u578bCPU"
        ]
    }
}

@github-actions github-actions Bot requested a review from liujianqiang-niu May 28, 2026 09:43
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 28, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

This PR enhances CPU device header generation by falling back to dmidecode fields when CPU model/vendor are missing, and adjusts the PageMultiInfo header area to size dynamically based on its content instead of using a hard-coded height.

Sequence diagram for CPU header generation with dmidecode fallback

sequenceDiagram
    participant DeviceGenerator
    participant lsCpu
    participant dmidecode
    participant calAndSetCpuHeaderInfo

    DeviceGenerator->>lsCpu: size()
    alt [lsCpu.size() > 0]
        DeviceGenerator->>lsCpu: at(0)
        DeviceGenerator->>DeviceGenerator: baseCpuInfo = lsCpu.at(0)
        alt [!baseCpuInfo.contains(model name) && dmidecode.contains(Version)]
            DeviceGenerator->>dmidecode: [read Version]
            DeviceGenerator->>DeviceGenerator: baseCpuInfo.insert(model name, dmidecode[Version])
        end
        alt [!baseCpuInfo.contains(vendor_id) && dmidecode.contains(Manufacturer)]
            DeviceGenerator->>dmidecode: [read Manufacturer]
            DeviceGenerator->>DeviceGenerator: baseCpuInfo.insert(vendor_id, dmidecode[Manufacturer])
        end
        DeviceGenerator->>calAndSetCpuHeaderInfo: calAndSetCpuHeaderInfo(baseCpuInfo, coreNum, logicalNum)
    else [lsCpu.size() == 0]
        DeviceGenerator-->>DeviceGenerator: [do not call calAndSetCpuHeaderInfo]
    end
Loading

File-Level Changes

Change Details Files
Improve CPU header generation robustness using dmidecode fallbacks when lscpu data is incomplete.
  • Wrap existing CPU header calculation in a guarded block that first copies the base CPU info map from the first lscpu entry.
  • If the CPU info lacks "model name" but dmidecode provides a "Version" field, insert that value as the model name.
  • If the CPU info lacks "vendor_id" but dmidecode provides a "Manufacturer" field, insert that value as the vendor_id.
  • Pass the potentially augmented CPU info map into calAndSetCpuHeaderInfo instead of the raw lscpu map.
deepin-devicemanager/src/GenerateDevice/DeviceGenerator.cpp
Make PageMultiInfo header widget height dynamic based on header row count instead of using a fixed default height.
  • Remove the kHeaderInfoDefaultHeight constant and any fixed maximum-height configuration for the header scroll area.
  • During updateInfo, compute a defaultHeight from the number of rows in the first headerInfo table (row count * ROW_HEIGHT + 2).
  • Apply the computed defaultHeight as both the maximum height and resize height of mp_HeaderInfoWidget when CPU is selected.
  • Keep minimum height at 0 and size policy as Expanding/Preferred to work with dynamic sizing.
deepin-devicemanager/src/Page/PageMultiInfo.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 left some high level feedback:

  • In generatorCpuDevice, you only fall back to dmidecode values when the model name/vendor_id keys are missing; consider also handling the case where the keys exist but contain empty strings so that truly missing values are correctly replaced.
  • The dynamic defaultHeight in PageMultiInfo::updateInfo is calculated only from headerInfo.at(0).size(), but multiple HeaderInfoTableWidgets are added; consider basing the height on the maximum row count among all headers or on the widgets’ sizeHint() to better handle multiple CPUs.
  • The + 2 adjustment in the defaultHeight calculation (headerInfo.at(0).size() * ROW_HEIGHT + 2) is a magic number; consider deriving this from actual margins or constants so that the intent and future adjustments are clearer.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `generatorCpuDevice`, you only fall back to dmidecode values when the `model name`/`vendor_id` keys are missing; consider also handling the case where the keys exist but contain empty strings so that truly missing values are correctly replaced.
- The dynamic `defaultHeight` in `PageMultiInfo::updateInfo` is calculated only from `headerInfo.at(0).size()`, but multiple `HeaderInfoTableWidget`s are added; consider basing the height on the maximum row count among all headers or on the widgets’ `sizeHint()` to better handle multiple CPUs.
- The `+ 2` adjustment in the `defaultHeight` calculation (`headerInfo.at(0).size() * ROW_HEIGHT + 2`) is a magic number; consider deriving this from actual margins or constants so that the intent and future adjustments are clearer.

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.

…r sizing

--Use dmidecode Version and Manufacturer as fallback values for
  missing CPU model name and vendor_id in DeviceGenerator::generatorCpuDevice
--Remove hard-coded PageMultiInfo header widget height and compute
the height dynamically from row count, improving layout handling for varying header data

Log: fix issue
Bug: https://pms.uniontech.com/bug-view-363473.html
@GongHeng2017 GongHeng2017 force-pushed the 202605281613-dev-eagle-fix branch from fa7679a to 4c3487e Compare May 28, 2026 11:20
@github-actions
Copy link
Copy Markdown

  • 检测到敏感词dmidecode变动
详情
    {
    "dmidecode": {
        "deepin-devicemanager/src/GenerateDevice/DeviceGenerator.cpp": [
            "        if (!baseCpuInfo.contains(kModelName) && dmidecode.contains(kDmiVersion)) {",
            "            baseCpuInfo.insert(kModelName, dmidecode[kDmiVersion]); // \u9002\u914d\u7279\u6b8a\u673a\u578bCPU",
            "        if (!baseCpuInfo.contains(kVendorId) && dmidecode.contains(kDmiManufacturer)) {",
            "            baseCpuInfo.insert(kVendorId, dmidecode[kDmiManufacturer]); // \u9002\u914d\u7279\u6b8a\u673a\u578bCPU"
        ]
    }
}

@deepin-ci-robot
Copy link
Copy Markdown

deepin pr auto review

你好!我是CodeGeeX,你的智能编程助手。我已仔细审查了你提供的Git Diff代码。这次修改主要涉及两个部分:一是针对特殊机型CPU信息的兼容性适配,二是CPU头部信息展示控件的高度自适应调整。

总体来说,代码的意图清晰,提取字符串常量避免了“魔法字符串”,高度自适应也比写死固定值更合理。但在语法逻辑、代码质量和性能安全方面,还有一些可以改进和优化的空间。以下是详细的审查意见:

一、 语法与逻辑

1. QMap 的隐式共享与深拷贝问题(性能与逻辑隐患)

  • 位置DeviceGenerator.cpp 第214行 QMap<QString, QString> baseCpuInfo = lsCpu.at(0);
  • 问题lsCpu.at(0) 返回的是 QMap,在Qt中 QMap 采用隐式共享(写时复制)机制。直接这样赋值虽然不会立刻触发深拷贝,但后续的 baseCpuInfo.insert() 会触发写操作,导致深拷贝的发生。如果 lsCpu 中的 QMap 数据量较大,这会产生不必要的性能开销。
  • 改进意见:如果 calAndSetCpuHeaderInfo 函数的参数是 const 引用(从Diff看确实是 const QMap<QString, QString> &firstProcessorInfo),我们完全可以直接在原始数据上操作,或者更优雅的做法是:构建一个临时的补充 QMap,在传递时合并,或者直接修改函数接口。但最简单的改法是避免不必要的拷贝:
// 修改建议:使用引用,避免深拷贝
if (!lsCpu.isEmpty()) {
    QMap<QString, QString> baseCpuInfo = lsCpu.at(0); // 此处仍会拷贝,因为需要insert修改
    // 如果不想拷贝,且不想改变原 lsCpu,可以采用以下方式:
    // 方式A:直接修改 calAndSetCpuHeaderInfo 接口,让它接收补充信息
    // 方式B:如果 lsCpu 允许修改,直接用引用:QMap<QString, QString> &baseCpuInfo = lsCpu[0];
    
    // 当前逻辑下,如果坚持使用拷贝,代码逻辑没问题,但需知晓这里有拷贝开销。
    // 优化写法:先判断再拷贝,如果没有缺失,就不需要拷贝和修改
    bool needPatch = (!baseCpuInfo.contains(kModelName) && dmidecode.contains(kDmiVersion)) ||
                     (!baseCpuInfo.contains(kVendorId) && dmidecode.contains(kDmiManufacturer));
    
    QMap<QString, QString> patchedCpuInfo = lsCpu.at(0); // 按需拷贝
    if (needPatch) {
        if (!patchedCpuInfo.contains(kModelName) && dmidecode.contains(kDmiVersion)) {
            patchedCpuInfo.insert(kModelName, dmidecode[kDmiVersion]);
        }
        if (!patchedCpuInfo.contains(kVendorId) && dmidecode.contains(kDmiManufacturer)) {
            patchedCpuInfo.insert(kVendorId, dmidecode[kDmiManufacturer]);
        }
    }
    calAndSetCpuHeaderInfo(patchedCpuInfo, coreNum, logicalNum);
}

2. 容器判空逻辑的严谨性

  • 位置DeviceGenerator.cpp 第213行 if (lsCpu.size() > 0)PageMultiInfo.cpp 第106行 if (headerInfo.size() > 0 && headerInfo.at(0).size() > 0)
  • 问题:在C++/Qt中,判断容器是否为空,推荐使用 isEmpty() 方法,语义更清晰,且对于某些容器来说性能更好(如 QListsize() 可能需要遍历计算,而 isEmpty() 是 O(1))。
  • 改进意见
// 修改前
if (lsCpu.size() > 0)
// 修改后
if (!lsCpu.isEmpty())

// 修改前
if (headerInfo.size() > 0 && headerInfo.at(0).size() > 0)
// 修改后
if (!headerInfo.isEmpty() && !headerInfo.at(0).isEmpty())

二、 代码质量

1. 全局常量的定义规范

  • 位置DeviceGenerator.cpp 第38-40行
  • 问题:在 .cpp 文件中定义全局常量使用了 const QString。这在C++中会导致每个编译单元(.cpp)如果都包含类似定义,会产生多余的字符串构造和析构开销。另外,Qt中对于仅限当前文件使用的常量,推荐使用匿名命名空间或 static 修饰;对于全局跨文件的常量,应使用 constexpr 或在头文件中声明 extern
  • 改进意见
// 推荐做法1:如果在 .cpp 内部使用,放入匿名命名空间或加 static
namespace {
const QString kModelName { "model name" };
const QString kVendorId { "vendor_id" };
const QString kDmiVersion { "Version" };
const QString kDmiManufacturer { "Manufacturer" };
}

// 推荐做法2:如果使用 C++17 或更高版本,且字符串不需要隐式共享机制,使用 constexpr (Qt 6 支持,Qt 5 部分支持)
// 或者使用 QStringLiteral 减少运行时内存分配
static const QString kModelName = QStringLiteral("model name");

2. PageMultiInfo.cppROW_HEIGHT 的来源不明

  • 位置PageMultiInfo.cpp 第108行 defaultHeight = headerInfo.at(0).size() * ROW_HEIGHT + kAdjustHeight;
  • 问题:Diff中没有显示 ROW_HEIGHT 的定义,如果它是一个宏或者全局变量,直接用来计算高度可能会因为 DPI 缩放导致高度计算不准确。另外,kAdjustHeight 被设为 { 2 },这个“2”的物理意义是什么?如果是边距或间距,建议使用更语义化的命名,如 kVerticalPadding

三、 代码性能

1. UI 控件的高度计算与布局性能

  • 位置PageMultiInfo.cpp 第99-113行
  • 问题:你通过手动计算 size() * ROW_HEIGHT 来设置 mp_HeaderInfoWidget 的最大高度和尺寸。这在 Qt 的布局系统中属于“手动干预”。如果 ROW_HEIGHT 因为字体变化、系统缩放比例改变而不再准确,界面就会出现滚动条或留白。
  • 改进意见:Qt 的布局系统(QLayout)本身就具备根据内容自动调整控件大小的能力(sizeHint)。你在这里使用了 setMaximumHeightresize,可能会导致后续窗口缩放时出现布局异常。
    如果确实需要手动控制,建议使用 QFontMetrics 动态获取当前字体的行高,而不是依赖硬编码的 ROW_HEIGHT
// 动态获取行高的示例
QFontMetrics fm(this->font());
int lineHeight = fm.height() + some_padding; 
defaultHeight = headerInfo.at(0).size() * lineHeight + kAdjustHeight;

四、 代码安全

1. dmidecode 数据来源的安全性

  • 位置DeviceGenerator.cpp 第217行 baseCpuInfo.insert(kModelName, dmidecode[kDmiVersion]);
  • 问题dmidecode 通常是通过执行系统命令 dmidecode 并解析其输出得来的。解析外部命令的输出时,极易因为格式不规范(如包含意外空格、换行符、特殊字符)导致界面显示混乱或潜在的注入问题(虽然这里是读取而非执行,风险较低,但脏数据风险高)。
  • 改进意见:在将 dmidecode 的值插入到 baseCpuInfo 之前,建议进行简单的字符串清洗(去除首尾空白字符等):
if (!baseCpuInfo.contains(kModelName) && dmidecode.contains(kDmiVersion)) {
    QString version = dmidecode[kDmiVersion].trimmed(); // 清除首尾空白符
    if (!version.isEmpty()) {
        baseCpuInfo.insert(kModelName, version);
    }
}

总结与重构建议

综合以上意见,针对 DeviceGenerator.cpp 中的修改,我提供一份优化后的代码供参考:

// 常量定义建议放入匿名命名空间或加 static,并使用 QStringLiteral 优化
namespace {
const QString kModelName = QStringLiteral("model name");
const QString kVendorId = QStringLiteral("vendor_id");
const QString kDmiVersion = QStringLiteral("Version");
const QString kDmiManufacturer = QStringLiteral("Manufacturer");
}

void DeviceGenerator::generatorCpuDevice()
{
    // ... 前置代码 ...

    // 计算并设置CPU头部信息(当前没有多个物理CPU的环境,所以只能编码单物理CPU的逻辑)
    if (!lsCpu.isEmpty()) {
        QMap<QString, QString> baseCpuInfo = lsCpu.at(0);
        bool needPatch = false;

        // 检查是否需要补丁,并对 dmidecode 的数据进行清洗
        if (!baseCpuInfo.contains(kModelName) && dmidecode.contains(kDmiVersion)) {
            QString version = dmidecode[kDmiVersion].trimmed();
            if (!version.isEmpty()) {
                baseCpuInfo.insert(kModelName, version);
                needPatch = true;
            }
        }
        if (!baseCpuInfo.contains(kVendorId) && dmidecode.contains(kDmiManufacturer)) {
            QString manufacturer = dmidecode[kDmiManufacturer].trimmed();
            if (!manufacturer.isEmpty()) {
                baseCpuInfo.insert(kVendorId, manufacturer);
                needPatch = true;
            }
        }
        
        calAndSetCpuHeaderInfo(baseCpuInfo, coreNum, logicalNum);
    }
}

对于 PageMultiInfo.cpp,建议将 size() > 0 替换为 !isEmpty(),并审视 ROW_HEIGHT 在高DPI环境下的准确性。希望这些意见对你有所帮助!

@deepin-ci-robot
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

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

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

@GongHeng2017
Copy link
Copy Markdown
Contributor Author

/forcemerge

@deepin-bot
Copy link
Copy Markdown
Contributor

deepin-bot Bot commented May 28, 2026

This pr force merged! (status: unstable)

@deepin-bot deepin-bot Bot merged commit 0008d44 into linuxdeepin:develop/eagle May 28, 2026
21 of 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