本例子利用线程进行文件拷贝,并且有界面显示,支持多文件夹复制。
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;
}