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