Skip to content
Permalink
Browse files

do not expose task and make it thread safe

  • Loading branch information
3nids committed Apr 27, 2018
1 parent 25108e5 commit 648562d2b7540ab76e78d03c924a60a66543861a
@@ -336,6 +336,7 @@
%Include qgsmessageoutput.sip
%Include qgsnetworkaccessmanager.sip
%Include qgsnetworkcontentfetcher.sip
%Include qgsnetworkcontentfetcherregistry.sip
%Include qgsnetworkcontentfetchertask.sip
%Include qgsofflineediting.sip
%Include qgspluginlayer.sip
@@ -645,8 +645,7 @@ within SVG files.

static QgsNetworkContentFetcherRegistry *networkContentFetcherRegistry();
%Docstring
Returns the application's SVG cache, used for caching SVG images and handling parameter replacement
within SVG files.
Returns the application's network content registry used for fetching temporary files during QGIS session

.. versionadded:: 3.2
%End
@@ -0,0 +1,131 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsnetworkcontentfetcherregistry.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/








class QgsFetchedContent : QObject
{
%Docstring
FetchedContent holds useful information about a network content being fetched

.. seealso:: :py:class:`QgsNetworkContentFetcherRegistry`

.. versionadded:: 3.2
%End

%TypeHeaderCode
#include "qgsnetworkcontentfetcherregistry.h"
%End
public:
enum ContentStatus
{
NotStarted,
Downloading,
Finished,
Failed
};

explicit QgsFetchedContent( QTemporaryFile *file = 0, ContentStatus status = NotStarted );
%Docstring
Constructs a FetchedContent with pointer to the downloaded file and status of the download
%End


const QString filePath() const;
%Docstring
Return the path to the local file, an empty string if the file is not accessible yet.
%End

ContentStatus status() const;
%Docstring
Return the status of the download
%End

QNetworkReply::NetworkError error() const;
%Docstring
Return the potential error of the download
%End

public slots:

void download( bool redownload = false );
%Docstring
Start the download

:param redownload: if set to true, it will restart any achieved or pending download.
%End

signals:
void fetched();
%Docstring
Sent when the file is fetched and accessible
%End

void downloadStarted( const bool redownload );
%Docstring
Sent went the download actually starts
%End

};

class QgsNetworkContentFetcherRegistry : QObject
{
%Docstring
Registry for temporary fetched files

This provides a simple way of downloading and accessing
remote files during QGIS application running.

.. seealso:: :py:class:`QgsFetchedContent`

.. versionadded:: 3.2
%End

%TypeHeaderCode
#include "qgsnetworkcontentfetcherregistry.h"
%End
public:
enum FetchingMode
{
DownloadLater,
DownloadImmediately,
};

explicit QgsNetworkContentFetcherRegistry();
%Docstring
Create the registry for temporary downloaded files
%End

~QgsNetworkContentFetcherRegistry();

const QgsFetchedContent *fetch( const QUrl &url, const FetchingMode &fetchingMode = DownloadLater );
%Docstring
Initialize a download for the given URL

:param url: the URL to be fetched
:param fetchingMode: defines if the download will start immediately or shall be manually triggered

.. note::

If the download starts immediately, it will not redownload any already fetched or currently fetching file.
%End

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsnetworkcontentfetcherregistry.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
@@ -1667,7 +1667,7 @@ QgsSvgCache *QgsApplication::svgCache()

QgsNetworkContentFetcherRegistry *QgsApplication::networkContentFetcherRegistry()
{
return members()->mNetworkContentFertcherRegistry;
return members()->mNetworkContentFetcherRegistry;
}

QgsSymbolLayerRegistry *QgsApplication::symbolLayerRegistry()
@@ -1749,7 +1749,7 @@ QgsApplication::ApplicationMembers::ApplicationMembers()
mAnnotationRegistry = new QgsAnnotationRegistry();
m3DRendererRegistry = new Qgs3DRendererRegistry();
mProjectStorageRegistry = new QgsProjectStorageRegistry();
mNetworkContentFertcherRegistry = new QgsNetworkContentFetcherRegistry();
mNetworkContentFetcherRegistry = new QgsNetworkContentFetcherRegistry();
}

QgsApplication::ApplicationMembers::~ApplicationMembers()
@@ -1773,7 +1773,7 @@ QgsApplication::ApplicationMembers::~ApplicationMembers()
delete mSvgCache;
delete mSymbolLayerRegistry;
delete mTaskManager;
delete mNetworkContentFertcherRegistry;
delete mNetworkContentFetcherRegistry;
}

QgsApplication::ApplicationMembers *QgsApplication::members()
@@ -588,8 +588,7 @@ class CORE_EXPORT QgsApplication : public QApplication
static QgsSvgCache *svgCache();

