QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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 #include <QFileInfo>
24 #include <QDir>
25 
27 {
28  QMap<QString, QgsFetchedContent *>::const_iterator it = mFileRegistry.constBegin();
29  for ( ; it != mFileRegistry.constEnd(); ++it )
30  {
31  delete it.value();
32  }
33  mFileRegistry.clear();
34 }
35 
36 QgsFetchedContent *QgsNetworkContentFetcherRegistry::fetch( const QString &url, const Qgis::ActionStart fetchingMode, const QString &authConfig )
37 {
38 
39  if ( mFileRegistry.contains( url ) )
40  {
41  return mFileRegistry.value( url );
42  }
43 
44  QgsFetchedContent *content = new QgsFetchedContent( url, nullptr, QgsFetchedContent::NotStarted, authConfig );
45 
46  mFileRegistry.insert( url, content );
47 
48  if ( fetchingMode == Qgis::ActionStart::Immediate )
49  content->download();
50 
51 
52  return content;
53 }
54 
55 QFile *QgsNetworkContentFetcherRegistry::localFile( const QString &filePathOrUrl )
56 {
57  QFile *file = nullptr;
58  const QString path = filePathOrUrl;
59 
60  if ( !QUrl::fromUserInput( filePathOrUrl ).isLocalFile() )
61  {
62  if ( mFileRegistry.contains( path ) )
63  {
64  const QgsFetchedContent *content = mFileRegistry.value( path );
65  if ( content && content->status() == QgsFetchedContent::Finished && content->file() )
66  {
67  file = content->file();
68  }
69  else
70  {
71  // if the file is not downloaded yet or has failed, return nullptr
72  }
73  }
74  else
75  {
76  // if registry doesn't contain the URL, return nullptr
77  }
78  }
79  else
80  {
81  file = new QFile( filePathOrUrl );
82  }
83  return file;
84 }
85 
86 QString QgsNetworkContentFetcherRegistry::localPath( const QString &filePathOrUrl )
87 {
88  QString path = filePathOrUrl;
89 
90  if ( !QUrl::fromUserInput( filePathOrUrl ).isLocalFile() )
91  {
92  if ( mFileRegistry.contains( path ) )
93  {
94  const QgsFetchedContent *content = mFileRegistry.value( path );
95  if ( content->status() == QgsFetchedContent::Finished && !content->filePath().isEmpty() )
96  {
97  path = content->filePath();
98  }
99  else
100  {
101  // if the file is not downloaded yet or has failed, return empty string
102  path = QString();
103  }
104  }
105  else
106  {
107  // if registry doesn't contain the URL, keep path unchanged
108  }
109  }
110  return path;
111 }
112 
113 
114 
115 
116 void QgsFetchedContent::download( bool redownload )
117 {
118 
119  if ( redownload && status() == QgsFetchedContent::Downloading )
120  {
121  {
122  if ( mFetchingTask )
123  disconnect( mFetchingTask, &QgsNetworkContentFetcherTask::taskCompleted, this, &QgsFetchedContent::taskCompleted );
124  }
125  cancel();
126  }
127  if ( redownload ||
130  {
131  mFetchingTask = new QgsNetworkContentFetcherTask( mUrl, mAuthConfig );
132  // use taskCompleted which is main thread rather than fetched signal in worker thread
133  connect( mFetchingTask, &QgsNetworkContentFetcherTask::taskCompleted, this, &QgsFetchedContent::taskCompleted );
134  connect( mFetchingTask, &QgsNetworkContentFetcherTask::taskTerminated, this, &QgsFetchedContent::taskCompleted );
136  QgsApplication::taskManager()->addTask( mFetchingTask );
138  }
139 
140 }
141 
143 {
144  if ( mFetchingTask && mFetchingTask->canCancel() )
145  {
146  mFetchingTask->cancel();
147  }
148  if ( mFile )
149  {
150  mFile->deleteLater();
151  mFilePath = QString();
152  }
153 }
154 
155 
156 void QgsFetchedContent::taskCompleted()
157 {
158  if ( !mFetchingTask || !mFetchingTask->reply() )
159  {
160  // if no reply, it has been canceled
161  mStatus = QgsFetchedContent::Failed;
162  mError = QNetworkReply::OperationCanceledError;
163  mFilePath = QString();
164  }
165  else
166  {
167  QNetworkReply *reply = mFetchingTask->reply();
168  if ( reply->error() == QNetworkReply::NoError )
169  {
170  // keep extension, it can be useful when guessing file content
171  // (when loading this file in a Qt WebView for instance)
172  const QString extension = QFileInfo( reply->request().url().fileName() ).completeSuffix();
173 
174  QTemporaryFile *tf = new QTemporaryFile( extension.isEmpty() ? QString( "XXXXXX" ) :
175  QString( "%1/XXXXXX.%2" ).arg( QDir::tempPath(), extension ) );
176  mFile = tf;
177  tf->open();
178  mFile->write( reply->readAll() );
179  // Qt docs notes that on some system if fileName is not called before close, file might get deleted
180  mFilePath = tf->fileName();
181  tf->close();
182  mStatus = QgsFetchedContent::Finished;
183  }
184  else
185  {
186  mStatus = QgsFetchedContent::Failed;
187  mError = reply->error();
188  mFilePath = QString();
189  }
190  }
191 
192  emit fetched();
193 }
QgsFetchedContent::file
QFile * file() const
Returns a pointer to the local file, or nullptr if the file is not accessible yet.
Definition: qgsnetworkcontentfetcherregistry.h:72
QgsNetworkContentFetcherRegistry::fetch
QgsFetchedContent * fetch(const QString &url, Qgis::ActionStart fetchingMode=Qgis::ActionStart::Deferred, const QString &authConfig=QString())
Initialize a download for the given URL.
Definition: qgsnetworkcontentfetcherregistry.cpp:36
QgsNetworkContentFetcherTask::reply
QNetworkReply * reply()
Returns the network reply.
Definition: qgsnetworkcontentfetchertask.cpp:88
QgsNetworkContentFetcherRegistry::~QgsNetworkContentFetcherRegistry
~QgsNetworkContentFetcherRegistry() override
Definition: qgsnetworkcontentfetcherregistry.cpp:26
QgsNetworkContentFetcherTask
Handles HTTP network content fetching in a background task.
Definition: qgsnetworkcontentfetchertask.h:47
Qgis::ActionStart
ActionStart
Enum to determine when an operation would begin.
Definition: qgis.h:521
QgsNetworkContentFetcherTask::cancel
void cancel() override
Notifies the task that it should terminate.
Definition: qgsnetworkcontentfetchertask.cpp:80
QgsTaskManager::addTask
long addTask(QgsTask *task, int priority=0)
Adds a task to the manager.
Definition: qgstaskmanager.cpp:420
QgsTask::taskCompleted
void taskCompleted()
Will be emitted by task to indicate its successful completion.
qgsapplication.h
qgsnetworkcontentfetcherregistry.h
QgsFetchedContent::Failed
@ Failed
Download failed.
Definition: qgsnetworkcontentfetcherregistry.h:50
QgsFetchedContent::Downloading
@ Downloading
Currently downloading.
Definition: qgsnetworkcontentfetcherregistry.h:48
QgsNetworkContentFetcherRegistry::localPath
QString localPath(const QString &filePathOrUrl)
Returns the path to a local file or to a temporary file previously fetched by the registry.
Definition: qgsnetworkcontentfetcherregistry.cpp:86
QgsTask::canCancel
bool canCancel() const
Returns true if the task can be canceled.
Definition: qgstaskmanager.h:106
QgsFetchedContent::NotStarted
@ NotStarted
No download started for such URL.
Definition: qgsnetworkcontentfetcherregistry.h:47
QgsFetchedContent::cancel
void cancel()
Cancel the download operation.
Definition: qgsnetworkcontentfetcherregistry.cpp:142
QgsApplication::taskManager
static QgsTaskManager * taskManager()
Returns the application's task manager, used for managing application wide background task handling.
Definition: qgsapplication.cpp:2300
QgsTask::taskTerminated
void taskTerminated()
Will be emitted by task if it has terminated for any reason other then completion (e....
QgsFetchedContent::status
ContentStatus status() const
Returns the status of the download.
Definition: qgsnetworkcontentfetcherregistry.h:79
QgsFetchedContent
FetchedContent holds useful information about a network content being fetched.
Definition: qgsnetworkcontentfetcherregistry.h:40
QgsNetworkContentFetcherRegistry::localFile
QFile * localFile(const QString &filePathOrUrl)
Returns a QFile from a local file or to a temporary file previously fetched by the registry.
Definition: qgsnetworkcontentfetcherregistry.cpp:55
QgsFetchedContent::Finished
@ Finished
Download finished and successful.
Definition: qgsnetworkcontentfetcherregistry.h:49
QgsFetchedContent::errorOccurred
void errorOccurred(QNetworkReply::NetworkError code, const QString &errorMsg)
Emitted when an error with code error occurred while processing the request errorMsg is a textual des...
QgsFetchedContent::download
void download(bool redownload=false)
Start the download.
Definition: qgsnetworkcontentfetcherregistry.cpp:116
QgsFetchedContent::fetched
void fetched()
Emitted when the file is fetched and accessible.
QgsFetchedContent::filePath
const QString filePath() const
Returns the path to the local file, an empty string if the file is not accessible yet.
Definition: qgsnetworkcontentfetcherregistry.h:76
QgsNetworkContentFetcherTask::errorOccurred
void errorOccurred(QNetworkReply::NetworkError code, const QString &errorMsg)
Emitted when an error with code error occurred while processing the request errorMsg is a textual des...