QGIS API Documentation  3.2.0-Bonn (bc43194)
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 }
26 
28 {
29  QMap<QString, QgsFetchedContent *>::const_iterator it = mFileRegistry.constBegin();
30  for ( ; it != mFileRegistry.constEnd(); ++it )
31  {
32  delete it.value();
33  }
34  mFileRegistry.clear();
35 }
36 
37 const QgsFetchedContent *QgsNetworkContentFetcherRegistry::fetch( const QString &url, const FetchingMode fetchingMode )
38 {
39 
40  if ( mFileRegistry.contains( url ) )
41  {
42  return mFileRegistry.value( url );
43  }
44 
46 
47  mFileRegistry.insert( url, content );
48 
49  if ( fetchingMode == DownloadImmediately )
50  content->download();
51 
52 
53  return content;
54 }
55 
56 QFile *QgsNetworkContentFetcherRegistry::localFile( const QString &filePathOrUrl )
57 {
58  QFile *file = nullptr;
59  QString path = filePathOrUrl;
60 
61  if ( !QUrl::fromUserInput( filePathOrUrl ).isLocalFile() )
62  {
63  if ( mFileRegistry.contains( path ) )
64  {
65  const QgsFetchedContent *content = mFileRegistry.value( path );
66  if ( content && content->status() == QgsFetchedContent::Finished && content->file() )
67  {
68  file = content->file();
69  }
70  else
71  {
72  // if the file is not downloaded yet or has failed, return nullptr
73  }
74  }
75  else
76  {
77  // if registry doesn't contain the URL, return nullptr
78  }
79  }
80  else
81  {
82  file = new QFile( filePathOrUrl );
83  }
84  return file;
85 }
86 
87 QString QgsNetworkContentFetcherRegistry::localPath( const QString &filePathOrUrl )
88 {
89  QString path = filePathOrUrl;
90 
91  if ( !QUrl::fromUserInput( filePathOrUrl ).isLocalFile() )
92  {
93  if ( mFileRegistry.contains( path ) )
94  {
95  const QgsFetchedContent *content = mFileRegistry.value( path );
96  if ( content->status() == QgsFetchedContent::Finished && !content->filePath().isEmpty() )
97  {
98  path = content->filePath();
99  }
100  else
101  {
102  // if the file is not downloaded yet or has failed, return empty string
103  path = QString();
104  }
105  }
106  else
107  {
108  // if registry doesn't contain the URL, keep path unchanged
109  }
110  }
111  return path;
112 }
113 
114 
115 
116 
117 void QgsFetchedContent::download( bool redownload )
118 {
119 
120  if ( redownload && status() == QgsFetchedContent::Downloading )
121  {
122  {
123  if ( mFetchingTask )
124  disconnect( mFetchingTask, &QgsNetworkContentFetcherTask::taskCompleted, this, &QgsFetchedContent::taskCompleted );
125  }
126  cancel();
127  }
128  if ( redownload ||
129  status() == QgsFetchedContent::NotStarted ||
130  status() == QgsFetchedContent::Failed )
131  {
132  mFetchingTask = new QgsNetworkContentFetcherTask( mUrl );
133  // use taskCompleted which is main thread rather than fetched signal in worker thread
134  connect( mFetchingTask, &QgsNetworkContentFetcherTask::taskCompleted, this, &QgsFetchedContent::taskCompleted );
135  QgsApplication::instance()->taskManager()->addTask( mFetchingTask );
137  }
138 
139 }
140 
142 {
143  if ( mFetchingTask && mFetchingTask->canCancel() )
144  {
145  mFetchingTask->cancel();
146  }
147  if ( mFile )
148  {
149  mFile->deleteLater();
150  mFilePath = QString();
151  }
152 }
153 
154 
155 void QgsFetchedContent::taskCompleted()
156 {
157  if ( !mFetchingTask || !mFetchingTask->reply() )
158  {
159  // if no reply, it has been canceled
160  mStatus = QgsFetchedContent::Failed;
161  mError = QNetworkReply::OperationCanceledError;
162  mFilePath = QString();
163  }
164  else
165  {
166  QNetworkReply *reply = mFetchingTask->reply();
167  if ( reply->error() == QNetworkReply::NoError )
168  {
169  QTemporaryFile *tf = new QTemporaryFile( QStringLiteral( "XXXXXX" ) );
170  mFile = tf;
171  tf->open();
172  mFile->write( reply->readAll() );
173  // Qt docs notes that on some system if fileName is not called before close, file might get deleted
174  mFilePath = tf->fileName();
175  tf->close();
176  mStatus = QgsFetchedContent::Finished;
177  }
178  else
179  {
180  mStatus = QgsFetchedContent::Failed;
181  mError = reply->error();
182  mFilePath = QString();
183  }
184  }
185 
186  emit fetched();
187 }
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, a null pointer 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...
QgsNetworkContentFetcherRegistry()
Create the registry for temporary downloaded files.
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.