QGIS API Documentation  3.20.0-Odense (decaadbb31)
qgsnetworkcontentfetcherregistry.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsnetworkcontentfetcherregistry.cpp
3  -------------------
4  begin : April, 2018
5  copyright : (C) 2018 by Denis Rouzaud
6  email : [email protected]
7 
8  ***************************************************************************/
9 
10 /***************************************************************************
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  ***************************************************************************/
18 
20 
21 #include "qgsapplication.h"
22 #include <QUrl>
23 
25 {
26  QMap<QString, QgsFetchedContent *>::const_iterator it = mFileRegistry.constBegin();
27  for ( ; it != mFileRegistry.constEnd(); ++it )
28  {
29  delete it.value();
30  }
31  mFileRegistry.clear();
32 }
33 
34 const QgsFetchedContent *QgsNetworkContentFetcherRegistry::fetch( const QString &url, const FetchingMode fetchingMode )
35 {
36 
37  if ( mFileRegistry.contains( url ) )
38  {
39  return mFileRegistry.value( url );
40  }
41 
43 
44  mFileRegistry.insert( url, content );
45 
46  if ( fetchingMode == DownloadImmediately )
47  content->download();
48 
49 
50  return content;
51 }
52 
53 QFile *QgsNetworkContentFetcherRegistry::localFile( const QString &filePathOrUrl )
54 {
55  QFile *file = nullptr;
56  QString path = filePathOrUrl;
57 
58  if ( !QUrl::fromUserInput( filePathOrUrl ).isLocalFile() )
59  {
60  if ( mFileRegistry.contains( path ) )
61  {
62  const QgsFetchedContent *content = mFileRegistry.value( path );
63  if ( content && content->status() == QgsFetchedContent::Finished && content->file() )
64  {
65  file = content->file();
66  }
67  else
68  {
69  // if the file is not downloaded yet or has failed, return nullptr
70  }
71  }
72  else
73  {
74  // if registry doesn't contain the URL, return nullptr
75  }
76  }
77  else
78  {
79  file = new QFile( filePathOrUrl );
80  }
81  return file;
82 }
83 
84 QString QgsNetworkContentFetcherRegistry::localPath( const QString &filePathOrUrl )
85 {
86  QString path = filePathOrUrl;
87 
88  if ( !QUrl::fromUserInput( filePathOrUrl ).isLocalFile() )
89  {
90  if ( mFileRegistry.contains( path ) )
91  {
92  const QgsFetchedContent *content = mFileRegistry.value( path );
93  if ( content->status() == QgsFetchedContent::Finished && !content->filePath().isEmpty() )
94  {
95  path = content->filePath();
96  }
97  else
98  {
99  // if the file is not downloaded yet or has failed, return empty string
100  path = QString();
101  }
102  }
103  else
104  {
105  // if registry doesn't contain the URL, keep path unchanged
106  }
107  }
108  return path;
109 }
110 
111 
112 
113 
114 void QgsFetchedContent::download( bool redownload )
115 {
116 
117  if ( redownload && status() == QgsFetchedContent::Downloading )
118  {
119  {
120  if ( mFetchingTask )
121  disconnect( mFetchingTask, &QgsNetworkContentFetcherTask::taskCompleted, this, &QgsFetchedContent::taskCompleted );
122  }
123  cancel();
124  }
125  if ( redownload ||
128  {
129  mFetchingTask = new QgsNetworkContentFetcherTask( mUrl );
130  // use taskCompleted which is main thread rather than fetched signal in worker thread
131  connect( mFetchingTask, &QgsNetworkContentFetcherTask::taskCompleted, this, &QgsFetchedContent::taskCompleted );
132  QgsApplication::instance()->taskManager()->addTask( mFetchingTask );
134  }
135 
136 }
137 
139 {
140  if ( mFetchingTask && mFetchingTask->canCancel() )
141  {
142  mFetchingTask->cancel();
143  }
144  if ( mFile )
145  {
146  mFile->deleteLater();
147  mFilePath = QString();
148  }
149 }
150 
151 
152 void QgsFetchedContent::taskCompleted()
153 {
154  if ( !mFetchingTask || !mFetchingTask->reply() )
155  {
156  // if no reply, it has been canceled
157  mStatus = QgsFetchedContent::Failed;
158  mError = QNetworkReply::OperationCanceledError;
159  mFilePath = QString();
160  }
161  else
162  {
163  QNetworkReply *reply = mFetchingTask->reply();
164  if ( reply->error() == QNetworkReply::NoError )
165  {
166  QTemporaryFile *tf = new QTemporaryFile( QStringLiteral( "XXXXXX" ) );
167  mFile = tf;
168  tf->open();
169  mFile->write( reply->readAll() );
170  // Qt docs notes that on some system if fileName is not called before close, file might get deleted
171  mFilePath = tf->fileName();
172  tf->close();
173  mStatus = QgsFetchedContent::Finished;
174  }
175  else
176  {
177  mStatus = QgsFetchedContent::Failed;
178  mError = reply->error();
179  mFilePath = QString();
180  }
181  }
182 
183  emit fetched();
184 }
static QgsApplication * instance()
Returns the singleton instance of the QgsApplication.
static QgsTaskManager * taskManager()
Returns the application's task manager, used for managing application wide background task handling.
FetchedContent holds useful information about a network content being fetched.
ContentStatus status() const
Returns the status of the download.
QFile * file() const
Returns a pointer to the local file, or nullptr if the file is not accessible yet.
void download(bool redownload=false)
Start the download.
const QString filePath() const
Returns the path to the local file, an empty string if the file is not accessible yet.
@ Finished
Download finished and successful.
@ NotStarted
No download started for such URL.
@ Downloading
Currently downloading.
void fetched()
Emitted when the file is fetched and accessible.
void cancel()
Cancel the download operation.
QString localPath(const QString &filePathOrUrl)
Returns the path to a local file or to a temporary file previously fetched by the registry.
QFile * localFile(const QString &filePathOrUrl)
Returns a QFile from a local file or to a temporary file previously fetched by the registry.
const QgsFetchedContent * fetch(const QString &url, FetchingMode fetchingMode=DownloadLater)
Initialize a download for the given URL.
FetchingMode
Enum to determine when the download should start.
@ DownloadImmediately
The download will start immediately, not need to run QgsFecthedContent::download()
Handles HTTP network content fetching in a background task.
QNetworkReply * reply()
Returns the network reply.
void cancel() override
Notifies the task that it should terminate.
long addTask(QgsTask *task, int priority=0)
Adds a task to the manager.
void taskCompleted()
Will be emitted by task to indicate its successful completion.
bool canCancel() const
Returns true if the task can be canceled.