QT拷贝文件(仿Windows复制文件界面)

本例子利用线程进行文件拷贝,并且有界面显示,支持多文件夹复制。

Dialog_CopyFile.h
#ifndef DIALOG_COPYFILE_H
#define DIALOG_COPYFILE_H

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

struct CopyList
{
    QString srcPath;
    QString dstPath;
};

class QThreadWork : public QThread
{
    Q_OBJECT
public:
    QThreadWork(int nID, const QString &srcPath, const QString &dstPath, bool b);
    ~QThreadWork();
    int m_nID;
    bool m_bInit;
    QString m_srcPath;
    QString m_dstPath;
    QList m_fileInfoList;
    bool coverFileIfExist;
    qulonglong m_filesizesAll;
signals:
    void setPosSignal(int, QString, QString, QString, int, int, QString);
    void endSignal(int);
    // QThread interface
protected:
    virtual void run() override;

    void getDirectoryList(const QString &srcPath, const QString &dstPath);

    QString formatSize(quint64 ullSize);
};

class Dialog_CopyFile : public QDialog
{
    Q_OBJECT
public:
    explicit Dialog_CopyFile(QWidget *parent = nullptr);

    bool copyDirectory(const QStringList &srcPathList,
                       const QStringList &dstPathList,
                       bool coverFileIfExist);

    bool copyDirectory(const QString &srcPath, const QString &dstPath, bool coverFileIfExist);

public:
    QVBoxLayout *m_pMainVBoxLayout;
    QWidget *m_pVBoxLayoutWidget[10];
    QVBoxLayout *m_pVBoxLayout[10];
    QLabel *m_pLable1[10];
    QLabel *m_pLable2[10];
    QLabel *m_pLable3[10];
    QLabel *m_pLable4[10];
    QProgressBar *m_pProgressBar[10];
    QThreadWork *m_pThreadWork[10];
    int m_nThreadCount;
    bool m_bWorking[10];

    // QWidget interface
protected:
    virtual void closeEvent(QCloseEvent *event) override;
};

#endif // DIALOG_COPYFILE_H
Dialog_CopyFile.cpp
#include "dialog_copyfile.h"

#include "splitline.h"
#include 
#include 
#include 

QString DoubleToQString(const double value, int precision)
{
    QRegExp rx;
    rx.setPattern("(\\.){0,1}0+$");
    return QString::number(value, 10, precision).replace(rx, "");
}

Dialog_CopyFile::Dialog_CopyFile(QWidget *parent)
    : QDialog(parent)
{
    setMaximumWidth(400);
    setMinimumWidth(400);
    setModal(true);
}

bool Dialog_CopyFile::copyDirectory(const QStringList &srcPathList,
                                    const QStringList &dstPathList,
                                    bool coverFileIfExist)
{
    setWindowTitle("文件复制");
    if (srcPathList.size() != dstPathList.size())
        return false;
    m_nThreadCount = srcPathList.size() > 10 ? 10 : srcPathList.size();
    m_pMainVBoxLayout = new QVBoxLayout;
    m_pMainVBoxLayout->setSizeConstraint(QLayout::SetFixedSize);
    m_pMainVBoxLayout->setMargin(0);
    for (int i = 0; i < m_nThreadCount; i++) {
        m_pVBoxLayoutWidget[i] = new QWidget;
        m_pVBoxLayout[i] = new QVBoxLayout;
        m_pLable1[i] = new QLabel;
        m_pVBoxLayout[i]->addWidget(m_pLable1[i]);
        m_pLable2[i] = new QLabel;
        m_pVBoxLayout[i]->addWidget(m_pLable2[i]);
        m_pProgressBar[i] = new QProgressBar;
        m_pProgressBar[i]->setValue(0);
        m_pVBoxLayout[i]->addWidget(m_pProgressBar[i]);
        m_pLable3[i] = new QLabel;
        m_pVBoxLayout[i]->addWidget(m_pLable3[i]);
        m_pLable4[i] = new QLabel;
        m_pVBoxLayout[i]->addWidget(m_pLable4[i]);
        m_pVBoxLayout[i]->addWidget(new SplitLine(this));
        m_pVBoxLayoutWidget[i]->setMinimumWidth(400);
        m_pVBoxLayoutWidget[i]->setMaximumWidth(400);
        m_pVBoxLayoutWidget[i]->setLayout(m_pVBoxLayout[i]);
        m_pVBoxLayoutWidget[i]->setMinimumHeight(180);
        m_pVBoxLayoutWidget[i]->setMaximumHeight(180);
        m_pMainVBoxLayout->addWidget(m_pVBoxLayoutWidget[i]);
        m_pThreadWork[i] = new QThreadWork(i,
                                           srcPathList.at(i),
                                           dstPathList.at(i),
                                           coverFileIfExist);
        connect(m_pThreadWork[i],
                &QThreadWork::setPosSignal,
                this,
                [&](int nID,
                    QString qsMsg,
                    QString qsMsg2,
                    QString src,
                    int i,
                    int nSize,
                    QString qsSize) {
                    m_pLable1[nID]->setText(qsMsg);
                    m_pLable2[nID]->setText(qsMsg2);
                    m_pProgressBar[nID]->setValue((i + 1) * 100 / nSize);
                    if (src != "")
                        m_pLable3[nID]->setText(QString("名称:%1").arg(src));
                    m_pLable4[nID]->setText(
                        QString("剩余项目:%1(%2)").arg(nSize - (i + 1)).arg(qsSize));
                });
        connect(m_pThreadWork[i], &QThreadWork::endSignal, this, [&](int nID) {
            m_pVBoxLayoutWidget[nID]->hide();
            m_bWorking[nID] = false;
            m_pThreadWork[nID]->deleteLater();
            m_pThreadWork[nID] = nullptr;
            bool bEnd = true;
            for (int i = 0; i < m_nThreadCount; i++) {
                if (m_bWorking[i])
                    bEnd = false;
            }
            if (bEnd) {
                QThread::sleep(1);
                setHidden(true);
                return;
            }
            move((QApplication::desktop()->width() - width()) / 2,
                 (QApplication::desktop()->height() - height()) / 2);
        });
        m_bWorking[i] = true;
        m_pThreadWork[i]->start(QThread::TimeCriticalPriority);
    }
    setLayout(m_pMainVBoxLayout);
    show();
    return true;
}

