Files
VX5_KRO_GearPump/fileManage/U盘热拔插修复方案.md
T

3.9 KiB
Raw Blame History

U盘热拔插修复方案

问题描述

FileManageWidget 右侧 U 盘文件显示列表的 udiskSelectBox 下拉框无法处理热拔插的 U 盘。每次点击下拉框时,应能识别到当前已插入的 U 盘列表。

根因分析

1. 信号连接已存在(无需修改)

在 FileManageWidget.ui 中,udiskSelectBox(UDiskComboBox 类型)的 popupShowed() 信号已经连接到 FileManageWidget::updateUDiskDevList() 槽:

<connection>
  <sender>udiskSelectBox</sender>
  <signal>popupShowed()</signal>
  <receiver>FileManageWidget</receiver>
  <slot>updateUDiskDevList()</slot>
</connection>

UDiskComboBox 重写了 showPopup(),每次下拉框展开时都会发射 popupShowed() 信号:

void UDiskComboBox::showPopup()
{
    emit popupShowed();
    QComboBox::showPopup();
}

2. 问题根源:updateUDiskDevList() 实现有缺陷

旧代码:

void FileManageWidget::updateUDiskDevList()
{
    QDir dir(UDISK_DOC_ROOT_DIR);
    if(!dir.exists()) {
        ui->udiskSelectBox->clear();
        return;
    }

    if(ui->udiskSelectBox->currentText() != tr("U盘")){
        ui->udiskSelectBox->clear();
        ui->udiskSelectBox->addItem(tr("U盘"));
        ui->udiskSelectBox->setCurrentIndex(0);
    }

    updateFileListView(ui->udiskFileListView);
}

两个问题:

  1. QDir::exists() 不可靠:UDISK_DOC_ROOT_DIR(/udisk/doc/)目录可能在 U 盘未挂载时也存在于根文件系统中,导致 exists() 始终返回 true,无法正确识别 U 盘的拔出。

  2. 条件判断逻辑脆弱:if(currentText() != "U盘") 的判断方式无法正确处理"拔出再插入"的完整热拔插场景。例如 U 盘拔出后下拉框被清空,再次插入时 currentText() 为空字符串,虽然能进入分支添加 "U盘",但整体逻辑不够健壮。

修复方案

修改文件

文件路径: fileManage/FileManageWidget.cpp

改动 1:新增头文件

#include <QFile>

改动 2:重写 updateUDiskDevList() 方法

void FileManageWidget::updateUDiskDevList()
{
    bool hasUDisk = false;
    QFile mountsFile("/proc/mounts");
    if (mountsFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
        QTextStream in(&mountsFile);
        while (!in.atEnd()) {
            const QString line = in.readLine();
            if (line.contains("/udisk ")) {
                hasUDisk = true;
                break;
            }
        }
        mountsFile.close();
    }

    if (!hasUDisk) {
        QDir dir(UDISK_DOC_ROOT_DIR);
        hasUDisk = dir.exists();
    }

    ui->udiskSelectBox->clear();
    if (hasUDisk) {
        ui->udiskSelectBox->addItem(tr("U盘"));
        ui->udiskSelectBox->setCurrentIndex(0);
    }

    updateFileListView(ui->udiskFileListView);
}

新逻辑说明

步骤 说明
1. 读取 /proc/mounts 检查 /udisk 挂载点是否真正挂载了设备(Linux 下判断挂载状态的标准方式)
2. 回退检查 如果 /proc/mounts 读取失败,回退到 QDir::exists() 作为兼容性保障
3. 重建下拉框 每次调用都先清空再根据检测结果添加 "U盘" 项,确保状态始终正确
4. 刷新文件列表 调用 updateFileListView() 更新 U 盘文件显示

行为对照

场景 修复前 修复后
U 盘插入 → 点击下拉框 可能不显示(目录始终存在) 通过 /proc/mounts 检测到挂载,显示 "U盘"
U 盘拔出 → 点击下拉框 仍显示 "U盘"(目录仍存在) 检测到 /udisk 未挂载,下拉框为空
U 盘拔出再插入 → 点击下拉框 状态不确定 正确检测到重新挂载,显示 "U盘"
系统启动时无 U 盘 可能显示 "U盘" 下拉框为空
系统启动时有 U 盘 显示 "U盘" 显示 "U盘"