045_第三代软件开发-U盘监测

news2024/11/26 16:46:19
头图

第三代软件开发-U盘监测

文章目录

  • 第三代软件开发-U盘监测
    • 项目介绍
    • U盘监测
      • 原理解释
      • 源代码

关键字: QtQmlUSBDisk文件

项目介绍

欢迎来到我们的 QML & C++ 项目!这个项目结合了 QML(Qt Meta-Object Language)和 C++ 的强大功能,旨在开发出色的用户界面和高性能的后端逻辑。

在项目中,我们利用 QML 的声明式语法和可视化设计能力创建出现代化的用户界面。通过直观的编码和可重用的组件,我们能够迅速开发出丰富多样的界面效果和动画效果。同时,我们利用 QML 强大的集成能力,轻松将 C++ 的底层逻辑和数据模型集成到前端界面中。

在后端方面,我们使用 C++ 编写高性能的算法、数据处理和计算逻辑。C++ 是一种强大的编程语言,能够提供卓越的性能和可扩展性。我们的团队致力于优化代码,减少资源消耗,以确保我们的项目在各种平台和设备上都能够高效运行。

无论您是对 QML 和 C++ 开发感兴趣,还是需要我们为您构建复杂的用户界面和后端逻辑,我们都随时准备为您提供支持。请随时联系我们,让我们一同打造现代化、高性能的 QML & C++ 项目!

重要说明☝

☀该专栏在第三代软开发更新完将涨价

U盘监测

一个项目在前期研究阶段需要的是什么,是理论的支撑,在验证这一理论的时候,需要大量的数据做支撑,所以我们需要软件具备数据记录功能,虽然这些功能不会最终暴露给用户,但是在前期研究阶段是必不可少的,所以我们需要具备这个功能,而这个功能开启的必要条件就是第一要在工程模式,第二要在U盘插入的情况下,才会开启。

而最终交付的用户的需求是需要把用户的报告导出到U盘,因为目前咱的设备是不带打印机的,无法直接打印出报告,而Linux下适配打印机,难度会超过Windows,不是我们不会,而是每家用的打印机都不一样,加上技术支持的技术不在线,所以暂时只是支持用户将报告导出到U盘,后期不排除直接配置打印机或者介入医院标准的HIS系统,不过那都是后话了,今天咱们主要解决USB下U盘监测的问题。

闭坑指南

Linux,每种系统实现的方式类似,又不完全一致,所以一下内用仅适用于Ubuntu 22.04版本,其他系统不做保证,不过原理应该是一致的,稍作改动即可。

原理解释

其实不管什么设备,在连入Linux系统,都会对应出一个文件来,为啥内,Linux 设计哲学之一 一切皆文件,所以我们实现的原理就是检测某一个文件夹的变化,这个Qt就给我们提供了很好的类QFileSystemWatcher,可以直接使用就可以。每个系统U盘设备的挂在有一定差异,自行搞一下就OK了。

源代码

头文件


#include <QObject>

#include "T_Core/Turing_FileMonitoring/turing_filesystemwatcher.h"


class XXXX : public QObject
{
    Q_OBJECT
    Q_PROPERTY(bool usbIn READ usbIn WRITE setUsbIn NOTIFY usbInChanged)                                    // USB插入标志
    Q_PROPERTY(QString usbPath READ usbPath WRITE setUsbPath NOTIFY usbPathChanged)                         // USB路劲
    Q_PROPERTY(QString systemPath READ systemPath WRITE setSystemPath NOTIFY SystemPathChanged)             // USB监听文件夹

public:
    explicit XXXX(QObject *parent = nullptr);
    ~XXXX();

    static XXXX* getInstance();

    QString getUserName();

    bool usbIn() const;

    void setUsbIn(bool newUsbIn);

    QString usbPath() const;

    void setUsbPath(const QString &newUsbPath);

    const QString &systemPath() const;

    void setSystemPath(const QString &newSystemPath);

signals:
    void usbInChanged();

    void usbPathChanged();

    void SystemPathChanged();

    void signalUmountUSB();


public slots:
    void slotUmountDisk();
private slots:

