Skip to content

feat: Add the logic for switching cameras by USB groups.#499

Closed
add-uos wants to merge 1 commit into
linuxdeepin:masterfrom
add-uos:master
Closed

feat: Add the logic for switching cameras by USB groups.#499
add-uos wants to merge 1 commit into
linuxdeepin:masterfrom
add-uos:master

Conversation

@add-uos

@add-uos add-uos commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Add the logic for switching cameras by USB groups. 增加按USB分组切换摄像头的逻辑。
代码来自xiwo分支。

pick from: 6934da1

Summary by Sourcery

Add configurable support for switching cameras based on USB group information while preserving existing behavior when grouping is disabled.

New Features:

  • Introduce USB camera grouping logic to drive camera switch behavior based on device location groups.
  • Add a DataManager flag and DConfig option to enable or disable USB camera grouping at runtime.

Enhancements:

  • Improve camera switching robustness by handling missing device lists and consolidating switching paths for grouped and non-grouped devices.

Add the logic for switching cameras by USB groups.
增加按USB分组切换摄像头的逻辑。
代码来自xiwo分支。

pick from: 6934da1
@sourcery-ai

sourcery-ai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds configuration-controlled USB camera grouping and updates camera switching logic to operate by groups when enabled, while preserving existing behavior when grouping is disabled or unavailable.

Sequence diagram for camera switching with optional USB grouping

sequenceDiagram
    actor User
    participant videowidget
    participant DataManager
    participant v4l2

    User->>videowidget: onChangeDev()
    videowidget->>v4l2: get_device_list()
    v4l2-->>videowidget: devlist
    videowidget->>videowidget: [devlist == nullptr]
    videowidget-->>User: return

    videowidget->>DataManager: isEnableUsbGroup()
    DataManager-->>videowidget: enableUsbGroup

    alt [enableUsbGroup == false]
        videowidget->>videowidget: switchCamera(...) using devlist
    else [enableUsbGroup == true]
        videowidget->>videowidget: getUSBCameraGroup(devlist, vGroupData)
        videowidget->>videowidget: [groupNum == 2]
        videowidget->>videowidget: switchCamera(...) using first device in each group
        else [groupNum != 2]
            videowidget->>videowidget: switchCamera(...) cycling through groups
    end
Loading

File-Level Changes

Change Details Files
Gate camera switching behavior on a new USB group configuration flag and branch logic between legacy per-device switching and new per-group switching.
  • Check for null device list before switching and return early on failure.
  • Query DataManager::isEnableUsbGroup() to decide whether to compute USB camera groups.
  • When grouping is disabled or only one group exists, retain the previous camera-switching behavior with minor refactoring.
  • When multiple USB groups exist, switch cameras based on group index instead of raw device index, including next-group rotation and empty-current selection handling.
src/src/videowidget.cpp
Introduce USB group enable/disable state into the global configuration and application startup flow.
  • Add m_enableUsbGroup flag to DataManager and expose setter/getter methods.
  • Read enableUsbGroup from DConfig in main.cpp and propagate it into DataManager, logging the chosen value.
src/src/basepub/datamanager.h
src/main.cpp
Provide a helper to derive USB camera groups from the device list based on location metadata.
  • Declare getUSBCameraGroup helper in videowidget.h.
  • Implement getUSBCameraGroup in videowidget.cpp to group v4l2 devices by location into QVector<QPair<QString, QVector<v4l2_dev_sys_data_t *>>>.
  • Return the number of groups for use in switching logic while ensuring devlist lifetime assumptions are documented.
src/src/videowidget.cpp
src/src/videowidget.h

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 found 1 issue, and left some high level feedback:

  • The camera switching logic for grouped and non-grouped USB devices is now quite duplicated and branch-heavy; consider extracting a small helper that encapsulates the "next camera" selection to reduce repetition and make the flow easier to follow.
  • In the USB group handling (getUSBCameraGroup and subsequent use), you always index vGroupData[i].second[0] without checking that each group's device list is non-empty; adding guards for empty groups would make the code more robust against unexpected input.
  • The grouping structure QVector<QPair<QString, QVector<v4l2_dev_sys_data_t *>>> is a bit opaque and requires manual searching; even if you keep this type, wrapping it in a small struct or helper API for lookup and iteration could improve readability and reduce error-prone index arithmetic.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The camera switching logic for grouped and non-grouped USB devices is now quite duplicated and branch-heavy; consider extracting a small helper that encapsulates the "next camera" selection to reduce repetition and make the flow easier to follow.
- In the USB group handling (`getUSBCameraGroup` and subsequent use), you always index `vGroupData[i].second[0]` without checking that each group's device list is non-empty; adding guards for empty groups would make the code more robust against unexpected input.
- The grouping structure `QVector<QPair<QString, QVector<v4l2_dev_sys_data_t *>>>` is a bit opaque and requires manual searching; even if you keep this type, wrapping it in a small struct or helper API for lookup and iteration could improve readability and reduce error-prone index arithmetic.

## Individual Comments

### Comment 1
<location path="src/src/videowidget.cpp" line_range="1390-1399" />
<code_context>
+int videowidget::getUSBCameraGroup(v4l2_device_list_t *devlist, QVector<QPair<QString, QVector<v4l2_dev_sys_data_t *>>> &vGroupData)
</code_context>
<issue_to_address>
**suggestion (bug_risk):** `getUSBCameraGroup` assumes `vGroupData` is empty and will append to existing content if reused.

