QGIS API Documentation  3.27.0-Master (597e8eebd4)
qgstiledownloadmanager.h
Go to the documentation of this file.
1 /***************************************************************************
2  qgstiledownloadmanager.h
3  ------------------------
4  begin : January 2021
5  copyright : (C) 2021 by Martin Dobias
6  email : wonder dot sk at gmail 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 
18 #ifndef QGSTILEDOWNLOADMANAGER_H
19 #define QGSTILEDOWNLOADMANAGER_H
20 
21 #define SIP_NO_FILE
22 
23 #include <QTimer>
24 #include <QThread>
25 #include <QMutex>
26 
27 #include <QNetworkAccessManager>
28 #include <QNetworkReply>
29 
30 #include "qgis_core.h"
31 
34 
47 class CORE_EXPORT QgsTileDownloadManagerReply : public QObject
48 {
49  Q_OBJECT
50  public:
52 
54  bool hasFinished() const { return mHasFinished; }
56  QByteArray data() const { return mData; }
58  QUrl url() const { return mUrl; }
60  QVariant attribute( QNetworkRequest::Attribute code );
62  QVariant header( QNetworkRequest::KnownHeaders header );
64  const QList<QNetworkReply::RawHeaderPair> rawHeaderPairs() const { return mRawHeaderPairs; }
66  QNetworkReply::NetworkError error() const { return mError; }
68  QString errorString() const { return mErrorString; }
70  QNetworkRequest request() const { return mRequest; }
71 
72  signals:
74  void finished();
75 
76  private slots:
77  void requestFinished( QByteArray data, QUrl url, const QMap<QNetworkRequest::Attribute, QVariant> &attributes, const QMap<QNetworkRequest::KnownHeaders, QVariant> &headers, const QList<QNetworkReply::RawHeaderPair> rawHeaderPairs, QNetworkReply::NetworkError error, const QString &errorString );
78  void cachedRangeRequestFinished();
79 
80  private:
81  QgsTileDownloadManagerReply( QgsTileDownloadManager *manager, const QNetworkRequest &request );
82 
83  friend class QgsTileDownloadManager; // allows creation of new instances from the manager
84 
85  private:
87  QgsTileDownloadManager *mManager = nullptr;
88  QNetworkRequest mRequest;
89  bool mHasFinished = false;
90  QByteArray mData;
91  QNetworkReply::NetworkError mError = QNetworkReply::NoError;
92  QString mErrorString;
93  QUrl mUrl;
94  QMap<QNetworkRequest::Attribute, QVariant> mAttributes;
95  QMap<QNetworkRequest::KnownHeaders, QVariant> mHeaders;
96  QList<QNetworkReply::RawHeaderPair> mRawHeaderPairs;
97 };
98 
99 
101 
107 class QgsTileDownloadManagerReplyWorkerObject : public QObject
108 {
109  Q_OBJECT
110  public:
111  QgsTileDownloadManagerReplyWorkerObject( QgsTileDownloadManager *manager, const QNetworkRequest &request )
112  : mManager( manager ), mRequest( request ) {}
113 
114  public slots:
115  void replyFinished();
116 
117  signals:
118  void finished( QByteArray data, QUrl url, const QMap<QNetworkRequest::Attribute, QVariant> &attributes, const QMap<QNetworkRequest::KnownHeaders, QVariant> &headers, const QList<QNetworkReply::RawHeaderPair> rawHeaderPairs, QNetworkReply::NetworkError error, const QString &errorString );
119 
120  private:
122  QgsTileDownloadManager *mManager = nullptr;
123  QNetworkRequest mRequest;
124 };
125 
126 
132 class QgsTileDownloadManagerWorker : public QObject
133 {
134  Q_OBJECT
135 
136  public:
138  QgsTileDownloadManagerWorker( QgsTileDownloadManager *manager, QObject *parent = nullptr );
139 
140  void startIdleTimer();
141 
142  public slots:
143  void queueUpdated();
144  void idleTimerTimeout();
145 
146  signals:
147  void requestFinished( QString url, QByteArray data );
148 
149  private:
150  void quitThread();
151 
152  private:
154  QgsTileDownloadManager *mManager = nullptr;
156  QTimer mIdleTimer;
157 };
158 
160 
161 
162 
202 class CORE_EXPORT QgsTileDownloadManager
203 {
204 
206  class QueueEntry
207  {
208  public:
209  bool isValid() const { return !request.url().isEmpty(); }
210 
212  QNetworkRequest request;
214  QgsTileDownloadManagerReplyWorkerObject *objWorker = nullptr;
216  QNetworkReply *networkReply = nullptr;
217  };
218 
219  public:
220 
226  class Stats
227  {
228  public:
230  int requestsTotal = 0;
232  int requestsMerged = 0;
234  int requestsEarlyDeleted = 0;
235 
237  int networkRequestsStarted = 0;
239  int networkRequestsOk = 0;
241  int networkRequestsFailed = 0;
242  };
243 
246 
251  QgsTileDownloadManagerReply *get( const QNetworkRequest &request );
252 
254  bool hasPendingRequests() const;
255 
260  bool waitForPendingRequests( int msec = -1 );
261 
263  void shutdown();
264 
269  bool hasWorkerThreadRunning() const;
270 
275  void setIdleThreadTimeout( int timeoutMs ) { mIdleThreadTimeoutMs = timeoutMs; }
276 
278  Stats statistics() const { return mStats; }
279 
281  void resetStatistics();
282 
283  friend class QgsTileDownloadManagerWorker;
285  friend class QgsTileDownloadManagerReplyWorkerObject;
286 
287  private:
288 
289  // these can be only used with mutex locked!
290  QueueEntry findEntryForRequest( const QNetworkRequest &request );
291  void addEntry( const QueueEntry &entry );
292  void updateEntry( const QueueEntry &entry );
293  void removeEntry( const QNetworkRequest &request );
294 
295  void signalQueueModified();
296 
297  bool isRangeRequest( const QNetworkRequest &request );
298  bool isCachedRangeRequest( const QNetworkRequest &request );
299 
300  private:
301 
302  QList<QueueEntry> mQueue;
303  bool mShuttingDown = false;
304 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
305  mutable QMutex mMutex;
306 #else
307  mutable QRecursiveMutex mMutex;
308 #endif
309  QThread *mWorkerThread = nullptr;
310  QgsTileDownloadManagerWorker *mWorker = nullptr;
311  Stats mStats;
312 
313  int mIdleThreadTimeoutMs = 10000;
314 
315  std::unique_ptr<QgsRangeRequestCache> mRangesCache;
316 };
317 
318 #endif // QGSTILEDOWNLOADMANAGER_H
A custom cache for handling the storage and retrieval of HTTP range requests on disk.
Reply object for tile download manager requests returned from calls to QgsTileDownloadManager::get().
QString errorString() const
Returns error string (only valid when already finished)
const QList< QNetworkReply::RawHeaderPair > rawHeaderPairs() const
Returns a list of raw header pairs.
bool hasFinished() const
Returns whether the reply has already finished (with success/failure)
QNetworkRequest request() const
Returns the original request for this reply object.
QByteArray data() const
Returns binary data returned in the reply (only valid when already finished)
QNetworkReply::NetworkError error() const
Returns error code (only valid when already finished)
QUrl url() const
Returns the reply URL.
void finished()
Emitted when the reply has finished (either with a success or with a failure)
Encapsulates any statistics we would like to keep about requests.
Tile download manager handles downloads of map tiles for the purpose of map rendering.
Stats statistics() const
Returns basic statistics of the queries handled by this class.
void setIdleThreadTimeout(int timeoutMs)
Sets after how many milliseconds the idle worker therad should terminate.