Qt 如何在QFutureWatcher中清除QFuture结果
我试图一次阻止多个文件,然后将它们复制到另一个位置 应同时阻止源文件和目标文件。因此,我不能使用Qt 如何在QFutureWatcher中清除QFuture结果,qt,c++14,shared-ptr,future,qtconcurrent,Qt,C++14,Shared Ptr,Future,Qtconcurrent,我试图一次阻止多个文件,然后将它们复制到另一个位置 应同时阻止源文件和目标文件。因此,我不能使用静态QFile::copy()函数 为了保存和移动文件,我使用QSharedPointer,因为QFile既不可复制也不可移动 为了完全执行整个操作,我使用QtConcurrent框架。即:QtConcurrent::mappedReduced和QFutureWatcher 要打开所有文件对,我使用“贴图函子”,然后要按顺序复制它们,我使用“减少函子” 使用PFile=QSharedPointer;
静态QFile::copy()
函数
为了保存和移动文件,我使用QSharedPointer
,因为QFile
既不可复制也不可移动
为了完全执行整个操作,我使用QtConcurrent
框架。即:QtConcurrent::mappedReduced
和QFutureWatcher
要打开所有文件对,我使用“贴图函子”,然后要按顺序复制它们,我使用“减少函子”
使用PFile=QSharedPointer;
使用PFileList=QList;
模板
结构函数WithResultType
:std::衰变\u t<函子>
{
使用结果类型=结果;
FunctorWithResultType(Functor和Functor)
:std::decation\u t{std::forward(Functor)}
{ ; }
};
模板
FunctorWithResultType
addResultType(Functor&&Functor)
{
返回{函子};
}
课堂测试
{
公众:
QDir目录;
QFutureWatcherfileCopyFutureWatcher;
// ...
};
// ...
Test::Test()
{
自动onfilescomped=[&]
{
PFileList copiedFiles=fileCopyFutureWatcher.result();
qCInfo(usbDevice)我的解决方案如下所示:
using PFile = QSharedPointer< QFile >;
using PFileList = QList< PFile >;
template< typename Result, typename Functor >
struct FunctorWithResultType
: std::decay_t< Functor >
{
using result_type = Result;
FunctorWithResultType(Functor & functor)
: std::decay_t< Functor >{std::forward< Functor >(functor)}
{ ; }
};
template< typename Result, typename Functor >
FunctorWithResultType< Result, Functor >
addResultType(Functor && functor)
{
return {functor};
}
class Test
{
public :
QDir currentDirectory;
// ...
};
// ...
void Test::onDeviceAdded(QString deviceName)
{
qCInfo(usbDevice) << "USB device" << deviceName << "is added.";
QDir sourceDirectory{deviceName};
if (!sourceDirectory.cd("dir")) {
qCInfo(usbDevice) << "Drive" << deviceName << "does not contain dir subdirectory.";
return;
}
auto destinationDirectory = currentDirectory;
if (!destinationDirectory.mkpath("fileCache")) {
qCCritical(usbDevice) << "Can't create fileCache subdirectory in"
<< destinationDirectory.absolutePath()
<< "directory";
return;
}
if (!destinationDirectory.cd("fileCache")) {
qCCritical(usbDevice) << "Can't change directory to fileCache subdirectory in"
<< destinationDirectory.absolutePath()
<< "directory";
return;
}
struct PFilePair
{
PFile source, destination;
};
auto openSourceAndDestinationFiles = [&, destinationDirectory] (QFileInfo const & fileInfo) -> PFilePair
{
auto source = PFile::create(fileInfo.absoluteFilePath());
QFile & sourceFile = *source;
if (!sourceFile.open(QFile::ReadOnly)) {
qCCritical(usbDevice) << "Can't open file" << sourceFile.fileName()
<< "to read:" << sourceFile.errorString();
return {};
}
auto destination = PFile::create(destinationDirectory.absoluteFilePath(fileInfo.fileName()));
QFile & destinationFile = *destination;;
if (!destinationFile.open(QFile::ReadWrite | QFile::Truncate)) {
qCCritical(usbDevice) << "Can't open file" << destinationFile.fileName()
<< "to write:" << destinationFile.errorString();
return {};
}
return {qMove(source), qMove(destination)};
};
auto copyFiles = [&] (PFileList & files, PFilePair const & filePair)
{
if (filePair.source.isNull() || filePair.destination.isNull()) {
return;
}
QFile & sourceFile = *filePair.source;
QFile & destinationFile = *filePair.destination;
qCInfo(usbDevice) << sourceFile.fileName() << "->" << destinationFile.fileName();
constexpr int size = (1 << 20); // 1MiB
QByteArray buffer{size, 0};
char * const data = buffer.data();
while (!sourceFile.atEnd()) {
auto bytesRead = sourceFile.read(data, size);
if (bytesRead < 0) {
qCCritical(usbDevice) << "Can't read file" << sourceFile.fileName()
<< ":" << sourceFile.errorString();
return;
}
auto bytesWritten = destinationFile.write(data, bytesRead);
while (bytesWritten < bytesRead) {
auto sizeWritten = destinationFile.write(data + bytesWritten, bytesRead - bytesWritten);
if (sizeWritten < 0) {
qCCritical(usbDevice) << "Can't write file" << destinationFile.fileName()
<< ":" << destinationFile.errorString();
return;
}
bytesWritten += sizeWritten;
}
Q_ASSERT(bytesWritten == bytesRead);
}
Q_ASSERT(sourceFile.size() == destinationFile.size());
destinationFile.flush();
files.append(filePair.destination);
};
auto & fileCopyFutureWatcher = *new QFutureWatcher< PFileList >{this};
auto onFilesCopied = [&]
{
fileCopyFutureWatcher.deleteLater();
PFileList copiedFiles = fileCopyFutureWatcher.result();
qCInfo(usbDevice) << "Files copy operation from drive finished.";
qCInfo(usbDevice) << copiedFiles.size();
for (PFile const & file : copiedFiles) {
// ...
}
};
connect(&fileCopyFutureWatcher, &fileCopyFutureWatcher.finished, onFilesCopied);
QStringList nameFilters;
nameFilters << "*.dat";
auto entryInfoList = sourceDirectory.entryInfoList(nameFilters, (QDir::Readable | QDir::Files));
fileCopyFutureWatcher.setFuture(QtConcurrent::mappedReduced< PFileList >(qMove(entryInfoList), addResultType< PFilePair >(openSourceAndDestinationFiles), copyFiles));
}
// ...
使用PFile=QSharedPointer;
使用PFileList=QList;
模板
结构函数WithResultType
:std::衰变\u t<函子>
{
使用结果类型=结果;
FunctorWithResultType(Functor和Functor)
:std::decation\u t{std::forward(Functor)}
{ ; }
};
模板
FunctorWithResultType
addResultType(Functor&&Functor)
{
返回{函子};
}
课堂测试
{
公众:
QDir目录;
// ...
};
// ...
无效测试::onDeviceAdded(QString deviceName)
{
qCInfo(usbDevice)
using PFile = QSharedPointer< QFile >;
using PFileList = QList< PFile >;
template< typename Result, typename Functor >
struct FunctorWithResultType
: std::decay_t< Functor >
{
using result_type = Result;
FunctorWithResultType(Functor & functor)
: std::decay_t< Functor >{std::forward< Functor >(functor)}
{ ; }
};
template< typename Result, typename Functor >
FunctorWithResultType< Result, Functor >
addResultType(Functor && functor)
{
return {functor};
}
class Test
{
public :
QDir currentDirectory;
// ...
};
// ...
void Test::onDeviceAdded(QString deviceName)
{
qCInfo(usbDevice) << "USB device" << deviceName << "is added.";
QDir sourceDirectory{deviceName};
if (!sourceDirectory.cd("dir")) {
qCInfo(usbDevice) << "Drive" << deviceName << "does not contain dir subdirectory.";
return;
}
auto destinationDirectory = currentDirectory;
if (!destinationDirectory.mkpath("fileCache")) {
qCCritical(usbDevice) << "Can't create fileCache subdirectory in"
<< destinationDirectory.absolutePath()
<< "directory";
return;
}
if (!destinationDirectory.cd("fileCache")) {
qCCritical(usbDevice) << "Can't change directory to fileCache subdirectory in"
<< destinationDirectory.absolutePath()
<< "directory";
return;
}
struct PFilePair
{
PFile source, destination;
};
auto openSourceAndDestinationFiles = [&, destinationDirectory] (QFileInfo const & fileInfo) -> PFilePair
{
auto source = PFile::create(fileInfo.absoluteFilePath());
QFile & sourceFile = *source;
if (!sourceFile.open(QFile::ReadOnly)) {
qCCritical(usbDevice) << "Can't open file" << sourceFile.fileName()
<< "to read:" << sourceFile.errorString();
return {};
}
auto destination = PFile::create(destinationDirectory.absoluteFilePath(fileInfo.fileName()));
QFile & destinationFile = *destination;;
if (!destinationFile.open(QFile::ReadWrite | QFile::Truncate)) {
qCCritical(usbDevice) << "Can't open file" << destinationFile.fileName()
<< "to write:" << destinationFile.errorString();
return {};
}
return {qMove(source), qMove(destination)};
};
auto copyFiles = [&] (PFileList & files, PFilePair const & filePair)
{
if (filePair.source.isNull() || filePair.destination.isNull()) {
return;
}
QFile & sourceFile = *filePair.source;
QFile & destinationFile = *filePair.destination;
qCInfo(usbDevice) << sourceFile.fileName() << "->" << destinationFile.fileName();
constexpr int size = (1 << 20); // 1MiB
QByteArray buffer{size, 0};
char * const data = buffer.data();
while (!sourceFile.atEnd()) {
auto bytesRead = sourceFile.read(data, size);
if (bytesRead < 0) {
qCCritical(usbDevice) << "Can't read file" << sourceFile.fileName()
<< ":" << sourceFile.errorString();
return;
}
auto bytesWritten = destinationFile.write(data, bytesRead);
while (bytesWritten < bytesRead) {
auto sizeWritten = destinationFile.write(data + bytesWritten, bytesRead - bytesWritten);
if (sizeWritten < 0) {
qCCritical(usbDevice) << "Can't write file" << destinationFile.fileName()
<< ":" << destinationFile.errorString();
return;
}
bytesWritten += sizeWritten;
}
Q_ASSERT(bytesWritten == bytesRead);
}
Q_ASSERT(sourceFile.size() == destinationFile.size());
destinationFile.flush();
files.append(filePair.destination);
};
auto & fileCopyFutureWatcher = *new QFutureWatcher< PFileList >{this};
auto onFilesCopied = [&]
{
fileCopyFutureWatcher.deleteLater();
PFileList copiedFiles = fileCopyFutureWatcher.result();
qCInfo(usbDevice) << "Files copy operation from drive finished.";
qCInfo(usbDevice) << copiedFiles.size();
for (PFile const & file : copiedFiles) {
// ...
}
};
connect(&fileCopyFutureWatcher, &fileCopyFutureWatcher.finished, onFilesCopied);
QStringList nameFilters;
nameFilters << "*.dat";
auto entryInfoList = sourceDirectory.entryInfoList(nameFilters, (QDir::Readable | QDir::Files));
fileCopyFutureWatcher.setFuture(QtConcurrent::mappedReduced< PFileList >(qMove(entryInfoList), addResultType< PFilePair >(openSourceAndDestinationFiles), copyFiles));
}
// ...