use individual network managers for threads (fixes #13721, fixes #14401, implements #14192)

This commit is contained in:
Juergen E. Fischer 2016-03-04 23:51:04 +01:00
parent 26d61956d7
commit 2eb82430bb
18 changed files with 341 additions and 271 deletions

View File

@ -62,29 +62,10 @@ class QgsNetworkAccessManager : QNetworkAccessManager
bool useSystemProxy();
public slots:
/** Send GET request, calls get().
* Emits requestSent().
* @param request request to be sent
*/
void sendGet( const QNetworkRequest & request );
/** Abort and delete reply. This slot may be used to abort reply created by instance of this class
* (and which was not moved to another thread) from a different thread. Such reply cannot
* be aborted directly from a different thread. The reply must be also deleted
* in this slot, otherwise it could happen that abort signal comes after the reply was deleted.
* @param reply reply to be aborted.
*/
void deleteReply( QNetworkReply * reply );
signals:
void requestAboutToBeCreated( QNetworkAccessManager::Operation, const QNetworkRequest &, QIODevice * );
void requestCreated( QNetworkReply * );
void requestTimedOut( QNetworkReply * );
/** Emitted when request was sent by request()
* @param reply request reply
* @param sender the object which called request() slot.
*/
void requestSent( QNetworkReply * reply, QObject *sender );
protected:
virtual QNetworkReply *createRequest( QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *outgoingData = 0 );

View File

@ -79,7 +79,6 @@
#include <QNetworkReply>
#include <QNetworkProxy>
#include <QAuthenticator>
#include <QNetworkDiskCache>
//
// Mac OS X Includes
@ -398,7 +397,7 @@ static void setTitleBarText_( QWidget & qgisApp )
*/
static QgsMessageOutput *messageOutputViewer_()
{
if ( QThread::currentThread() == QApplication::instance()->thread() )
if ( QThread::currentThread() == qApp->thread() )
return new QgsMessageViewer( QgisApp::instance() );
else
return new QgsMessageOutputConsole();
@ -10864,6 +10863,8 @@ void QgisApp::namSetup()
void QgisApp::namAuthenticationRequired( QNetworkReply *reply, QAuthenticator *auth )
{
Q_ASSERT( qApp->thread() == QThread::currentThread() );
QString username = auth->user();
QString password = auth->password();
@ -10882,31 +10883,38 @@ void QgisApp::namAuthenticationRequired( QNetworkReply *reply, QAuthenticator *a
}
}
for ( ;; )
{
QMutexLocker lock( QgsCredentials::instance()->mutex() );
bool ok;
for ( ;; )
{
bool ok = QgsCredentials::instance()->get(
QString( "%1 at %2" ).arg( auth->realm(), reply->url().host() ),
username, password,
tr( "Authentication required" ) );
if ( !ok )
return;
QMutexLocker lock( QgsCredentials::instance()->mutex() );
ok = QgsCredentials::instance()->get(
QString( "%1 at %2" ).arg( auth->realm(), reply->url().host() ),
username, password,
tr( "Authentication required" ) );
}
if ( !ok )
return;
if ( reply->isFinished() )
return;
if ( reply->isFinished() )
return;
if ( auth->user() != username || ( password != auth->password() && !password.isNull() ) )
break;
if ( auth->user() != username || ( password != auth->password() && !password.isNull() ) )
break;
// credentials didn't change - stored ones probably wrong? clear password and retry
// credentials didn't change - stored ones probably wrong? clear password and retry
{
QMutexLocker lock( QgsCredentials::instance()->mutex() );
QgsCredentials::instance()->put(
QString( "%1 at %2" ).arg( auth->realm(), reply->url().host() ),
username, QString::null );
}
}
// save credentials
// save credentials
{
QMutexLocker lock( QgsCredentials::instance()->mutex() );
QgsCredentials::instance()->put(
QString( "%1 at %2" ).arg( auth->realm(), reply->url().host() ),
username, password
@ -10930,27 +10938,34 @@ void QgisApp::namProxyAuthenticationRequired( const QNetworkProxy &proxy, QAuthe
QString username = auth->user();
QString password = auth->password();
for ( ;; )
{
QMutexLocker lock( QgsCredentials::instance()->mutex() );
bool ok;
for ( ;; )
{
bool ok = QgsCredentials::instance()->get(
QString( "proxy %1:%2 [%3]" ).arg( proxy.hostName() ).arg( proxy.port() ).arg( auth->realm() ),
username, password,
tr( "Proxy authentication required" ) );
if ( !ok )
return;
QMutexLocker lock( QgsCredentials::instance()->mutex() );
ok = QgsCredentials::instance()->get(
QString( "proxy %1:%2 [%3]" ).arg( proxy.hostName() ).arg( proxy.port() ).arg( auth->realm() ),
username, password,
tr( "Proxy authentication required" ) );
}
if ( !ok )
return;
if ( auth->user() != username || ( password != auth->password() && !password.isNull() ) )
break;
if ( auth->user() != username || ( password != auth->password() && !password.isNull() ) )
break;
// credentials didn't change - stored ones probably wrong? clear password and retry
// credentials didn't change - stored ones probably wrong? clear password and retry
{
QMutexLocker lock( QgsCredentials::instance()->mutex() );
QgsCredentials::instance()->put(
QString( "proxy %1:%2 [%3]" ).arg( proxy.hostName() ).arg( proxy.port() ).arg( auth->realm() ),
username, QString::null );
}
}
{
QMutexLocker lock( QgsCredentials::instance()->mutex() );
QgsCredentials::instance()->put(
QString( "proxy %1:%2 [%3]" ).arg( proxy.hostName() ).arg( proxy.port() ).arg( auth->realm() ),
username, password

View File

@ -149,6 +149,7 @@ SET(QGIS_CORE_SRCS
qgsmimedatautils.cpp
qgsmultirenderchecker.cpp
qgsnetworkaccessmanager.cpp
qgsnetworkdiskcache.cpp
qgsnetworkcontentfetcher.cpp
qgsnetworkreplyparser.cpp
qgsobjectcustomproperties.cpp
@ -452,6 +453,7 @@ SET(QGIS_CORE_MOC_HDRS
qgsmessagelog.h
qgsmessageoutput.h
qgsnetworkaccessmanager.h
qgsnetworkdiskcache.h
qgsnetworkcontentfetcher.h
qgsnetworkreplyparser.h
qgsofflineediting.h

View File

@ -30,14 +30,17 @@
#include <QSettings>
#include <QTimer>
#include <QNetworkReply>
#include <QNetworkDiskCache>
#include <QThreadStorage>
#ifndef QT_NO_OPENSSL
#include <QSslConfiguration>
#endif
#include "qgsnetworkdiskcache.h"
#include "qgsauthmanager.h"
QgsNetworkAccessManager *QgsNetworkAccessManager::smMainNAM = 0;
/// @cond PRIVATE
class QgsNetworkProxyFactory : public QNetworkProxyFactory
{
@ -99,13 +102,22 @@ class QgsNetworkProxyFactory : public QNetworkProxyFactory
//
QgsNetworkAccessManager* QgsNetworkAccessManager::instance()
{
static QgsNetworkAccessManager* sInstance( new QgsNetworkAccessManager( QApplication::instance() ) );
return sInstance;
static QThreadStorage<QgsNetworkAccessManager> sInstances;
QgsNetworkAccessManager *nam = &sInstances.localData();
if ( nam->thread() == qApp->thread() )
smMainNAM = nam;
if ( !nam->mInitialized )
nam->setupDefaultProxyAndCache();
return nam;
}
QgsNetworkAccessManager::QgsNetworkAccessManager( QObject *parent )
: QNetworkAccessManager( parent )
, mUseSystemProxy( false )
, mInitialized( false )
{
setProxyFactory( new QgsNetworkProxyFactory() );
}
@ -221,6 +233,8 @@ void QgsNetworkAccessManager::abortRequest()
QNetworkReply *reply = qobject_cast<QNetworkReply *>( timer->parent() );
Q_ASSERT( reply );
QgsDebugMsg( QString( "Abort [reply:%1]" ).arg(( qint64 ) reply, 0, 16 ) );
QgsMessageLog::logMessage( tr( "Network request %1 timed out" ).arg( reply->url().toString() ), tr( "Network" ) );
if ( reply->isRunning() )
@ -270,36 +284,36 @@ QNetworkRequest::CacheLoadControl QgsNetworkAccessManager::cacheLoadControlFromN
void QgsNetworkAccessManager::setupDefaultProxyAndCache()
{
QNetworkProxy proxy;
QStringList excludes;
QSettings settings;
mInitialized = true;
mUseSystemProxy = false;
if ( this != instance() )
{
Qt::ConnectionType connectionType = thread() == instance()->thread() ? Qt::AutoConnection : Qt::BlockingQueuedConnection;
Q_ASSERT( smMainNAM );
if ( smMainNAM != this )
{
connect( this, SIGNAL( authenticationRequired( QNetworkReply *, QAuthenticator * ) ),
instance(), SIGNAL( authenticationRequired( QNetworkReply *, QAuthenticator * ) ),
connectionType );
smMainNAM, SIGNAL( authenticationRequired( QNetworkReply *, QAuthenticator * ) ),
Qt::BlockingQueuedConnection );
connect( this, SIGNAL( proxyAuthenticationRequired( const QNetworkProxy &, QAuthenticator * ) ),
instance(), SIGNAL( proxyAuthenticationRequired( const QNetworkProxy &, QAuthenticator * ) ),
connectionType );
smMainNAM, SIGNAL( proxyAuthenticationRequired( const QNetworkProxy &, QAuthenticator * ) ),
Qt::BlockingQueuedConnection );
connect( this, SIGNAL( requestTimedOut( QNetworkReply* ) ),
instance(), SIGNAL( requestTimedOut( QNetworkReply* ) ) );
smMainNAM, SIGNAL( requestTimedOut( QNetworkReply* ) ) );
#ifndef QT_NO_OPENSSL
connect( this, SIGNAL( sslErrors( QNetworkReply *, const QList<QSslError> & ) ),
instance(), SIGNAL( sslErrors( QNetworkReply *, const QList<QSslError> & ) ),
connectionType );
smMainNAM, SIGNAL( sslErrors( QNetworkReply *, const QList<QSslError> & ) ),
Qt::BlockingQueuedConnection );
#endif
}
// check if proxy is enabled
QSettings settings;
QNetworkProxy proxy;
QStringList excludes;
bool proxyEnabled = settings.value( "proxy/proxyEnabled", false ).toBool();
if ( proxyEnabled )
{
@ -354,9 +368,9 @@ void QgsNetworkAccessManager::setupDefaultProxyAndCache()
setFallbackProxyAndExcludes( proxy, excludes );
QNetworkDiskCache *newcache = qobject_cast<QNetworkDiskCache*>( cache() );
QgsNetworkDiskCache *newcache = qobject_cast<QgsNetworkDiskCache*>( cache() );
if ( !newcache )
newcache = new QNetworkDiskCache( this );
newcache = new QgsNetworkDiskCache( this );
QString cacheDirectory = settings.value( "cache/directory", QgsApplication::qgisSettingsDirPath() + "cache" ).toString();
qint64 cacheSize = settings.value( "cache/size", 50 * 1024 * 1024 ).toULongLong();
@ -370,21 +384,3 @@ void QgsNetworkAccessManager::setupDefaultProxyAndCache()
if ( cache() != newcache )
setCache( newcache );
}
void QgsNetworkAccessManager::sendGet( const QNetworkRequest & request )
{
QgsDebugMsg( "Entered" );
QNetworkReply * reply = get( request );
emit requestSent( reply, QObject::sender() );
}
void QgsNetworkAccessManager::deleteReply( QNetworkReply * reply )
{
QgsDebugMsg( "Entered" );
if ( !reply )
{
return;
}
reply->abort();
reply->deleteLater();
}

View File

@ -82,31 +82,13 @@ class CORE_EXPORT QgsNetworkAccessManager : public QNetworkAccessManager
//! Setup the NAM according to the user's settings
void setupDefaultProxyAndCache();
//! return whether the system proxy should be used
bool useSystemProxy() { return mUseSystemProxy; }
public slots:
/** Send GET request, calls get().
* Emits requestSent().
* @param request request to be sent
*/
void sendGet( const QNetworkRequest & request );
/** Abort and delete reply. This slot may be used to abort reply created by instance of this class
* (and which was not moved to another thread) from a different thread. Such reply cannot
* be aborted directly from a different thread. The reply must be also deleted
* in this slot, otherwise it could happen that abort signal comes after the reply was deleted.
* @param reply reply to be aborted.
*/
void deleteReply( QNetworkReply * reply );
signals:
void requestAboutToBeCreated( QNetworkAccessManager::Operation, const QNetworkRequest &, QIODevice * );
void requestCreated( QNetworkReply * );
void requestTimedOut( QNetworkReply * );
/** Emitted when request was sent by request()
* @param reply request reply
* @param sender the object which called request() slot.
*/
void requestSent( QNetworkReply * reply, QObject *sender );
private slots:
void abortRequest();
@ -119,6 +101,8 @@ class CORE_EXPORT QgsNetworkAccessManager : public QNetworkAccessManager
QNetworkProxy mFallbackProxy;
QStringList mExcludedURLs;
bool mUseSystemProxy;
bool mInitialized;
static QgsNetworkAccessManager *smMainNAM;
};
#endif // QGSNETWORKACCESSMANAGER_H

View File

@ -0,0 +1,115 @@
/***************************************************************************
qgsnetworkdiskcache.cpp - Thread-safe interface for QNetworkDiskCache
-------------------
begin : 2016-03-05
copyright : (C) 2016 by Juergen E. Fischer
email : jef at norbit dot de
***************************************************************************/
/***************************************************************************
* *
* 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 "qgsnetworkdiskcache.h"
QgsNetworkDiskCache::ExpirableNetworkDiskCache QgsNetworkDiskCache::smDiskCache;
QMutex QgsNetworkDiskCache::smDiskCacheMutex;
QgsNetworkDiskCache::QgsNetworkDiskCache( QObject *parent )
: QNetworkDiskCache( parent )
{
}
QgsNetworkDiskCache::~QgsNetworkDiskCache()
{
}
QString QgsNetworkDiskCache::cacheDirectory() const
{
QMutexLocker lock( &smDiskCacheMutex );
return smDiskCache.cacheDirectory();
}
void QgsNetworkDiskCache::setCacheDirectory( const QString &cacheDir )
{
QMutexLocker lock( &smDiskCacheMutex );
smDiskCache.setCacheDirectory( cacheDir );
}
qint64 QgsNetworkDiskCache::maximumCacheSize() const
{
QMutexLocker lock( &smDiskCacheMutex );
return smDiskCache.maximumCacheSize();
}
void QgsNetworkDiskCache::setMaximumCacheSize( qint64 size )
{
QMutexLocker lock( &smDiskCacheMutex );
smDiskCache.setMaximumCacheSize( size );
}
qint64 QgsNetworkDiskCache::cacheSize() const
{
QMutexLocker lock( &smDiskCacheMutex );
return smDiskCache.cacheSize();
}
QNetworkCacheMetaData QgsNetworkDiskCache::metaData( const QUrl &url )
{
QMutexLocker lock( &smDiskCacheMutex );
return smDiskCache.metaData( url );
}
void QgsNetworkDiskCache::updateMetaData( const QNetworkCacheMetaData &metaData )
{
QMutexLocker lock( &smDiskCacheMutex );
smDiskCache.updateMetaData( metaData );
}
QIODevice *QgsNetworkDiskCache::data( const QUrl &url )
{
QMutexLocker lock( &smDiskCacheMutex );
return smDiskCache.data( url );
}
bool QgsNetworkDiskCache::remove( const QUrl &url )
{
QMutexLocker lock( &smDiskCacheMutex );
return smDiskCache.remove( url );
}
QIODevice *QgsNetworkDiskCache::prepare( const QNetworkCacheMetaData &metaData )
{
QMutexLocker lock( &smDiskCacheMutex );
return smDiskCache.prepare( metaData );
}
void QgsNetworkDiskCache::insert( QIODevice *device )
{
QMutexLocker lock( &smDiskCacheMutex );
smDiskCache.insert( device );
}
QNetworkCacheMetaData QgsNetworkDiskCache::fileMetaData( const QString &fileName ) const
{
QMutexLocker lock( &smDiskCacheMutex );
return smDiskCache.fileMetaData( fileName );
}
qint64 QgsNetworkDiskCache::expire()
{
QMutexLocker lock( &smDiskCacheMutex );
return smDiskCache.runExpire();
}
void QgsNetworkDiskCache::clear()
{
QMutexLocker lock( &smDiskCacheMutex );
return smDiskCache.clear();
}

View File

@ -0,0 +1,100 @@
/***************************************************************************
qgsnetworkdiskcache.h - Thread-safe interface for QNetworkDiskCache
-------------------
begin : 2016-03-05
copyright : (C) 2016 by Juergen E. Fischer
email : jef at norbit dot de
***************************************************************************/
/***************************************************************************
* *
* 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 QGSNETWORKDISKCACHE_H
#define QGSNETWORKDISKCACHE_H
#include <QNetworkDiskCache>
#include <QMutex>
class QNetworkDiskCache;
/**
* Wrapper implementation of QNetworkDiskCache with all methods guarded by a
* mutex soly for internal use of QgsNetworkAccessManagers
*
* @note not available in Python bindings
*/
class QgsNetworkDiskCache : public QNetworkDiskCache
{
Q_OBJECT
public:
~QgsNetworkDiskCache();
//! @see QNetworkDiskCache::cacheDirectory
QString cacheDirectory() const;
//! @see QNetworkDiskCache::setCacheDirectory
void setCacheDirectory( const QString &cacheDir );
//! @see QNetworkDiskCache::maximumCacheSize()
qint64 maximumCacheSize() const;
//! @see QNetworkDiskCache::setMaximumCacheSize()
void setMaximumCacheSize( qint64 size );
//! @see QNetworkDiskCache::metaData()
QNetworkCacheMetaData metaData( const QUrl &url ) override;
//! @see QNetworkDiskCache::updateMetaData()
void updateMetaData( const QNetworkCacheMetaData &metaData ) override;
//! @see QNetworkDiskCache::data()
QIODevice *data( const QUrl &url ) override;
//! @see QNetworkDiskCache::remove()
bool remove( const QUrl &url ) override;
//! @see QNetworkDiskCache::cacheSize()
qint64 cacheSize() const override;
//! @see QNetworkDiskCache::prepare()
QIODevice *prepare( const QNetworkCacheMetaData &metaData ) override;
//! @see QNetworkDiskCache::insert()
void insert( QIODevice *device ) override;
//! @see QNetworkDiskCache::fileMetaData()
QNetworkCacheMetaData fileMetaData( const QString &fileName ) const;
public slots:
//! @see QNetworkDiskCache::clear()
void clear() override;
protected:
//! @see QNetworkDiskCache::expire()
virtual qint64 expire() override;
private:
QgsNetworkDiskCache( QObject *parent );
Q_DISABLE_COPY( QgsNetworkDiskCache )
class ExpirableNetworkDiskCache : public QNetworkDiskCache
{
public:
ExpirableNetworkDiskCache( QObject *parent = 0 ) : QNetworkDiskCache( parent ) {}
qint64 runExpire() { return QNetworkDiskCache::expire(); }
};
static ExpirableNetworkDiskCache smDiskCache;
static QMutex smDiskCacheMutex;
friend class QgsNetworkAccessManager;
};
#endif // QGSNETWORKDISKCACHE_H

View File

@ -67,6 +67,7 @@ bool QgsCredentialDialog::request( const QString& realm, QString &username, QStr
void QgsCredentialDialog::requestCredentials( const QString& realm, QString *username, QString *password, const QString& message, bool *ok )
{
Q_ASSERT( qApp->thread() == thread() && thread() == QThread::currentThread() );
QgsDebugMsg( "Entering." );
stackedWidget->setCurrentIndex( 0 );

View File

@ -17,8 +17,6 @@
* (at your option) any later version. *
* *
***************************************************************************/
#include <typeinfo>
#include "qgslogger.h"
#include "qgswcscapabilities.h"
#include "qgsowsconnection.h"
@ -32,25 +30,13 @@
#include "qgsrectangle.h"
#include "qgscoordinatereferencesystem.h"
#include "qgsnetworkaccessmanager.h"
#include <qgsmessageoutput.h>
#include <qgsmessagelog.h>
#include "qgsmessageoutput.h"
#include "qgsmessagelog.h"
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QNetworkProxy>
#include <QNetworkDiskCache>
#include <QUrl>
#include <QIcon>
#include <QImage>
#include <QImageReader>
#include <QPainter>
#include <QPixmap>
#include <QSet>
#include <QSettings>
#include <QEventLoop>
#include <QCoreApplication>
#include <QTime>
#ifdef _MSC_VER
#include <float.h>
@ -175,10 +161,9 @@ bool QgsWcsCapabilities::sendRequest( QString const & url )
connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ) );
connect( mCapabilitiesReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( capabilitiesReplyProgress( qint64, qint64 ) ) );
while ( mCapabilitiesReply )
{
QCoreApplication::processEvents( QEventLoop::ExcludeUserInputEvents );
}
QEventLoop loop;
connect( this, SIGNAL( downloadFinished() ), &loop, SLOT( quit() ) );
loop.exec( QEventLoop::ExcludeUserInputEvents );
if ( mCapabilitiesResponse.isEmpty() )
{
@ -271,7 +256,10 @@ bool QgsWcsCapabilities::retrieveServerCapabilities( const QString& preferredVer
QString url = getCapabilitiesUrl( preferredVersion );
if ( ! sendRequest( url ) ) { return false; }
if ( !sendRequest( url ) )
{
return false;
}
QgsDebugMsg( "Converting to Dom." );
@ -325,7 +313,10 @@ bool QgsWcsCapabilities::describeCoverage( QString const &identifier, bool force
QString url = getDescribeCoverageUrl( coverage->identifier );
if ( ! sendRequest( url ) ) { return false; }
if ( !sendRequest( url ) )
{
return false;
}
QgsDebugMsg( "Converting to Dom." );
@ -416,6 +407,8 @@ void QgsWcsCapabilities::capabilitiesReplyFinished()
mCapabilitiesReply->deleteLater();
mCapabilitiesReply = nullptr;
emit downloadFinished();
}
void QgsWcsCapabilities::capabilitiesReplyProgress( qint64 bytesReceived, qint64 bytesTotal )

View File

@ -206,13 +206,14 @@ class QgsWcsCapabilities : public QObject
static QStringList domElementsTexts( const QDomElement &element, const QString &path );
signals:
/** \brief emit a signal to notify of a progress event */
void progressChanged( int theProgress, int theTotalSteps );
/** \brief emit a signal to be caught by qgisapp and display a msg on status bar */
void statusChanged( QString const & theStatusQString );
void downloadFinished();
private slots:
void capabilitiesReplyFinished();
void capabilitiesReplyProgress( qint64, qint64 );

View File

@ -3,7 +3,7 @@
OGC Web Coverage Service layers
-------------------
begin : 2 July, 2012
copyright : (C) (C) 2012 by Radim Blazek
copyright : (C) 2012 by Radim Blazek
email : radim dot blazek at gmail.com
Based on qgswmsprovider.cpp written by Brendan Morley.
@ -19,8 +19,6 @@
* *
***************************************************************************/
#include <typeinfo>
#include "qgslogger.h"
#include "qgswcsprovider.h"
#include "qgscoordinatetransform.h"
@ -31,20 +29,14 @@
#include "qgscoordinatereferencesystem.h"
#include "qgsnetworkaccessmanager.h"
#include "qgsnetworkreplyparser.h"
#include "qgsmessageoutput.h"
#include "qgsmessagelog.h"
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QNetworkProxy>
#include <QNetworkDiskCache>
#include <QUrl>
#include <QRegExp>
#include <QSettings>
#include <QEventLoop>
#include <QCoreApplication>
#include <QTime>
#include <QFile>
#ifdef QGISDEBUG
@ -1589,14 +1581,6 @@ QString QgsWcsProvider::nodeAttribute( const QDomElement &e, const QString& name
return defValue;
}
void QgsWcsProvider::showMessageBox( const QString& title, const QString& text )
{
QgsMessageOutput *message = QgsMessageOutput::createMessageOutput();
message->setTitle( title );
message->setMessage( text, QgsMessageOutput::MessageText );
message->showMessage();
}
QMap<QString, QString> QgsWcsProvider::supportedMimes()
{
QMap<QString, QString> mimes;
@ -1670,16 +1654,13 @@ QGISEXTERN bool isProvider()
int QgsWcsDownloadHandler::sErrors = 0;
QgsWcsDownloadHandler::QgsWcsDownloadHandler( const QUrl& url, QgsWcsAuthorization& auth, QNetworkRequest::CacheLoadControl cacheLoadControl, QByteArray& cachedData, const QString& wcsVersion, QgsError& cachedError )
: mNAM( new QgsNetworkAccessManager )
, mAuth( auth )
: mAuth( auth )
, mEventLoop( new QEventLoop )
, mCacheReply( nullptr )
, mCachedData( cachedData )
, mWcsVersion( wcsVersion )
, mCachedError( cachedError )
{
mNAM->setupDefaultProxyAndCache();
QNetworkRequest request( url );
if ( !mAuth.setAuthorization( request ) )
{
@ -1690,7 +1671,7 @@ QgsWcsDownloadHandler::QgsWcsDownloadHandler( const QUrl& url, QgsWcsAuthorizati
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, cacheLoadControl );
mCacheReply = mNAM->get( request );
mCacheReply = QgsNetworkAccessManager::instance()->get( request );
connect( mCacheReply, SIGNAL( finished() ), this, SLOT( cacheReplyFinished() ) );
connect( mCacheReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( cacheReplyProgress( qint64, qint64 ) ) );
}
@ -1698,7 +1679,6 @@ QgsWcsDownloadHandler::QgsWcsDownloadHandler( const QUrl& url, QgsWcsAuthorizati
QgsWcsDownloadHandler::~QgsWcsDownloadHandler()
{
delete mEventLoop;
delete mNAM;
}
void QgsWcsDownloadHandler::blockingDownload()
@ -1726,7 +1706,7 @@ void QgsWcsDownloadHandler::cacheReplyFinished()
tr( "WCS" ) );
return;
}
mCacheReply = mNAM->get( request );
mCacheReply = QgsNetworkAccessManager::instance()->get( request );
connect( mCacheReply, SIGNAL( finished() ), this, SLOT( cacheReplyFinished() ) );
connect( mCacheReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( cacheReplyProgress( qint64, qint64 ) ) );
@ -1890,7 +1870,7 @@ void QgsWcsDownloadHandler::cacheReplyFinished()
mCacheReply->deleteLater();
mCacheReply = mNAM->get( request );
mCacheReply = QgsNetworkAccessManager::instance()->get( request );
connect( mCacheReply, SIGNAL( finished() ), this, SLOT( cacheReplyFinished() ), Qt::DirectConnection );
connect( mCacheReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( cacheReplyProgress( qint64, qint64 ) ), Qt::DirectConnection );

View File

@ -211,8 +211,6 @@ class QgsWcsProvider : public QgsRasterDataProvider, QgsGdalProviderBase
void dataChanged();
private:
void showMessageBox( const QString& title, const QString& text );
// case insensitive attribute value lookup
static QString nodeAttribute( const QDomElement &e, const QString& name, const QString& defValue = QString::null );
@ -433,7 +431,6 @@ class QgsWcsDownloadHandler : public QObject
protected:
void finish() { QMetaObject::invokeMethod( mEventLoop, "quit", Qt::QueuedConnection ); }
QgsNetworkAccessManager* mNAM;
QgsWcsAuthorization& mAuth;
QEventLoop* mEventLoop;

View File

@ -22,6 +22,7 @@
#include <QSettings>
#include <QCoreApplication>
#include <QEventLoop>
QgsWFSLayerItem::QgsWFSLayerItem( QgsDataItem* parent, QString name, QgsDataSourceURI uri, QString featureType, QString title, QString crsString )
@ -42,7 +43,6 @@ QgsWFSConnectionItem::QgsWFSConnectionItem( QgsDataItem* parent, QString name, Q
: QgsDataCollectionItem( parent, name, path )
, mUri( uri )
, mCapabilities( nullptr )
, mGotCapabilities( false )
{
mIconName = "mIconWfs.svg";
}
@ -53,21 +53,17 @@ QgsWFSConnectionItem::~QgsWFSConnectionItem()
QVector<QgsDataItem*> QgsWFSConnectionItem::createChildren()
{
mGotCapabilities = false;
QgsDataSourceURI uri;
uri.setEncodedUri( mUri );
QgsDebugMsg( "mUri = " + mUri );
mCapabilities = new QgsWFSCapabilities( mUri );
connect( mCapabilities, SIGNAL( gotCapabilities() ), this, SLOT( gotCapabilities() ) );
mCapabilities->requestCapabilities();
while ( !mGotCapabilities )
{
QCoreApplication::processEvents( QEventLoop::ExcludeUserInputEvents );
}
QEventLoop loop;
connect( mCapabilities, SIGNAL( gotCapabilities() ), &loop, SLOT( quit() ) );
loop.exec( QEventLoop::ExcludeUserInputEvents );
QVector<QgsDataItem*> layers;
if ( mCapabilities->errorCode() == QgsWFSCapabilities::NoError )
@ -92,11 +88,6 @@ QVector<QgsDataItem*> QgsWFSConnectionItem::createChildren()
return layers;
}
void QgsWFSConnectionItem::gotCapabilities()
{
mGotCapabilities = true;
}
QList<QAction*> QgsWFSConnectionItem::actions()
{
QList<QAction*> lst;

View File

@ -52,8 +52,6 @@ class QgsWFSConnectionItem : public QgsDataCollectionItem
virtual QList<QAction*> actions() override;
private slots:
void gotCapabilities();
void editConnection();
void deleteConnection();
@ -61,7 +59,6 @@ class QgsWFSConnectionItem : public QgsDataCollectionItem
QString mUri;
QgsWFSCapabilities* mCapabilities;
bool mGotCapabilities;
};

View File

@ -1872,7 +1872,6 @@ QgsWmsCapabilitiesDownload::QgsWmsCapabilitiesDownload( bool forceRefresh, QObje
, mIsAborted( false )
, mForceRefresh( forceRefresh )
{
connectManager();
}
QgsWmsCapabilitiesDownload::QgsWmsCapabilitiesDownload( const QString& baseUrl, const QgsWmsAuthorization& auth, bool forceRefresh, QObject *parent )
@ -1883,17 +1882,6 @@ QgsWmsCapabilitiesDownload::QgsWmsCapabilitiesDownload( const QString& baseUrl,
, mIsAborted( false )
, mForceRefresh( forceRefresh )
{
connectManager();
}
void QgsWmsCapabilitiesDownload::connectManager()
{
// The instance of this class may live on a thread different from QgsNetworkAccessManager instance's thread,
// so we cannot call QgsNetworkAccessManager::get() directly and we must send a signal instead.
connect( this, SIGNAL( sendRequest( const QNetworkRequest & ) ),
QgsNetworkAccessManager::instance(), SLOT( sendGet( const QNetworkRequest & ) ) );
connect( this, SIGNAL( deleteReply( QNetworkReply * ) ),
QgsNetworkAccessManager::instance(), SLOT( deleteReply( QNetworkReply * ) ) );
}
QgsWmsCapabilitiesDownload::~QgsWmsCapabilitiesDownload()
@ -1934,9 +1922,9 @@ bool QgsWmsCapabilitiesDownload::downloadCapabilities()
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, mForceRefresh ? QNetworkRequest::AlwaysNetwork : QNetworkRequest::PreferCache );
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
connect( QgsNetworkAccessManager::instance(), SIGNAL( requestSent( QNetworkReply *, QObject * ) ),
SLOT( requestSent( QNetworkReply *, QObject * ) ) );
emit sendRequest( request );
mCapabilitiesReply = QgsNetworkAccessManager::instance()->get( request );
connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ), Qt::DirectConnection );
connect( mCapabilitiesReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( capabilitiesReplyProgress( qint64, qint64 ) ), Qt::DirectConnection );
QEventLoop loop;
connect( this, SIGNAL( downloadFinished() ), &loop, SLOT( quit() ) );
@ -1945,40 +1933,13 @@ bool QgsWmsCapabilitiesDownload::downloadCapabilities()
return mError.isEmpty();
}
void QgsWmsCapabilitiesDownload::requestSent( QNetworkReply * reply, QObject *sender )
{
QgsDebugMsg( "Entered" );
if ( sender != this ) // it is not our reply
{
return;
}
disconnect( QgsNetworkAccessManager::instance(), SIGNAL( requestSent( QNetworkReply *, QObject * ) ),
this, SLOT( requestSent( QNetworkReply *, QObject * ) ) );
if ( !reply )
{
emit downloadFinished();
return;
}
if ( mIsAborted )
{
emit deleteReply( reply );
emit downloadFinished();
return;
}
// Note: the reply was created on QgsNetworkAccessManager's thread
mCapabilitiesReply = reply;
connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ), Qt::DirectConnection );
connect( mCapabilitiesReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( capabilitiesReplyProgress( qint64, qint64 ) ), Qt::DirectConnection );
}
void QgsWmsCapabilitiesDownload::abort()
{
QgsDebugMsg( "Entered" );
mIsAborted = true;
if ( mCapabilitiesReply )
{
emit deleteReply( mCapabilitiesReply );
mCapabilitiesReply->deleteLater();
mCapabilitiesReply = nullptr;
}
}
@ -2029,11 +1990,9 @@ void QgsWmsCapabilitiesDownload::capabilitiesReplyFinished()
mCapabilitiesReply = nullptr;
QgsDebugMsg( QString( "redirected getcapabilities: %1 forceRefresh=%2" ).arg( redirect.toString() ).arg( mForceRefresh ) );
//mCapabilitiesReply = QgsNetworkAccessManager::instance()->get( request );
connect( QgsNetworkAccessManager::instance(),
SIGNAL( requestSent( QNetworkReply *, QObject * ) ),
SLOT( requestSent( QNetworkReply *, QObject * ) ) );
emit sendRequest( request );
mCapabilitiesReply = QgsNetworkAccessManager::instance()->get( request );
connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ), Qt::DirectConnection );
connect( mCapabilitiesReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( capabilitiesReplyProgress( qint64, qint64 ) ), Qt::DirectConnection );
return;
}
}

View File

@ -685,11 +685,6 @@ class QgsWmsCapabilities
/** Class that handles download of capabilities.
* Methods of this class may only be called directly from the thread to which instance of the class has affinity.
* It is possible to connect to abort() slot from another thread however.
*/
/* The requirement to call methods only from the thread to which this class instance has affinity guarantees that
* abort() cannot be called in the middle of another method and makes it simple to check if the request was aborted.
*/
class QgsWmsCapabilitiesDownload : public QObject
{
@ -710,8 +705,7 @@ class QgsWmsCapabilitiesDownload : public QObject
QByteArray response() const { return mHttpCapabilitiesResponse; }
public slots:
/** Abort network request immediately */
//! Abort network request immediately
void abort();
signals:
@ -721,14 +715,7 @@ class QgsWmsCapabilitiesDownload : public QObject
/** \brief emit a signal once the download is finished */
void downloadFinished();
/** Send request via signal/slot to main another thread */
void sendRequest( const QNetworkRequest & request );
/** Abort request through QgsNetworkAccessManager */
void deleteReply( QNetworkReply * reply );
protected slots:
void requestSent( QNetworkReply * reply, QObject *sender );
void capabilitiesReplyFinished();
void capabilitiesReplyProgress( qint64, qint64 );
@ -752,9 +739,6 @@ class QgsWmsCapabilitiesDownload : public QObject
bool mIsAborted;
bool mForceRefresh;
private:
void connectManager();
};

View File

@ -24,10 +24,6 @@
* *
***************************************************************************/
#include <QTimer>
#include <typeinfo>
#include "qgslogger.h"
#include "qgswmsprovider.h"
#include "qgswmsconnection.h"
@ -50,27 +46,19 @@
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QNetworkProxy>
#include <QNetworkDiskCache>
#include <QtXmlPatterns/QXmlSchema>
#include <QtXmlPatterns/QXmlSchemaValidator>
#include <QUrl>
#include <QIcon>
#include <QImage>
#include <QImageReader>
#include <QPainter>
#include <QSet>
#include <QSettings>
#include <QEventLoop>
#include <QCoreApplication>
#include <QTextCodec>
#include <QTime>
#include <QThread>
#include <QScriptEngine>
#include <QScriptValue>
#include <QScriptValueIterator>
#include <QNetworkDiskCache>
#include <QTimer>
#include <ogr_api.h>
@ -555,10 +543,6 @@ QImage *QgsWmsProvider::draw( QgsRectangle const &viewExtent, int pixelWidth, in
QgsWmsImageDownloadHandler handler( dataSourceUri(), url, mSettings.authorization(), mCachedImage );
handler.downloadBlocking();
//QTime t;
//t.start();
}
else
{
@ -3191,14 +3175,11 @@ QgsWmsImageDownloadHandler::QgsWmsImageDownloadHandler( const QString& providerU
: mProviderUri( providerUri )
, mCachedImage( image )
, mEventLoop( new QEventLoop )
, mNAM( new QgsNetworkAccessManager )
{
mNAM->setupDefaultProxyAndCache();
QNetworkRequest request( url );
auth.setAuthorization( request );
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
mCacheReply = mNAM->get( request );
mCacheReply = QgsNetworkAccessManager::instance()->get( request );
connect( mCacheReply, SIGNAL( finished() ), this, SLOT( cacheReplyFinished() ) );
connect( mCacheReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( cacheReplyProgress( qint64, qint64 ) ) );
@ -3208,7 +3189,6 @@ QgsWmsImageDownloadHandler::QgsWmsImageDownloadHandler( const QString& providerU
QgsWmsImageDownloadHandler::~QgsWmsImageDownloadHandler()
{
delete mNAM;
delete mEventLoop;
}
@ -3229,7 +3209,7 @@ void QgsWmsImageDownloadHandler::cacheReplyFinished()
mCacheReply->deleteLater();
QgsDebugMsg( QString( "redirected getmap: %1" ).arg( redirect.toString() ) );
mCacheReply = mNAM->get( QNetworkRequest( redirect.toUrl() ) );
mCacheReply = QgsNetworkAccessManager::instance()->get( QNetworkRequest( redirect.toUrl() ) );
connect( mCacheReply, SIGNAL( finished() ), this, SLOT( cacheReplyFinished() ) );
return;
}
@ -3333,12 +3313,9 @@ QgsWmsTiledImageDownloadHandler::QgsWmsTiledImageDownloadHandler( const QString&
, mCachedImage( cachedImage )
, mCachedViewExtent( cachedViewExtent )
, mEventLoop( new QEventLoop )
, mNAM( new QgsNetworkAccessManager )
, mTileReqNo( tileReqNo )
, mSmoothPixmapTransform( smoothPixmapTransform )
{
mNAM->setupDefaultProxyAndCache();
Q_FOREACH ( const TileRequest& r, requests )
{
QNetworkRequest request( r.url );
@ -3350,7 +3327,7 @@ QgsWmsTiledImageDownloadHandler::QgsWmsTiledImageDownloadHandler( const QString&
request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileRect ), r.rect );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileRetry ), 0 );
QNetworkReply *reply = mNAM->get( request );
QNetworkReply *reply = QgsNetworkAccessManager::instance()->get( request );
connect( reply, SIGNAL( finished() ), this, SLOT( tileReplyFinished() ) );
mReplies << reply;
@ -3359,7 +3336,6 @@ QgsWmsTiledImageDownloadHandler::QgsWmsTiledImageDownloadHandler( const QString&
QgsWmsTiledImageDownloadHandler::~QgsWmsTiledImageDownloadHandler()
{
delete mNAM;
delete mEventLoop;
}
@ -3393,9 +3369,9 @@ void QgsWmsTiledImageDownloadHandler::tileReplyFinished()
}
#endif
if ( mNAM->cache() )
if ( QgsNetworkAccessManager::instance()->cache() )
{
QNetworkCacheMetaData cmd = mNAM->cache()->metaData( reply->request().url() );
QNetworkCacheMetaData cmd = QgsNetworkAccessManager::instance()->cache()->metaData( reply->request().url() );
QNetworkCacheMetaData::RawHeaderList hl;
Q_FOREACH ( const QNetworkCacheMetaData::RawHeader &h, cmd.rawHeaders() )
@ -3412,7 +3388,7 @@ void QgsWmsTiledImageDownloadHandler::tileReplyFinished()
cmd.setExpirationDate( QDateTime::currentDateTime().addSecs( s.value( "/qgis/defaultTileExpiry", "24" ).toInt() * 60 * 60 ) );
}
mNAM->cache()->updateMetaData( cmd );
QgsNetworkAccessManager::instance()->cache()->updateMetaData( cmd );
}
int tileReqNo = reply->request().attribute( static_cast<QNetworkRequest::Attribute>( TileReqNo ) ).toInt();
@ -3448,7 +3424,7 @@ void QgsWmsTiledImageDownloadHandler::tileReplyFinished()
reply->deleteLater();
QgsDebugMsg( QString( "redirected gettile: %1" ).arg( redirect.toString() ) );
reply = mNAM->get( request );
reply = QgsNetworkAccessManager::instance()->get( request );
mReplies << reply;
connect( reply, SIGNAL( finished() ), this, SLOT( tileReplyFinished() ) );
@ -3624,7 +3600,7 @@ void QgsWmsTiledImageDownloadHandler::repeatTileRequest( QNetworkRequest const &
QgsDebugMsg( QString( "repeat tileRequest %1 %2(retry %3) for url: %4" ).arg( tileReqNo ).arg( tileNo ).arg( retry ).arg( url ) );
request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileRetry ), retry );
QNetworkReply *reply = mNAM->get( request );
QNetworkReply *reply = QgsNetworkAccessManager::instance()->get( request );
mReplies << reply;
connect( reply, SIGNAL( finished() ), this, SLOT( tileReplyFinished() ) );
}

View File

@ -589,7 +589,6 @@ class QgsWmsImageDownloadHandler : public QObject
QImage* mCachedImage;
QEventLoop* mEventLoop;
QgsNetworkAccessManager* mNAM;
};
@ -635,7 +634,6 @@ class QgsWmsTiledImageDownloadHandler : public QObject
QgsRectangle mCachedViewExtent;
QEventLoop* mEventLoop;
QgsNetworkAccessManager* mNAM;
int mTileReqNo;
bool mSmoothPixmapTransform;