update copy function
parent
dc26fdc78a
commit
a79d319dbd
@ -0,0 +1,129 @@
|
||||
#include "ccopier.h"
|
||||
|
||||
|
||||
static QString toString(HRESULT hr)
|
||||
{
|
||||
_com_error err{hr};
|
||||
return QStringLiteral("Error 0x%1: %2").arg((quint32)hr, 8, 16, QLatin1Char('0')).arg(err.ErrorMessage());
|
||||
}
|
||||
|
||||
static QString getLastErrorMsg()
|
||||
{
|
||||
return toString(HRESULT_FROM_WIN32(GetLastError()));
|
||||
}
|
||||
|
||||
cCopier::cCopier(const QString& src, const QString& dst, QObject* parent) :
|
||||
QObject(parent),
|
||||
m_src(src),
|
||||
m_dst(dst)
|
||||
{
|
||||
}
|
||||
|
||||
cCopier::~cCopier()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
void cCopier::stop()
|
||||
{
|
||||
resume();
|
||||
m_stop = TRUE;
|
||||
}
|
||||
|
||||
void cCopier::pause()
|
||||
{
|
||||
m_pause = true;
|
||||
}
|
||||
|
||||
void cCopier::resume()
|
||||
{
|
||||
if(m_pause)
|
||||
m_pauseWait.notify_one();
|
||||
m_pause = false;
|
||||
}
|
||||
|
||||
void cCopier::newStatus(ULONGLONG part, ULONGLONG whole)
|
||||
{
|
||||
if(part != m_lastPart || whole != m_lastWhole)
|
||||
{
|
||||
m_lastPart = part;
|
||||
m_lastWhole = whole;
|
||||
emit newStatus(static_cast<int>(part*100/whole));
|
||||
}
|
||||
}
|
||||
|
||||
#if _WIN32_WINNT >= _WIN32_WINNT_WIN8
|
||||
void cCopier::copy()
|
||||
{
|
||||
m_lastPart = m_lastWhole = {};
|
||||
m_stop = FALSE;
|
||||
m_pause = false;
|
||||
QtConcurrent::run([this]
|
||||
{
|
||||
COPYFILE2_EXTENDED_PARAMETERS params
|
||||
{
|
||||
sizeof(COPYFILE2_EXTENDED_PARAMETERS), 0, &m_stop,
|
||||
Copier::copyProgress2, this
|
||||
};
|
||||
auto rc = CopyFile2((PCWSTR)m_src.utf16(), (PCWSTR)m_dst.utf16(), ¶ms);
|
||||
if(!SUCCEEDED(rc))
|
||||
emit newStatus(toString(rc));
|
||||
emit finished();
|
||||
});
|
||||
}
|
||||
|
||||
COPYFILE2_MESSAGE_ACTION CALLBACK cCopier::copyProgress2(const COPYFILE2_MESSAGE *message, PVOID context)
|
||||
{
|
||||
COPYFILE2_MESSAGE_ACTION action = COPYFILE2_PROGRESS_CONTINUE;
|
||||
auto self = static_cast<Copier*>(context);
|
||||
|
||||
if(message->Type == COPYFILE2_CALLBACK_CHUNK_FINISHED)
|
||||
{
|
||||
auto& info = message->Info.ChunkFinished;
|
||||
self->newStatus(info.uliTotalBytesTransferred.QuadPart, info.uliTotalFileSize.QuadPart);
|
||||
}
|
||||
else if (message->Type == COPYFILE2_CALLBACK_ERROR)
|
||||
{
|
||||
auto& info = message->Info.Error;
|
||||
self->newStatus(info.uliTotalBytesTransferred.QuadPart, info.uliTotalFileSize.QuadPart);
|
||||
emit self->newStatus(toString(info.hrFailure));
|
||||
action = COPYFILE2_PROGRESS_CANCEL;
|
||||
}
|
||||
|
||||
if(self->m_pause)
|
||||
{
|
||||
QMutexLocker lock{&self->m_pauseMutex};
|
||||
self->m_pauseWait.wait(&self->m_pauseMutex);
|
||||
}
|
||||
return action;
|
||||
}
|
||||
#else
|
||||
void cCopier::copy()
|
||||
{
|
||||
m_lastPart = m_lastWhole = {};
|
||||
m_stop = FALSE;
|
||||
m_pause = false;
|
||||
QtConcurrent::run([this]
|
||||
{
|
||||
auto rc = CopyFileExW((LPCWSTR)m_src.utf16(), (LPCWSTR)m_dst.utf16(), ©Progress, this, &m_stop, 0);
|
||||
if(!rc)
|
||||
{
|
||||
qDebug() << getLastErrorMsg();
|
||||
emit newStatus(-1);
|
||||
}
|
||||
emit finished();
|
||||
});
|
||||
}
|
||||
|
||||
DWORD CALLBACK cCopier::copyProgress(const LARGE_INTEGER totalSize, const LARGE_INTEGER totalTransferred, LARGE_INTEGER, LARGE_INTEGER, DWORD, DWORD, HANDLE, HANDLE, LPVOID data)
|
||||
{
|
||||
auto self = static_cast<cCopier*>(data);
|
||||
self->newStatus(totalTransferred.QuadPart, totalSize.QuadPart);
|
||||
if(self->m_pause)
|
||||
{
|
||||
QMutexLocker lock{&self->m_pauseMutex};
|
||||
self->m_pauseWait.wait(&self->m_pauseMutex);
|
||||
}
|
||||
return PROGRESS_CONTINUE;
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,49 @@
|
||||
#ifndef CCOPIER_H
|
||||
#define CCOPIER_H
|
||||
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <QtConcurrent>
|
||||
#include <windows.h>
|
||||
#include <comdef.h>
|
||||
|
||||
|
||||
class cCopier : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
BOOL m_stop;
|
||||
QMutex m_pauseMutex;
|
||||
QAtomicInt m_pause;
|
||||
QWaitCondition m_pauseWait;
|
||||
|
||||
QString m_src;
|
||||
QString m_dst;
|
||||
ULONGLONG m_lastPart;
|
||||
ULONGLONG m_lastWhole;
|
||||
|
||||
void newStatus(ULONGLONG part, ULONGLONG whole);
|
||||
|
||||
#if _WIN32_WINNT >= _WIN32_WINNT_WIN8
|
||||
static COPYFILE2_MESSAGE_ACTION CALLBACK copyProgress2(const COPYFILE2_MESSAGE *message, PVOID context);
|
||||
#else
|
||||
static DWORD CALLBACK copyProgress(LARGE_INTEGER totalSize, LARGE_INTEGER totalTransferred, LARGE_INTEGER streamSize, LARGE_INTEGER streamTransferred, DWORD streamNo, DWORD callbackReason, HANDLE src, HANDLE dst, LPVOID data);
|
||||
#endif
|
||||
|
||||
public:
|
||||
explicit cCopier(const QString& src, const QString& dst, QObject* parent = nullptr);
|
||||
~cCopier() override;
|
||||
|
||||
signals:
|
||||
void newStatus(int percent);
|
||||
void finished();
|
||||
|
||||
public slots:
|
||||
void copy();
|
||||
void stop();
|
||||
void pause();
|
||||
void resume();
|
||||
};
|
||||
|
||||
#endif // CCOPIER_H
|
||||
Loading…
Reference in New Issue