    void slot_GetSystemDevByName();

    void slot_AddSystemDevByName(QString strFolder, QString strFile);

    void slot_DeleteSystemDevByName(QString strFolder, QString strFile);

private:
    Turing_FileSystemWatcher*                           m_systemWatcher             = nullptr;
    QString                                             m_systemPath                = "";
    QStringList                                         m_systemList;
    bool                                                m_usbIn                     = false;
    QString                                             m_usbPath                   = ".";


};

#endif // XXXX_H

源文件

#include "XXXX.h"

#include <QProcess>

#include <iostream>


#include <QTextStream>
#include <QEventLoop>
#include <QTimer>

#include <QDir>
#include <QEventLoop>
#include <QTimer>

static QTextStream cout(stdout, QIODevice::WriteOnly);


Q_GLOBAL_STATIC(XXXX,XXXX)                                      // 单例宏
/**
 * @brief XXXX::XXXX
 * @param parent
 * 构造函数
 */
XXXX::XXXX(QObject *parent)
    : QObject{parent}
{
    m_systemWatcher = new Turing_FileSystemWatcher();

    connect(m_systemWatcher,&Turing_FileSystemWatcher::signalAddFile,
            this,&XXXX::slot_AddSystemDevByName);
    connect(m_systemWatcher,&Turing_FileSystemWatcher::signalDeleteFile,
            this,&XXXX::slot_DeleteSystemDevByName);

    connect(this, &XXXX::SystemPathChanged,this,
            &XXXX::slot_GetSystemDevByName);

    setSystemPath("/media/" + getUserName());

}

XXXX::~XXXX()
{

}
/**
 * @brief XXXX::getInstance
 * @return
 * 单例接口
 */
XXXX *XXXX::getInstance()
{
    return XXXX;
}
/**
 * @brief XXXX::getUserName
 * @return
 * 获取用户名
 */
QString XXXX::getUserName()
{
#ifdef Q_OS_LINUX
    QStringList envVariables;
    envVariables << "SUDO_USER.*";
    QStringList environment = QProcess::systemEnvironment();
    foreach (QString string, envVariables) {
        int index = environment.indexOf(QRegExp(string));
        if (index != -1)
        {
            QStringList stringList = environment.at(index).split('=');
            if (stringList.size() == 2)
            {
                qInfo() << "系统名称获取成功,系统名称: " << stringList.at(1);
                return stringList.at(1);
            }
        }
    }
    qWarning() << "系统名称获取失败,默认系统名称: " << "turing";
    return "turing";
#endif
}


/**
 * @brief XXXX::slot_GetSystemDevByName 初始化检测U盘是否存在
 */
void XXXX::slot_GetSystemDevByName()
{
    QDir dir(m_systemPath);
    if(!dir.exists())
        return;

    dir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
    dir.setSorting(QDir::Name);
    m_systemList = dir.entryList();

    if(m_systemList.size() > 0)
    {
        setUsbIn(true);
        // 默认活动U盘为获取的第一个
        setUsbPath(m_systemPath + "/" + m_systemList.at(0));

        qInfo() << "初始化获取U盘,U盘路径: " << m_usbPath;
    }
    else
    {
        setUsbIn(false);
    }
}

/**
 * @brief XXXX::slot_AddSystemDevByName 插入活动U盘
 * @param strFolder
 * @param strFile
 */
void XXXX::slot_AddSystemDevByName(QString strFolder, QString strFile)
{
    if(strFolder != m_systemPath)
        return;

    // 判断是否存在活动U盘
    if(!m_usbIn)
    {
        QEventLoop loop;//定义一个新的事件循环
        QTimer::singleShot(100, &loop, SLOT(quit()));  //创建单次定时器,槽函数为事件循环的退出函数
        loop.exec();  //事件循环开始执行,程序会卡在这里,直到定时时间到,本循环被退出
        setUsbPath(m_systemPath + "/" + strFile);
        setUsbIn(!m_usbIn);
        qInfo() << "挂在U盘,路径: " << m_usbPath;
    }
}

/**
 * @brief XXXX::slot_DeleteSystemDevByName 拔出活动U盘
 * @param strFolder
 * @param strFile
 */
