Skip to content

Commit d39d268

Browse files
committed
Add a QgsTask for fetching network content
Provides a simple method for fetching remote HTTP content in a QgsTask. Utilises QgsNetworkContentFetcher so Url redirects and progress reports are automatically handled. (cherry-picked from e2f09fa)
1 parent 61a650a commit d39d268

10 files changed

+354
-8
lines changed

python/core/core_auto.sip

+1
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@
329329
%Include qgsmessageoutput.sip
330330
%Include qgsnetworkaccessmanager.sip
331331
%Include qgsnetworkcontentfetcher.sip
332+
%Include qgsnetworkcontentfetchertask.sip
332333
%Include qgsofflineediting.sip
333334
%Include qgspluginlayer.sip
334335
%Include qgspointxy.sip

python/core/qgsnetworkcontentfetcher.sip.in

+9-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212

1313

14-
1514
class QgsNetworkContentFetcher : QObject
1615
{
1716
%Docstring
@@ -20,6 +19,8 @@ and converting the content to standard formats. Url redirects are automatically
2019
handled.
2120

2221
.. versionadded:: 2.5
22+
23+
.. seealso:: :py:class:`QgsNetworkContentFetcherTask`
2324
%End
2425

2526
%TypeHeaderCode
@@ -69,6 +70,13 @@ Returns the fetched content as a string
6970
void finished();
7071
%Docstring
7172
Emitted when content has loaded
73+
%End
74+
75+
void downloadProgress( qint64 bytesReceived, qint64 bytesTotal );
76+
%Docstring
77+
Emitted when data is received.
78+
79+
.. versionadded:: 3.2
7280
%End
7381

7482
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/************************************************************************
2+
* This file has been generated automatically from *
3+
* *
4+
* src/core/qgsnetworkcontentfetchertask.h *
5+
* *
6+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
7+
************************************************************************/
8+
9+
10+
11+
12+
13+
14+
class QgsNetworkContentFetcherTask : QgsTask
15+
{
16+
%Docstring
17+
Handles HTTP network content fetching in a background task.
18+
19+
Provides a simple method for fetching remote HTTP content in a QgsTask.
20+
Url redirects are automatically handled.
21+
22+
After constructing a QgsNetworkContentFetcherTask, callers should
23+
connect to the QgsNetworkContentFetcherTask.fetched signal. They can
24+
then safely access the network reply() from the connected slot
25+
without danger of the task being first removed by the QgsTaskManager.
26+
27+
.. seealso:: :py:class:`QgsNetworkContentFetcher`
28+
29+
.. versionadded:: 3.2
30+
%End
31+
32+
%TypeHeaderCode
33+
#include "qgsnetworkcontentfetchertask.h"
34+
%End
35+
public:
36+
37+
QgsNetworkContentFetcherTask( const QUrl &url );
38+
%Docstring
39+
Constructor for a QgsNetworkContentFetcherTask which fetches
40+
the specified ``url``.
41+
%End
42+
43+
QgsNetworkContentFetcherTask( const QNetworkRequest &request );
44+
%Docstring
45+
Constructor for a QgsNetworkContentFetcherTask which fetches
46+
the specified network ``request``.
47+
%End
48+
49+
~QgsNetworkContentFetcherTask();
50+
51+
virtual bool run();
52+
53+
54+
QNetworkReply *reply();
55+
%Docstring
56+
Returns the network reply. Ownership is not transferred.
57+
58+
May return None if the request has not yet completed.
59+
%End
60+
61+
signals:
62+
63+
void fetched();
64+
%Docstring
65+
Emitted when the network content has been fetched, regardless
66+
of whether the fetch was successful or not.
67+
68+
Users of QgsNetworkContentFetcherTask should connect to this signal,
69+
and from the associated slot they can then safely access the network reply()
70+
without danger of the task being first removed by the :py:class:`QgsTaskManager`.
71+
%End
72+
73+
};
74+
75+
/************************************************************************
76+
* This file has been generated automatically from *
77+
* *
78+
* src/core/qgsnetworkcontentfetchertask.h *
79+
* *
80+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
81+
************************************************************************/

src/core/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ SET(QGIS_CORE_SRCS
235235
qgsnetworkaccessmanager.cpp
236236
qgsnetworkdiskcache.cpp
237237
qgsnetworkcontentfetcher.cpp
238+
qgsnetworkcontentfetchertask.cpp
238239
qgsnetworkreplyparser.cpp
239240
qgsobjectcustomproperties.cpp
240241
qgsofflineediting.cpp
@@ -610,6 +611,7 @@ SET(QGIS_CORE_MOC_HDRS
610611
qgsnetworkaccessmanager.h
611612
qgsnetworkdiskcache.h
612613
qgsnetworkcontentfetcher.h
614+
qgsnetworkcontentfetchertask.h
613615
qgsnetworkreplyparser.h
614616
qgsofflineediting.h
615617
qgsowsconnection.h

src/core/qgsnetworkcontentfetcher.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ void QgsNetworkContentFetcher::fetchContent( const QNetworkRequest &request )
5555

5656
mReply = QgsNetworkAccessManager::instance()->get( request );
5757
connect( mReply, &QNetworkReply::finished, this, [ = ] { contentLoaded(); } );
58+
connect( mReply, &QNetworkReply::downloadProgress, this, &QgsNetworkContentFetcher::downloadProgress );
5859
}
5960

6061
QNetworkReply *QgsNetworkContentFetcher::reply()

src/core/qgsnetworkcontentfetcher.h

+13-7
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@
2626
#include "qgis_core.h"
2727

2828
/**
29-
\class QgsNetworkContentFetcher
30-
\ingroup core
31-
\brief HTTP network content fetcher. A simple method for fetching remote HTTP content
32-
and converting the content to standard formats. Url redirects are automatically
33-
handled.
34-
\since 2.5
29+
* \class QgsNetworkContentFetcher
30+
* \ingroup core
31+
* \brief HTTP network content fetcher. A simple method for fetching remote HTTP content
32+
* and converting the content to standard formats. Url redirects are automatically
33+
* handled.
34+
* \since QGIS 2.5
35+
* \see QgsNetworkContentFetcherTask
3536
*/
36-
3737
class CORE_EXPORT QgsNetworkContentFetcher : public QObject
3838
{
3939
Q_OBJECT
@@ -81,6 +81,12 @@ class CORE_EXPORT QgsNetworkContentFetcher : public QObject
8181
*/
8282
void finished();
8383

84+
/**
85+
* Emitted when data is received.
86+
* \since QGIS 3.2
87+
*/
88+
void downloadProgress( qint64 bytesReceived, qint64 bytesTotal );
89+
8490
private:
8591

8692
QNetworkReply *mReply = nullptr;
+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/***************************************************************************
2+
qgsnetworkcontentfetchertask.cpp
3+
-------------------
4+
begin : March 2018
5+
copyright : (C) 2018 by Nyall Dawson
6+
email : nyall dot dawson at gmail dot com
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+
19+
#include "qgsnetworkcontentfetchertask.h"
20+
#include "qgsnetworkcontentfetcher.h"
21+
22+
QgsNetworkContentFetcherTask::QgsNetworkContentFetcherTask( const QUrl &url )
23+
: QgsNetworkContentFetcherTask( QNetworkRequest( url ) )
24+
{
25+
}
26+
27+
QgsNetworkContentFetcherTask::QgsNetworkContentFetcherTask( const QNetworkRequest &request )
28+
: QgsTask( tr( "Fetching %1" ).arg( request.url().toString() ) )
29+
, mRequest( request )
30+
{
31+
}
32+
33+
QgsNetworkContentFetcherTask::~QgsNetworkContentFetcherTask()
34+
{
35+
if ( mFetcher )
36+
mFetcher->deleteLater();
37+
}
38+
39+
bool QgsNetworkContentFetcherTask::run()
40+
{
41+
mFetcher = new QgsNetworkContentFetcher();
42+
QEventLoop loop;
43+
connect( mFetcher, &QgsNetworkContentFetcher::finished, &loop, &QEventLoop::quit );
44+
connect( mFetcher, &QgsNetworkContentFetcher::downloadProgress, this, [ = ]( qint64 bytesReceived, qint64 bytesTotal )
45+
{
46+
if ( bytesTotal > 0 )
47+
{
48+
setProgress( ( bytesReceived * 100 ) / bytesTotal );
49+
}
50+
} );
51+
mFetcher->fetchContent( mRequest );
52+
loop.exec();
53+
emit fetched();
54+
return true;
55+
}
56+
57+
QNetworkReply *QgsNetworkContentFetcherTask::reply()
58+
{
59+
return mFetcher ? mFetcher->reply() : nullptr;
60+
}
+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/***************************************************************************
2+
qgsnetworkcontentfetchertask.h
3+
-------------------
4+
begin : March, 2018
5+
copyright : (C) 2018 by Nyall Dawson
6+
email : nyall dot dawson at gmail dot com
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+
19+
20+
#ifndef QGSNETWORKCONTENTFETCHERTASK_H
21+
#define QGSNETWORKCONTENTFETCHERTASK_H
22+
23+
#include "qgstaskmanager.h"
24+
#include "qgis_core.h"
25+
#include <QNetworkRequest>
26+
27+
class QgsNetworkContentFetcher;
28+
class QNetworkReply;
29+
30+
/**
31+
* \class QgsNetworkContentFetcherTask
32+
* \ingroup core
33+
* \brief Handles HTTP network content fetching in a background task.
34+
*
35+
* Provides a simple method for fetching remote HTTP content in a QgsTask.
36+
* Url redirects are automatically handled.
37+
*
38+
* After constructing a QgsNetworkContentFetcherTask, callers should
39+
* connect to the QgsNetworkContentFetcherTask::fetched signal. They can
40+
* then safely access the network reply() from the connected slot
41+
* without danger of the task being first removed by the QgsTaskManager.
42+
*
43+
* \see QgsNetworkContentFetcher
44+
*
45+
* \since QGIS 3.2
46+
*/
47+
class CORE_EXPORT QgsNetworkContentFetcherTask : public QgsTask
48+
{
49+
Q_OBJECT
50+
51+
public:
52+
53+
/**
54+
* Constructor for a QgsNetworkContentFetcherTask which fetches
55+
* the specified \a url.
56+
*/
57+
QgsNetworkContentFetcherTask( const QUrl &url );
58+
59+
/**
60+
* Constructor for a QgsNetworkContentFetcherTask which fetches
61+
* the specified network \a request.
62+
*/
63+
QgsNetworkContentFetcherTask( const QNetworkRequest &request );
64+
65+
~QgsNetworkContentFetcherTask();
66+
67+
bool run() override;
68+
69+
/**
70+
* Returns the network reply. Ownership is not transferred.
71+
*
72+
* May return nullptr if the request has not yet completed.
73+
*/
74+
QNetworkReply *reply();
75+
76+
signals:
77+
78+
/**
79+
* Emitted when the network content has been fetched, regardless
80+
* of whether the fetch was successful or not.
81+
*
82+
* Users of QgsNetworkContentFetcherTask should connect to this signal,
83+
* and from the associated slot they can then safely access the network reply()
84+
* without danger of the task being first removed by the QgsTaskManager.
85+
*/
86+
void fetched();
87+
88+
private:
89+
90+
QNetworkRequest mRequest;
91+
QgsNetworkContentFetcher *mFetcher = nullptr;
92+
93+
};
94+
95+
#endif //QGSNETWORKCONTENTFETCHERTASK_H

tests/src/python/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ ADD_PYTHON_TEST(PyQgsMargins test_qgsmargins.py)
112112
ADD_PYTHON_TEST(PyQgsMemoryProvider test_provider_memory.py)
113113
ADD_PYTHON_TEST(PyQgsMultiEditToolButton test_qgsmultiedittoolbutton.py)
114114
ADD_PYTHON_TEST(PyQgsNetworkContentFetcher test_qgsnetworkcontentfetcher.py)
115+
ADD_PYTHON_TEST(PyQgsNetworkContentFetcherTask test_qgsnetworkcontentfetchertask.py)
115116
ADD_PYTHON_TEST(PyQgsNullSymbolRenderer test_qgsnullsymbolrenderer.py)
116117
ADD_PYTHON_TEST(PyQgsNewGeoPackageLayerDialog test_qgsnewgeopackagelayerdialog.py)
117118
ADD_PYTHON_TEST(PyQgsNoApplication test_qgsnoapplication.py)

0 commit comments

Comments
 (0)