Skip to content

Commit

Permalink
Add a QgsTask for fetching network content
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
nyalldawson committed Apr 6, 2018
1 parent 61a650a commit d39d268
Show file tree
Hide file tree
Showing 10 changed files with 354 additions and 8 deletions.
1 change: 1 addition & 0 deletions python/core/core_auto.sip
Expand Up @@ -329,6 +329,7 @@
%Include qgsmessageoutput.sip
%Include qgsnetworkaccessmanager.sip
%Include qgsnetworkcontentfetcher.sip
%Include qgsnetworkcontentfetchertask.sip
%Include qgsofflineediting.sip
%Include qgspluginlayer.sip
%Include qgspointxy.sip
Expand Down
10 changes: 9 additions & 1 deletion python/core/qgsnetworkcontentfetcher.sip.in
Expand Up @@ -11,7 +11,6 @@




class QgsNetworkContentFetcher : QObject
{
%Docstring
Expand All @@ -20,6 +19,8 @@ and converting the content to standard formats. Url redirects are automatically
handled.

.. versionadded:: 2.5

.. seealso:: :py:class:`QgsNetworkContentFetcherTask`
%End

%TypeHeaderCode
Expand Down Expand Up @@ -69,6 +70,13 @@ Returns the fetched content as a string
void finished();
%Docstring
Emitted when content has loaded
%End

void downloadProgress( qint64 bytesReceived, qint64 bytesTotal );
%Docstring
Emitted when data is received.

.. versionadded:: 3.2
%End

};
Expand Down
81 changes: 81 additions & 0 deletions python/core/qgsnetworkcontentfetchertask.sip.in
@@ -0,0 +1,81 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsnetworkcontentfetchertask.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/






