QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgsalgorithmfiledownloader.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsalgorithmfiledownloader.cpp
3  ---------------------
4  begin : October 2017
5  copyright : (C) 2017 by Etienne Trimaille
6  email : etienne at kartoza dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
19 #include "qgsfiledownloader.h"
20 #include "qgsfileutils.h"
21 #include <QEventLoop>
22 #include <QFileInfo>
23 #include <QTimer>
24 #include <QUrl>
25 
27 
28 QString QgsFileDownloaderAlgorithm::name() const
29 {
30  return QStringLiteral( "filedownloader" );
31 }
32 
33 QString QgsFileDownloaderAlgorithm::displayName() const
34 {
35  return tr( "Download file" );
36 }
37 
38 QStringList QgsFileDownloaderAlgorithm::tags() const
39 {
40  return tr( "file,downloader,internet,url,fetch,get,https" ).split( ',' );
41 }
42 
43 QString QgsFileDownloaderAlgorithm::group() const
44 {
45  return tr( "File tools" );
46 }
47 
48 QString QgsFileDownloaderAlgorithm::groupId() const
49 {
50  return QStringLiteral( "filetools" );
51 }
52 
53 QString QgsFileDownloaderAlgorithm::shortHelpString() const
54 {
55  return tr( "This algorithm downloads a URL on the file system." );
56 }
57 
58 QgsFileDownloaderAlgorithm *QgsFileDownloaderAlgorithm::createInstance() const
59 {
60  return new QgsFileDownloaderAlgorithm();
61 }
62 
63 void QgsFileDownloaderAlgorithm::initAlgorithm( const QVariantMap & )
64 {
65  addParameter( new QgsProcessingParameterString( QStringLiteral( "URL" ), tr( "URL" ), QVariant(), false, false ) );
66  addParameter( new QgsProcessingParameterFileDestination( QStringLiteral( "OUTPUT" ),
67  tr( "File destination" ), QObject::tr( "All files (*.*)" ), QVariant(), true ) );
68 }
69 
70 QVariantMap QgsFileDownloaderAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
71 {
72  mFeedback = feedback;
73  QString url = parameterAsString( parameters, QStringLiteral( "URL" ), context );
74  if ( url.isEmpty() )
75  throw QgsProcessingException( tr( "No URL specified" ) );
76  QString outputFile = parameterAsFileOutput( parameters, QStringLiteral( "OUTPUT" ), context );
77 
78  QEventLoop loop;
79  QTimer timer;
80  QgsFileDownloader *downloader = new QgsFileDownloader( QUrl( url ), outputFile, QString(), true );
81  connect( mFeedback, &QgsFeedback::canceled, downloader, &QgsFileDownloader::cancelDownload );
82  connect( downloader, &QgsFileDownloader::downloadError, this, &QgsFileDownloaderAlgorithm::reportErrors );
83  connect( downloader, &QgsFileDownloader::downloadProgress, this, &QgsFileDownloaderAlgorithm::receiveProgressFromDownloader );
84  connect( downloader, &QgsFileDownloader::downloadExited, &loop, &QEventLoop::quit );
85  connect( &timer, &QTimer::timeout, this, &QgsFileDownloaderAlgorithm::sendProgressFeedback );
86  downloader->startDownload();
87  timer.start( 1000 );
88 
89  loop.exec();
90 
91  timer.stop();
92  bool exists = QFileInfo::exists( outputFile );
93  if ( !feedback->isCanceled() && !exists )
94  throw QgsProcessingException( tr( "Output file doesn't exist." ) );
95 
96  QVariantMap outputs;
97  outputs.insert( QStringLiteral( "OUTPUT" ), exists ? outputFile : QString() );
98  return outputs;
99 }
100 
101 void QgsFileDownloaderAlgorithm::reportErrors( const QStringList &errors )
102 {
103  throw QgsProcessingException( errors.join( '\n' ) );
104 }
105 
106 void QgsFileDownloaderAlgorithm::sendProgressFeedback()
107 {
108  if ( !mReceived.isEmpty() && mLastReport != mReceived )
109  {
110  mLastReport = mReceived;
111  if ( mTotal.isEmpty() )
112  mFeedback->pushInfo( tr( "%1 downloaded." ).arg( mReceived ) );
113  else
114  mFeedback->pushInfo( tr( "%1 of %2 downloaded." ).arg( mReceived, mTotal ) );
115  }
116 }
117 
118 void QgsFileDownloaderAlgorithm::receiveProgressFromDownloader( qint64 bytesReceived, qint64 bytesTotal )
119 {
120  mReceived = QgsFileUtils::representFileSize( bytesReceived );
121  if ( bytesTotal > 0 )
122  {
123  if ( mTotal.isEmpty() )
124  mTotal = QgsFileUtils::representFileSize( bytesTotal );
125 
126  mFeedback->setProgress( ( bytesReceived * 100 ) / bytesTotal );
127  }
128 }
129 
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
void startDownload()
Called to start the download.
Base class for providing feedback from a processing algorithm.
void canceled()
Internal routines can connect to this signal if they use event loop.
static QString representFileSize(qint64 bytes)
Returns the human size from bytes.
Custom exception class for processing related exceptions.
Definition: qgsexception.h:82
A generic file based destination parameter, for specifying the destination path for a file (non-map l...
QgsFileDownloader is a utility class for downloading files.
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
Emitted when data are ready to be processed.
void downloadError(QStringList errorMessages)
Emitted when an error makes the download fail.
Contains information about the context in which a processing algorithm is executed.
void cancelDownload()
Call to abort the download and delete this object after the cancellation has been processed...
void downloadExited()
Emitted always when the downloader exits.
A string parameter for processing algorithms.