/**
* Returns the application's SVG cache, used for caching SVG images and handling parameter replacement
* within SVG files.
* Returns the application's network content registry used for fetching temporary files during QGIS session
* \since QGIS 3.2
*/
static QgsNetworkContentFetcherRegistry *networkContentFetcherRegistry();
@@ -810,7 +809,7 @@ class CORE_EXPORT QgsApplication : public QApplication
QgsColorSchemeRegistry *mColorSchemeRegistry = nullptr;
QgsFieldFormatterRegistry *mFieldFormatterRegistry = nullptr;
QgsGpsConnectionRegistry *mGpsConnectionRegistry = nullptr;
QgsNetworkContentFetcherRegistry *mNetworkContentFertcherRegistry = nullptr;
QgsNetworkContentFetcherRegistry *mNetworkContentFetcherRegistry = nullptr;
QgsMessageLog *mMessageLog = nullptr;
QgsPaintEffectRegistry *mPaintEffectRegistry = nullptr;
QgsPluginLayerRegistry *mPluginLayerRegistry = nullptr;
@@ -3,7 +3,7 @@
-------------------
begin : April, 2018
copyright : (C) 2018 by Denis Rouzaud
email : denis.rouzaud@gmail.com
email : denis@opengis.ch
***************************************************************************/

@@ -28,66 +28,78 @@ QgsNetworkContentFetcherRegistry::QgsNetworkContentFetcherRegistry()

QgsNetworkContentFetcherRegistry::~QgsNetworkContentFetcherRegistry()
{
QMap<QUrl, FetchedContent>::const_iterator it = mFileRegistry.constBegin();
QMap<QUrl, QgsFetchedContent *>::const_iterator it = mFileRegistry.constBegin();
for ( ; it != mFileRegistry.constEnd(); ++it )
{
it.value().mFile->deleteLater();
it.value()->mFile->close();
delete it.value()->mFile;
}
mFileRegistry.clear();
}

const QgsNetworkContentFetcherTask *QgsNetworkContentFetcherRegistry::fetch( const QUrl &url, const bool reload )
const QgsFetchedContent *QgsNetworkContentFetcherRegistry::fetch( const QUrl &url, const FetchingMode &fetchingMode )
{
if ( mFileRegistry.contains( url ) )
{
if ( !reload )
{
return mFileRegistry.value( url ).mFetchingTask;
}
else
return mFileRegistry.value( url );
}

QgsFetchedContent *content = new QgsFetchedContent( nullptr, QgsFetchedContent::NotStarted );
QgsNetworkContentFetcherTask *fetcher = new QgsNetworkContentFetcherTask( url );

QObject::connect( content, &QgsFetchedContent::downloadStarted, this, [ = ]( const bool redownload )
{
QMutexLocker locker( &mMutex );
if ( mFileRegistry.contains( url ) && redownload )
{
FetchedContent content = mFileRegistry.take( url );
if ( content.mFetchingTask )
const QgsFetchedContent *content = mFileRegistry[url];
if ( mFileRegistry.value( url )->status() == QgsFetchedContent::Downloading && content->mFetchingTask )
{
content.mFetchingTask->cancel();
content->mFetchingTask->cancel();
}
if ( content.mFile )
if ( content->mFile )
{
content.mFile->deleteLater();
content->mFile->deleteLater();
mFileRegistry[url]->setFilePath( QStringLiteral() );
}
}
}

QgsNetworkContentFetcherTask *fetcher = new QgsNetworkContentFetcherTask( url );
QgsApplication::instance()->taskManager()->addTask( fetcher );
mFileRegistry.insert( url,
FetchedContent( nullptr,
QgsNetworkContentFetcherRegistry::Downloading ) );
if ( ( mFileRegistry.contains( url ) && mFileRegistry.value( url )->status() == QgsFetchedContent::NotStarted ) || redownload )
{
QgsApplication::instance()->taskManager()->addTask( fetcher );
}
} );

QObject::connect( fetcher, &QgsNetworkContentFetcherTask::fetched, this, [ = ]()
{
QMutexLocker locker( &mMutex );
QNetworkReply *reply = fetcher->reply();
FetchedContent content = mFileRegistry.take( url );
QgsFetchedContent *content = mFileRegistry.value( url );
if ( reply->error() == QNetworkReply::NoError )
{
content.setFile( new QTemporaryFile( QStringLiteral( "XXXXXX" ) ) );
content.mFile->write( reply->readAll() );
content.setStatus( Finished );
QTemporaryFile *tf = new QTemporaryFile( QStringLiteral( "XXXXXX" ) );
content->setFile( tf );
tf->open();
content->mFile->write( reply->readAll() );
// Qt docs notes that on some system if fileName is not called before close, file might get deleted
content->setFilePath( tf->fileName() );
tf->close();
content->setStatus( QgsFetchedContent::Finished );
}
else
{
content.setStatus( Failed );
content.setError( reply->error() );
content->setStatus( QgsFetchedContent::Failed );
content->setError( reply->error() );
content->setFilePath( QStringLiteral() );
}
mFileRegistry.insert( url, content );
content->emitFetched();
} );

if ( fetchingMode == DownloadImmediately )
content->download();
mFileRegistry.insert( url, content );

return fetcher;
return content;
}



QgsNetworkContentFetcherRegistry::FetchedContent QgsNetworkContentFetcherRegistry::file( const QUrl &url )
{
return mFileRegistry.value( url );
}

0 comments on commit 648562d

Please sign in to comment.
You can’t perform that action at this time.