void XXXX::slot_DeleteSystemDevByName(QString strFolder, QString strFile)
{
    if(strFolder != m_systemPath)
        return;

    if(m_usbIn)
    {
        // 判断拔出的是否是活动U盘
        if(m_usbPath != m_systemPath + "/" + strFile)
        {
            return;
        }
        setUsbPath("./");
        setUsbIn(!m_usbIn);

        qInfo() << "U盘非正常状态卸载,请检查数据完整性!";

    }
    else
    {
        qInfo() << "U盘正常弹出. 完毕";
    }
}

/**
 * @brief XXXX::slotUmountDisk  卸载U盘槽函数
 */
void XXXX::slotUmountDisk()
{
    emit signalUmountUSB();

    QEventLoop loop;//定义一个新的事件循环
    QTimer::singleShot(1000, &loop, SLOT(quit()));  //创建单次定时器,槽函数为事件循环的退出函数
    loop.exec();  //事件循环开始执行,程序会卡在这里,直到定时时间到,本循环被退出



    int ret = system(QString("echo umount '%1'").arg(m_usbPath).toLocal8Bit());
    if(ret == -1)
    {
        qInfo() << "卸载U盘失败";
    }
    else
    {
        setUsbIn(false);
        qInfo() << "弹出U盘";
    }
}

/**
 * @brief XXXX::usbIn
 * @return
 * 返回USB插入拔出状态
 */
bool XXXX::usbIn() const
{
    return m_usbIn;
}
/**
 * @brief XXXX::setUsbIn
 * @param newUsbIn
 * 设置USB插入拔出状态
 */
void XXXX::setUsbIn(bool newUsbIn)
{
    if (m_usbIn == newUsbIn)
        return;

    m_usbIn = newUsbIn;
    emit usbInChanged();
}
/**
 * @brief XXXX::usbPath
 * @return
 * 返回USB设备路径
 */
QString XXXX::usbPath() const
{
    return m_usbPath;
}
/**
 * @brief XXXX::setUsbPath
 * @param newUsbPath
 * 设置USB设备路径
 */
void XXXX::setUsbPath(const QString &newUsbPath)
{
    if (m_usbPath == newUsbPath)
        return;
    m_usbPath = newUsbPath;
    emit usbPathChanged();
}

/**
 * @brief XXXX::systemPath 返回检测U盘存在路径
 * @return
 */
const QString &XXXX::systemPath() const
{
    return m_systemPath;
}

/**
 * @brief XXXX::setSystemPath 设置检测U盘存在路径
 * @param newSystemPath
 */
void XXXX::setSystemPath(const QString &newSystemPath)
{
    if (m_systemPath == newSystemPath)
        return;
    m_systemPath = newSystemPath;
    qInfo() << "新增监控路径:" << m_systemPath;

    m_systemWatcher ->addWatchPath(m_systemPath);

    emit SystemPathChanged();
}

  1. 这里需要注意,我使用了Qt的属性系统,我这里有三个属性,这些属性将在QML中被使用。

    Q_PROPERTY(bool usbIn READ usbIn WRITE setUsbIn NOTIFY usbInChanged)                                    // USB插入标志
    Q_PROPERTY(QString usbPath READ usbPath WRITE setUsbPath NOTIFY usbPathChanged)                         // USB路劲
    Q_PROPERTY(QString systemPath READ systemPath WRITE setSystemPath NOTIFY SystemPathChanged)             // USB监听文件夹
    
  2. 第二部就是需要给这个U盘检测模块设置一个监测地址

    void XXXX::setSystemPath(const QString &newSystemPath)
    {
        if (m_systemPath == newSystemPath)
            return;
        m_systemPath = newSystemPath;
        qInfo() << "新增监控路径:" << m_systemPath;
    
        m_systemWatcher ->addWatchPath(m_systemPath);
    
        emit SystemPathChanged();
    }
    

    这里搭建看了可一个Turing_FileSystemWatcher,暂时这里可以直接把它理解成为一个Qt的文件监视器,只不过Qt的文件监视器只能知道文件夹变化了,而不能准确返回是增加了、减少了还是修改了,我们自己的Turing_FileSystemWatcher可以分类识别到时增加、减少还是修改,仅此而已,不影响代码阅读。

  3. 接着就是Qt 的事件循环,等待Turing_FileSystemWatcher的信号了。这里就不做具体解释了,代码没有太大难度。看下注释应该没有问题。