bool Dialog_CopyFile::copyDirectory(const QString &srcPath,
                                    const QString &dstPath,
                                    bool coverFileIfExist)
{
    copyDirectory(QStringList(srcPath), QStringList(dstPath), coverFileIfExist);
}

void Dialog_CopyFile::closeEvent(QCloseEvent *event)
{
    for (int i = 0; i < m_nThreadCount; i++) {
        m_pThreadWork[i]->m_bInit = false;
        m_pThreadWork[i]->deleteLater();
        m_pThreadWork[i] = nullptr;
    }
}

QThreadWork::QThreadWork(int nID, const QString &srcPath, const QString &dstPath, bool b)
{
    m_nID = nID;
    m_srcPath = srcPath;
    m_dstPath = dstPath;
    coverFileIfExist = b;
    m_filesizesAll = 0;
    m_bInit = true;
}

QThreadWork::~QThreadWork()
{
    m_bInit = false;
    this->wait();
}

void QThreadWork::run()
{
    getDirectoryList(m_srcPath, m_dstPath);
    QFileInfo fileInfoSrc(m_srcPath);
    QFileInfo fileInfoDst(m_dstPath);
    for (int i = 0; i < m_fileInfoList.size(); i++) {
        if (!m_bInit)
            return;
        CopyList copyList = m_fileInfoList.at(i);
        //        qDebug() << QString("copy %1, percent %2")
        //                        .arg(copyList.srcPath)
        //                        .arg((i + 1) * 100 / m_fileInfoList.size());
        QFileInfo fileInfo(copyList.srcPath);
        QFileInfo fileInfo1(copyList.dstPath);
        m_filesizesAll -= fileInfo.size();
        QString qsMsg = QString("正在将%1项目从%2复制到%3")
                            .arg(i + 1)
                            .arg(fileInfoSrc.fileName())
                            .arg(fileInfoDst.fileName());
        QString qsMsg2 = QString("已完成%1%").arg((i + 1) * 100 / m_fileInfoList.size());
        emit setPosSignal(m_nID,
                          qsMsg,
                          qsMsg2,
                          fileInfo.fileName(),
                          i,
                          m_fileInfoList.size(),
                          formatSize(m_filesizesAll));
        if (fileInfo.isDir()) {
            QDir dstDir(copyList.dstPath);
            if (!dstDir.mkdir(dstDir.absolutePath())) {
                emit endSignal(m_nID);
                return;
            }
        } else {
            QFile file(copyList.dstPath);
            if (coverFileIfExist && file.exists()) {
                file.remove();
            }
            //进行文件copy
            QFile::copy(copyList.srcPath, copyList.dstPath);
        }
    }
    emit endSignal(m_nID);
}

