045_第三代软件开发-U盘监测
  y1CBs17Aqlft 2023年11月19日 42 0


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

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


文章目录

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



关键字:

Qt

Qml

USB

Disk

文件

项目介绍

欢迎来到我们的 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了。

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

源代码

头文件

#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监听文件夹
  1. 第二部就是需要给这个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可以分类识别到时增加、减少还是修改,仅此而已,不影响代码阅读。

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

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


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月19日 0

暂无评论

推荐阅读
y1CBs17Aqlft