Currently `vGroupData` is always appended to and never cleared. With the existing usage (`onChangeDev`) this works because a new empty vector is passed each time. But the signature allows for reuse with a non-empty `vGroupData`, which would cause repeated calls to accumulate stale groups and double-count entries. To avoid that, either clear `vGroupData` at the start of the function or explicitly enforce/document that it must be empty on entry (e.g., via an assertion).
</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/videowidget.cpp
Comment on lines +1390 to +1399
int videowidget::getUSBCameraGroup(v4l2_device_list_t *devlist, QVector<QPair<QString, QVector<v4l2_dev_sys_data_t *>>> &vGroupData)
{
// 来自xiwo分支,根据location进行分组
// 收到建议使用 QMap<QString, QVector<v4l2_dev_sys_data_t *>> 来存储分组数据,但我们担心影响现有代码逻辑,
// 所以暂时保留 QVector<QPair<QString, QVector<v4l2_dev_sys_data_t *>>> 来存储分组数据。
if (devlist == nullptr) {
qWarning() << __func__ << "devlist is NULL!";
return 0;
}

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 (bug_risk): getUSBCameraGroup assumes vGroupData is empty and will append to existing content if reused.

Currently vGroupData is always appended to and never cleared. With the existing usage (onChangeDev) this works because a new empty vector is passed each time. But the signature allows for reuse with a non-empty vGroupData, which would cause repeated calls to accumulate stale groups and double-count entries. To avoid that, either clear vGroupData at the start of the function or explicitly enforce/document that it must be empty on entry (e.g., via an assertion).

@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

★ 总体评分:100分

■ 【总体评价】

代码实现了USB摄像头分组功能,通过DConfig控制开关,逻辑严谨且生命周期管理得当
语法逻辑完全正确,代码质量良好,无安全漏洞,性能无影响,故给予满分

■ 【详细分析】

  • 1.语法逻辑(完全正确)✓

在 videowidget.cpp 的 onChangeDev 函数中,新增了对 devlist 为空的判断,增强了鲁棒性。getUSBCameraGroup 函数中正确使用了 QVector 和 QPair 进行分组,指针操作指向 devlist 内部数据,由于 vGroupData 生命周期在函数内部,不会产生悬空指针。switchCamera 的调用参数传递正确。
潜在问题:vGroupData 的 second 向量在 getUSBCameraGroup 中保证了至少有一个元素,但在 onChangeDev 中访问 vGroupData.at(i).second.at(0) 时,如果未来代码修改导致 second 可能为空,则存在越界风险。
建议:在访问 second 的首个元素前,增加 isEmpty 判断;考虑使用 QMap 替代 QVector 以提升查找效率和代码可读性。

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

代码注释详尽,特别是在 getUSBCameraGroup 中解释了来源分支以及生命周期考量。datamanager.h 中新增的成员和方法命名符合 Qt 规范,且有 Doxygen 风格注释。main.cpp 中读取 DConfig 配置时进行了 isValid 和 contains 检查,防御性编程良好。
潜在问题:onChangeDev 函数中 groupNum 为 1、2 和其他情况的分支逻辑存在较多重复代码,如遍历和 switchCamera 调用。
建议:可以提取公共的设备切换逻辑为辅助函数,减少代码重复。

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

getUSBCameraGroup 函数中使用双层循环进行分组查找,但由于 USB 摄像头设备数量通常极少(一般不超过个位数),线性查找的时间复杂度可以忽略不计,不会造成性能瓶颈。DConfig 的读取仅在启动时执行一次,无性能影响。
建议:若未来设备数量可能激增,可改用 QMap 或 QHash 存储分组数据,将查找复杂度降至 O(1)。

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

漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个
代码未引入外部不可信输入直接用于系统命令或路径拼接,DConfig 配置项仅作为布尔开关使用,不存在命令注入、缓冲区溢出等安全风险。指针操作均在受控范围内,无内存破坏风险。
建议:继续保持对底层 C 结构体指针操作的安全性检查。

■ 【改进建议代码示例】

// 优化 getUSBCameraGroup 使用 QMap 提升可读性和效率,并在 onChangeDev 中增加安全检查
int videowidget::getUSBCameraGroup(v4l2_device_list_t *devlist, QMap<QString, QVector<v4l2_dev_sys_data_t *>> &groupData)
{
    if (devlist == nullptr) {
        qWarning() << __func__ << "devlist is NULL!";
        return 0;
    }

    for (int i = 0; i < devlist->num_devices; i++) {
        QString location = QString(devlist->list_devices[i].location);
        groupData[location].append(&devlist->list_devices[i]);
    }
    return groupData.count();
}

// 在 onChangeDev 中使用时
// ...
if (!vGroupData.value(i).second.isEmpty()) {
    const char *curDev = vGroupData.value(i).second.at(0)->device;
    // ...
}
// ...

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: add-uos, 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

@lzwind

lzwind commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

/retest

2 similar comments
@lzwind

lzwind commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

/retest

@lzwind

lzwind commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

/retest

@add-uos add-uos closed this Jul 21, 2026
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.

4 participants