void QThreadWork::getDirectoryList(const QString &srcPath, const QString &dstPath)
{
    QFileInfo fileInfoSrc(m_srcPath);
    QFileInfo fileInfoDst(m_dstPath);
    QDir srcDir(srcPath);
    QDir dstDir(dstPath);
    if (!m_bInit)
        return;
    if (!dstDir.exists()) {
        CopyList c;
        c.srcPath = srcPath;
        c.dstPath = dstPath;
        QFileInfo fileInfoTemp(srcPath);
        QString qsSuffix = fileInfoTemp.suffix();
        if (qsSuffix.toLower() != "lnk") //如果是
        {
            m_fileInfoList.append(c);
            m_filesizesAll += fileInfoTemp.size();
            QString qsMsg = QString("正在准备从%1复制到%2")
                                .arg(fileInfoSrc.fileName())
                                .arg(fileInfoDst.fileName());
            QString qsMsg2 = QString("已发现%1个项目(%2)...")
                                 .arg(m_fileInfoList.size())
                                 .arg(formatSize(m_filesizesAll));
            emit setPosSignal(m_nID,
                              qsMsg,
                              qsMsg2,
                              "",
                              -1,
                              m_fileInfoList.size(),
                              formatSize(m_filesizesAll));
        }
    }
    QFileInfoList fileInfoList = srcDir.entryInfoList();
    foreach (QFileInfo fileInfo, fileInfoList) {
        if (!m_bInit)
            return;
        if (fileInfo.fileName() == "." || fileInfo.fileName() == "..")
            continue;
        QString qsSuffix = fileInfo.suffix();
        if (fileInfo.isDir() && qsSuffix.toLower() != "lnk") { // 当为目录时,递归的进行copy
            getDirectoryList(fileInfo.filePath(), dstDir.filePath(fileInfo.fileName()));
        } else { //当允许覆盖操作时,将旧文件进行删除操作
            CopyList c;
            c.srcPath = fileInfo.filePath();
            c.dstPath = dstDir.filePath(fileInfo.fileName());
            QFileInfo fileInfoTemp(c.srcPath);
            QString qsSuffix = fileInfoTemp.suffix();
            if (qsSuffix.toLower() == "link")
                continue;
            m_fileInfoList.append(c);
            m_filesizesAll += fileInfoTemp.size();
            QString qsMsg = QString("正在准备从%1复制到%2")
                                .arg(fileInfoSrc.fileName())
                                .arg(fileInfoDst.fileName());
            QString qsMsg2 = QString("已发现%1个项目(%2)...")
                                 .arg(m_fileInfoList.size())
                                 .arg(formatSize(m_filesizesAll));
            emit setPosSignal(m_nID,
                              qsMsg,
                              qsMsg2,
                              "",
                              -1,
                              m_fileInfoList.size(),
                              formatSize(m_filesizesAll));
        }
    }
}

QString QThreadWork::formatSize(quint64 ullSize)
{
    QString qsReturn;
    if (ullSize >= 1024 * 1024 * 1024) {
        qsReturn = QString("%1 %2")
                       .arg(DoubleToQString(((double) ullSize) / (1024 * 1024 * 1024), 1))
                       .arg("GB");
    } else if (ullSize >= 1024 * 1024) {
        qsReturn
            = QString("%1 %2").arg(DoubleToQString(((double) ullSize) / (1024 * 1024), 1)).arg("MB");
    } else if (ullSize >= 1024) {
        qsReturn = QString("%1 %2").arg(DoubleToQString(((double) ullSize) / 1024, 1)).arg("KB");
    } else
        qsReturn = QString("%1 %2").arg(ullSize).arg("Byte");
    return qsReturn;
}
SplitLine.h
#ifndef SPLITLINE_H
#define SPLITLINE_H

#include 

class SplitLine : public QFrame
{
    Q_OBJECT
public:
    SplitLine(QWidget *parent = 0);
    QFrame *frame;
public slots:
    int setHorizontalVertical(int i = 0);
};

#endif // SPLITLINE_H
SplitLine.cpp
#include "splitline.h"

#include 

SplitLine::SplitLine(QWidget *parent)
    : QFrame(parent)
{
    frame = new QFrame(this);
    setHorizontalVertical(0); //默认为水平分割
    frame->setAutoFillBackground(true);
    frame->setMaximumHeight(2);
    frame->setStyleSheet("border:1px solid rgb(18, 150, 219)");
    QVBoxLayout *pMainVBoxLayout = new QVBoxLayout;
    pMainVBoxLayout->setMargin(0);
    pMainVBoxLayout->addWidget(frame);
    setLayout(pMainVBoxLayout);
}

int SplitLine::setHorizontalVertical(int i)
{
    if (i == 1) {
        frame->setFrameShape(QFrame::VLine); // 垂直分割线
        frame->setFrameShadow(QFrame::Plain);
    } else {
        frame->setFrameShape(QFrame::HLine);
        frame->setFrameShadow(QFrame::Plain);
    }
    return i;
}

你可能感兴趣的:(C++,QT,qt,c++,开发语言)