博客签名2021

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1173238.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

1.如何实现统一的API前缀-web组件篇

文章目录 1. 问题的由来2.实现原理3. 总结 1. 问题的由来 系统提供了 2 种类型的用户&#xff0c;分别满足对应的管理后台、用户 App 场景。 两种场景的前缀不同&#xff0c;分别为/admin-api/和/app-api/&#xff0c;都写在一个controller里面&#xff0c;显然比较混乱。分开…

storm安装手册及笔记

图解Storm相关概念 图解storm的并发机制 安装Storm的步骤 1、安装一个zookeeper集群 2、上传storm的安装包&#xff0c;解压 3、修改配置文件storm.yaml #所使用的zookeeper集群主机 storm.zookeeper.servers: - "weekend05" - "weekend06"…

亚马逊 JDK下载地址

下载地址 https://docs.aws.amazon.com/corretto/选择版本 选择操作系统 比如 windows64 位 可以选择安装包或者解压版本 msi 的为安装版 zip 的为解压版

微积分第一章函数与极限

1.正反三角函数的导数 2.常用等价无穷小 3.正反三角函数转化&#xff1a; 1.secx1/cosx 2.cecx1/sinx 3.cotx1/tanx 4.基本数学思想&#xff1a; 1.有限式子与无限式子&#xff1a;在面对无限个式子运算时&#xff0c;大体思路为两个方面&#xff0c;第一个为放缩&#xff…

静态、友好、内在:解析C++中的这些特殊元素和对象复制的优化

W...Y的主页 &#x1f60a; 代码仓库分享&#x1f495; &#x1f354;前言&#xff1a; 前面我们学习了C中关于类与对象的许多知识点&#xff0c;今天我们继续学习类与对象&#xff0c;最后再总结一下类与对象中的一些关键字内容&#xff0c;以及需要注意的细节。满满的干货…

【H.264】RTP h264 码流 实例解析分析 3 : webrtc

【srs】SRS检测IBMF还是annexb 【H.264】RTP h264 码流 实例解析分析 2 : mediasoup收包 mediasoup 并没完整解析rtp包的内容,可能与mediasoup 只需要转发,不需要解码有关系。 webrtc 本身都是全的。 m98代码,先说关键: webrtc的VideoRtpDepacketizer 第一:对RTPVideoType…

年终述职技巧

一个共识 给个交代 复盘 给自己的交代 展示 给公司的交代 三维构思法 认知与成长 以己为师 萃取与迭代 以事为师 响应与前瞻 以人为师&#xff08;“作者视角”转变为“观众视角”&#xff0c;听懂、感兴趣、认可、有收获&#xff09; 六点通关术 论证价值点 工作成果&#x…

从《lc114. 二叉树展开为链表》到《lc-LCR 155二叉搜索树转化为排序的双向链表》

1 lc114. 二叉树展开为链表 1.1 描述 进阶&#xff1a;你可以使用原地算法&#xff08;O(1) 额外空间&#xff09;展开这棵树吗&#xff1f; 1.2 解法一&#xff1a; 先序遍历这棵树并且将节点加入到一个list中&#xff0c;随后按顺序将list中的每一个元素的left指针置换为…

AGV 导航方法总体设计与分析

导航方案设计 导航方法分为三个部分——路径规划、实时定位、轨迹纠正。 视觉定位模块 主要有三个工作任务&#xff1a;利用二维码定位对 AGV 初始位姿 进行矫正&#xff0c;保证 AGV 初始运动时其运动轨迹能够与道路平行&#xff1b;利用 ORBSLAM 定位能够实时的获得 AGV 在…

LeetCode热题100——链表

链表 1. 相交链表2. 反转链表3. 回文链表4. 环形链表5. 合并两个有序链表 1. 相交链表 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 // 题解&#xff1a;使用A/B循环遍…