class QgsNetworkContentFetcherTask : QgsTask
{
%Docstring
Handles HTTP network content fetching in a background task.

Provides a simple method for fetching remote HTTP content in a QgsTask.
Url redirects are automatically handled.

After constructing a QgsNetworkContentFetcherTask, callers should
connect to the QgsNetworkContentFetcherTask.fetched signal. They can
then safely access the network reply() from the connected slot
without danger of the task being first removed by the QgsTaskManager.

.. seealso:: :py:class:`QgsNetworkContentFetcher`

.. versionadded:: 3.2
%End

%TypeHeaderCode
#include "qgsnetworkcontentfetchertask.h"
%End
public:

QgsNetworkContentFetcherTask( const QUrl &url );
%Docstring
Constructor for a QgsNetworkContentFetcherTask which fetches
the specified ``url``.
%End

QgsNetworkContentFetcherTask( const QNetworkRequest &request );
%Docstring
Constructor for a QgsNetworkContentFetcherTask which fetches
the specified network ``request``.
%End

~QgsNetworkContentFetcherTask();

virtual bool run();


QNetworkReply *reply();
%Docstring
Returns the network reply. Ownership is not transferred.

May return None if the request has not yet completed.
%End

signals:

void fetched();
%Docstring
Emitted when the network content has been fetched, regardless
of whether the fetch was successful or not.

Users of QgsNetworkContentFetcherTask should connect to this signal,
and from the associated slot they can then safely access the network reply()
without danger of the task being first removed by the :py:class:`QgsTaskManager`.
%End

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsnetworkcontentfetchertask.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
2 changes: 2 additions & 0 deletions src/core/CMakeLists.txt
Expand Up @@ -235,6 +235,7 @@ SET(QGIS_CORE_SRCS
qgsnetworkaccessmanager.cpp
qgsnetworkdiskcache.cpp
qgsnetworkcontentfetcher.cpp
qgsnetworkcontentfetchertask.cpp
qgsnetworkreplyparser.cpp
qgsobjectcustomproperties.cpp
qgsofflineediting.cpp
Expand Down Expand Up @@ -610,6 +611,7 @@ SET(QGIS_CORE_MOC_HDRS
qgsnetworkaccessmanager.h
qgsnetworkdiskcache.h
qgsnetworkcontentfetcher.h
qgsnetworkcontentfetchertask.h
qgsnetworkreplyparser.h
qgsofflineediting.h
qgsowsconnection.h
Expand Down
1 change: 1 addition & 0 deletions src/core/qgsnetworkcontentfetcher.cpp
Expand Up @@ -55,6 +55,7 @@ void QgsNetworkContentFetcher::fetchContent( const QNetworkRequest &request )

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

QNetworkReply *QgsNetworkContentFetcher::reply()
Expand Down
20 changes: 13 additions & 7 deletions src/core/qgsnetworkcontentfetcher.h
Expand Up @@ -26,14 +26,14 @@
#include "qgis_core.h"

/**
\class QgsNetworkContentFetcher
\ingroup core
\brief HTTP network content fetcher. A simple method for fetching remote HTTP content
and converting the content to standard formats. Url redirects are automatically
handled.
\since 2.5
* \class QgsNetworkContentFetcher
* \ingroup core
* \brief HTTP network content fetcher. A simple method for fetching remote HTTP content
* and converting the content to standard formats. Url redirects are automatically
* handled.
* \since QGIS 2.5
* \see QgsNetworkContentFetcherTask
*/

class CORE_EXPORT QgsNetworkContentFetcher : public QObject
{
Q_OBJECT
Expand Down Expand Up @@ -81,6 +81,12 @@ class CORE_EXPORT QgsNetworkContentFetcher : public QObject
*/
void finished();

/**
* Emitted when data is received.
* \since QGIS 3.2
*/
void downloadProgress( qint64 bytesReceived, qint64 bytesTotal );

private:

QNetworkReply *mReply = nullptr;
Expand Down
60 changes: 60 additions & 0 deletions src/core/qgsnetworkcontentfetchertask.cpp
@@ -0,0 +1,60 @@
/***************************************************************************
qgsnetworkcontentfetchertask.cpp
-------------------
begin : March 2018
copyright : (C) 2018 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsnetworkcontentfetchertask.h"
#include "qgsnetworkcontentfetcher.h"

QgsNetworkContentFetcherTask::QgsNetworkContentFetcherTask( const QUrl &url )
: QgsNetworkContentFetcherTask( QNetworkRequest( url ) )
{
}

QgsNetworkContentFetcherTask::QgsNetworkContentFetcherTask( const QNetworkRequest &request )
: QgsTask( tr( "Fetching %1" ).arg( request.url().toString() ) )
, mRequest( request )
{
}

QgsNetworkContentFetcherTask::~QgsNetworkContentFetcherTask()
{
if ( mFetcher )
mFetcher->deleteLater();
}

bool QgsNetworkContentFetcherTask::run()
{
mFetcher = new QgsNetworkContentFetcher();
QEventLoop loop;
connect( mFetcher, &QgsNetworkContentFetcher::finished, &loop, &QEventLoop::quit );
connect( mFetcher, &QgsNetworkContentFetcher::downloadProgress, this, [ = ]( qint64 bytesReceived, qint64 bytesTotal )
{
if ( bytesTotal > 0 )
{
setProgress( ( bytesReceived * 100 ) / bytesTotal );
}
} );
mFetcher->fetchContent( mRequest );
loop.exec();
emit fetched();
return true;
}

QNetworkReply *QgsNetworkContentFetcherTask::reply()
{
return mFetcher ? mFetcher->reply() : nullptr;
}
95 changes: 95 additions & 0 deletions src/core/qgsnetworkcontentfetchertask.h
@@ -0,0 +1,95 @@
/***************************************************************************
qgsnetworkcontentfetchertask.h
-------------------
begin : March, 2018
copyright : (C) 2018 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/


#ifndef QGSNETWORKCONTENTFETCHERTASK_H
#define QGSNETWORKCONTENTFETCHERTASK_H

#include "qgstaskmanager.h"
#include "qgis_core.h"
#include <QNetworkRequest>

class QgsNetworkContentFetcher;
class QNetworkReply;

/**
* \class QgsNetworkContentFetcherTask
* \ingroup core
* \brief Handles HTTP network content fetching in a background task.
*
* Provides a simple method for fetching remote HTTP content in a QgsTask.
* Url redirects are automatically handled.
*
* After constructing a QgsNetworkContentFetcherTask, callers should
* connect to the QgsNetworkContentFetcherTask::fetched signal. They can
* then safely access the network reply() from the connected slot
* without danger of the task being first removed by the QgsTaskManager.
*
* \see QgsNetworkContentFetcher
*
* \since QGIS 3.2
*/
class CORE_EXPORT QgsNetworkContentFetcherTask : public QgsTask
{
Q_OBJECT

public:

/**
* Constructor for a QgsNetworkContentFetcherTask which fetches
* the specified \a url.
*/
QgsNetworkContentFetcherTask( const QUrl &url );

/**
* Constructor for a QgsNetworkContentFetcherTask which fetches
* the specified network \a request.
*/
QgsNetworkContentFetcherTask( const QNetworkRequest &request );

~QgsNetworkContentFetcherTask();

bool run() override;

/**
* Returns the network reply. Ownership is not transferred.
*
* May return nullptr if the request has not yet completed.
*/
QNetworkReply *reply();

signals:

/**
* Emitted when the network content has been fetched, regardless
* of whether the fetch was successful or not.
*
* Users of QgsNetworkContentFetcherTask should connect to this signal,
* and from the associated slot they can then safely access the network reply()
* without danger of the task being first removed by the QgsTaskManager.
*/
void fetched();

private:

QNetworkRequest mRequest;
QgsNetworkContentFetcher *mFetcher = nullptr;

};

#endif //QGSNETWORKCONTENTFETCHERTASK_H
1 change: 1 addition & 0 deletions tests/src/python/CMakeLists.txt
Expand Up @@ -112,6 +112,7 @@ ADD_PYTHON_TEST(PyQgsMargins test_qgsmargins.py)
ADD_PYTHON_TEST(PyQgsMemoryProvider test_provider_memory.py)
ADD_PYTHON_TEST(PyQgsMultiEditToolButton test_qgsmultiedittoolbutton.py)
ADD_PYTHON_TEST(PyQgsNetworkContentFetcher test_qgsnetworkcontentfetcher.py)
ADD_PYTHON_TEST(PyQgsNetworkContentFetcherTask test_qgsnetworkcontentfetchertask.py)
ADD_PYTHON_TEST(PyQgsNullSymbolRenderer test_qgsnullsymbolrenderer.py)
ADD_PYTHON_TEST(PyQgsNewGeoPackageLayerDialog test_qgsnewgeopackagelayerdialog.py)
ADD_PYTHON_TEST(PyQgsNoApplication test_qgsnoapplication.py)
Expand Down

0 comments on commit d39d268

Please sign in to comment.