1 /***************************************************************************
2   qgscopyfiletask.cpp
3   --------------------------------------
4   Date                 : March 2021
5   Copyright            : (C) 2021 by Julien Cabieces
6   Email                : julien dot cabieces at oslandia dot com
7  ***************************************************************************
8  *                                                                         *
9  *   This program is free software; you can redistribute it and/or modify  *
10  *   it under the terms of the GNU General Public License as published by  *
11  *   the Free Software Foundation; either version 2 of the License, or     *
12  *   (at your option) any later version.                                   *
13  *                                                                         *
14  ***************************************************************************/
15 
16 #include "qgscopyfiletask.h"
17 
18 #include <QFile>
19 #include <QFileInfo>
20 #include <QDir>
21 
QgsCopyFileTask(const QString & source,const QString & destination)22 QgsCopyFileTask::QgsCopyFileTask( const QString &source, const QString &destination )
23   : mSource( source ),
24     mDestination( destination )
25 {
26 }
27 
run()28 bool QgsCopyFileTask::run()
29 {
30   QFile fileSource( mSource );
31   if ( !fileSource.exists() )
32   {
33     mErrorString = tr( "Source file '%1' does not exist" ).arg( mSource );
34     return false;
35   }
36 
37   if ( QFileInfo( mDestination ).isDir() )
38   {
39     mDestination = QDir( mDestination ).absoluteFilePath( QFileInfo( fileSource ).fileName() );
40   }
41 
42   QFile fileDestination( mDestination );
43   if ( fileDestination.exists() )
44   {
45     mErrorString = tr( "Destination file '%1' already exist" ).arg( mDestination );
46     return false;
47   }
48 
49   const QDir destinationDir = QFileInfo( mDestination ).absoluteDir();
50   if ( !destinationDir.exists() )
51   {
52     mErrorString = tr( "Destination directory '%1' does not exist" ).arg( destinationDir.absolutePath() );
53     return false;
54   }
55 
56   fileSource.open( QIODevice::ReadOnly );
57   fileDestination.open( QIODevice::WriteOnly );
58 
59   const int size = fileSource.size();
60   const int chunkSize = std::clamp( size / 100, 1024, 1024 * 1024 );
61 
62   int bytesRead = 0;
63   std::vector<char> data( chunkSize );
64   while ( true )
65   {
66     const int len = fileSource.read( data.data(), chunkSize );
67     if ( len == -1 )
68     {
69       mErrorString = tr( "Fail reading from '%1'" ).arg( mSource );
70       return false;
71     }
72 
73     // finish reading
74     if ( !len )
75       break;
76 
77     if ( fileDestination.write( data.data(), len ) != len )
78     {
79       mErrorString = tr( "Fail writing to '%1'" ).arg( mDestination );
80       return false;
81     }
82 
83     bytesRead += len;
84     setProgress( static_cast<double>( bytesRead ) / size );
85   }
86 
87   setProgress( 100 );
88 
89   fileSource.close();
90   fileDestination.close();
91 
92   return true;
93 }
94 
errorString() const95 const QString &QgsCopyFileTask::errorString() const
96 {
97   return mErrorString;
98 }
99 
destination() const100 const QString &QgsCopyFileTask::destination() const
101 {
102   return mDestination;
103 }
104