Windows Server 2019安装docker服务

离线状态下&#xff0c;使用脚本在Windows Server 2019环境中安装docker服务。 1.安装脚本 在微软官方网站中&#xff0c;找到脚本并下载&#xff1a; 准备 Windows 操作系统容器 | Microsoft Learn 脚本地址&#xff1a; https://raw.githubusercontent.com/microsoft/Win…

数字化饲料工厂中常见的系统及其介绍

数字化饲料工厂是基于先进技术和数字化平台构建的现代化饲料生产系统&#xff0c;它包含了多种软件、硬件和基础设施系统。以下是数字化饲料工厂中常见的系统及其介绍&#xff1a; 一、自动化控制系统&#xff1a;包括PLC&#xff08;可编程逻辑控制器&#xff09;系统、SCADA&…

R语言 PPT 预习+复习

什么狗吧发明的结业考&#xff0c;站出来和我对线 第一章 绪论 吊码没有&#xff0c;就算考R语言特点我也不背&#xff0c;问就是叫么这没用。 第二章 R语言入门 x<-1:20 赋值语句 x 1到20在x上添加均值为0、标准差为2的正态分布噪声 y <- x rnorm (20, 0, 2) 这…

SOEM源码解析——eeprom_read(读EEPROM)

0 工具准备 1.SOEM-master-1.4.0源码1 eeprom_read函数总览 eeprom_read函数在SOEM源码的路径如下&#xff1a;test->linux->eepromtool->eepromtool.c&#xff0c;功能是读取指定字地址和长度的EEPROM数据&#xff1a; /*** brief 读取EEPROM数据* * param slave …

Vue3:一页多题答案校正及radio和checkbox混合使用

一页多题&#xff0c;类型包括单选&#xff0c;判断多选&#xff0c;涉及radio和checkbox同时使用&#xff0c;答案校正数据匹配&#xff0c;正确答案格式化&#xff0c;答案提交数据格式化&#xff0c;数据提交。 效果&#xff1a; 数据获取&#xff1a; 数据提交&#xff1a…

k8s中实现mysql主备

文章目录 一、k8s中实现mysql主备1.1 环境信息1.2 部署nfs-provisioner1.2.1 安装nfs1.2.2 部署nfs-provisioner 1.3 安装mysql1.4 备库上查看是否同步 一、k8s中实现mysql主备 1.1 环境信息 机器操作系统ipmysql版本k8s版本storageClassmaster1CentOS7.8192.168.0.20mysql5.…

Xbox漫游指南

以Xbox series s为例 开机启动 用手柄连接&#xff0c;注意两颗电池要方向相反插入&#xff0c;虽然里面2个插槽长一样&#xff1b; Xbox APP极其难用&#xff0c;放弃&#xff0c;直接用手柄连接 转区 只需要一个空U盘&#xff0c;大小不限制&#xff0c;格式化为NTPS格式…

【51单片机】DS1302时钟(学习笔记)

一、DS1302时钟 1、DS1302介绍 DS1302是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片。它可以对年、月、日、周、时、分、秒进行计时&#xff0c;且具有闰年补偿等多种功能 RTC(Real Time Clock)&#xff1a;实时时钟&#xff0c;是一种集成电路&#xf…

基础课22——云服务(SaaS、Pass、laas、AIaas)

1.云服务概念和类型 云服务是一种基于互联网的计算模式&#xff0c;通过云计算技术将计算、存储、网络等资源以服务的形式提供给用户&#xff0c;用户可以通过网络按需使用这些资源&#xff0c;无需购买、安装和维护硬件设备。云服务具有灵活扩展、按需使用、随时随地访问等优…

Spring-IOC容器深度剖析详解

&#x1f388;个人公众号:&#x1f388; :✨✨✨ 可为编程✨ &#x1f35f;&#x1f35f; &#x1f511;个人信条:&#x1f511; 知足知不足 有为有不为 为与不为皆为可为&#x1f335; &#x1f349;本篇简介:&#x1f349; 本篇由表及里分析Spring-IOC容器始末&#xff0c;如…