qgswfsfeatureiterator.cpp (QGIS-final-3_10_11) | : | qgswfsfeatureiterator.cpp (QGIS-final-3_10_12) | ||
---|---|---|---|---|
skipping to change at line 36 | skipping to change at line 36 | |||
#include "qgswfsconstants.h" | #include "qgswfsconstants.h" | |||
#include "qgswfsfeatureiterator.h" | #include "qgswfsfeatureiterator.h" | |||
#include "qgswfsprovider.h" | #include "qgswfsprovider.h" | |||
#include "qgswfsshareddata.h" | #include "qgswfsshareddata.h" | |||
#include "qgswfsutils.h" | #include "qgswfsutils.h" | |||
#include "qgslogger.h" | #include "qgslogger.h" | |||
#include "qgssettings.h" | #include "qgssettings.h" | |||
#include "qgsexception.h" | #include "qgsexception.h" | |||
#include "qgsfeedback.h" | #include "qgsfeedback.h" | |||
#include "qgssqliteutils.h" | #include "qgssqliteutils.h" | |||
#include "qgsnetworkaccessmanager.h" | ||||
#include <algorithm> | #include <algorithm> | |||
#include <QDir> | #include <QDir> | |||
#include <QProgressDialog> | #include <QProgressDialog> | |||
#include <QTimer> | #include <QTimer> | |||
#include <QStyle> | #include <QStyle> | |||
#include <sqlite3.h> | #include <sqlite3.h> | |||
QgsWFSFeatureHitsAsyncRequest::QgsWFSFeatureHitsAsyncRequest( QgsWFSDataSourceUR I &uri ) | QgsWFSFeatureHitsAsyncRequest::QgsWFSFeatureHitsAsyncRequest( QgsWFSDataSourceUR I &uri ) | |||
skipping to change at line 87 | skipping to change at line 88 | |||
emit gotHitsResponse(); | emit gotHitsResponse(); | |||
} | } | |||
QString QgsWFSFeatureHitsAsyncRequest::errorMessageWithReason( const QString &re ason ) | QString QgsWFSFeatureHitsAsyncRequest::errorMessageWithReason( const QString &re ason ) | |||
{ | { | |||
return tr( "Download of feature count failed: %1" ).arg( reason ); | return tr( "Download of feature count failed: %1" ).arg( reason ); | |||
} | } | |||
// ------------------------- | // ------------------------- | |||
QgsWFSFeatureDownloader::QgsWFSFeatureDownloader( QgsWFSSharedData *shared ) | QgsWFSFeatureDownloader::QgsWFSFeatureDownloader( QgsWFSSharedData *shared, bool requestMadeFromMainThread ) | |||
: QgsWfsRequest( shared->mURI ) | : QgsWfsRequest( shared->mURI ) | |||
, mShared( shared ) | , mShared( shared ) | |||
, mStop( false ) | , mStop( false ) | |||
, mProgressDialogShowImmediately( false ) | , mProgressDialogShowImmediately( false ) | |||
, mPageSize( shared->mPageSize ) | , mPageSize( shared->mPageSize ) | |||
, mRemoveNSPrefix( false ) | , mRemoveNSPrefix( false ) | |||
, mNumberMatched( -1 ) | , mNumberMatched( -1 ) | |||
, mFeatureHitsAsyncRequest( shared->mURI ) | , mFeatureHitsAsyncRequest( shared->mURI ) | |||
, mTotalDownloadedFeatureCount( 0 ) | , mTotalDownloadedFeatureCount( 0 ) | |||
{ | { | |||
// Needed because used by a signal | // Needed because used by a signal | |||
qRegisterMetaType< QVector<QgsWFSFeatureGmlIdPair> >( "QVector<QgsWFSFeatureGm lIdPair>" ); | qRegisterMetaType< QVector<QgsWFSFeatureGmlIdPair> >( "QVector<QgsWFSFeatureGm lIdPair>" ); | |||
if ( requestMadeFromMainThread ) | ||||
{ | ||||
auto emitResumeMainThread = [this]() | ||||
{ | ||||
emit resumeMainThread(); | ||||
}; | ||||
connect( QgsNetworkAccessManager::instance(), &QgsNetworkAccessManager::auth | ||||
RequestOccurred, | ||||
this, emitResumeMainThread, Qt::DirectConnection ); | ||||
connect( QgsNetworkAccessManager::instance(), &QgsNetworkAccessManager::prox | ||||
yAuthenticationRequired, | ||||
this, emitResumeMainThread, Qt::DirectConnection ); | ||||
#ifndef QT_NO_SSL | ||||
connect( QgsNetworkAccessManager::instance(), &QgsNetworkAccessManager::sslE | ||||
rrorsOccurred, | ||||
this, emitResumeMainThread, Qt::DirectConnection ); | ||||
#endif | ||||
} | ||||
} | } | |||
QgsWFSFeatureDownloader::~QgsWFSFeatureDownloader() | QgsWFSFeatureDownloader::~QgsWFSFeatureDownloader() | |||
{ | { | |||
stop(); | stop(); | |||
if ( mProgressDialog ) | if ( mProgressDialog ) | |||
mProgressDialog->deleteLater(); | mProgressDialog->deleteLater(); | |||
if ( mTimer ) | if ( mTimer ) | |||
mTimer->deleteLater(); | mTimer->deleteLater(); | |||
skipping to change at line 896 | skipping to change at line 913 | |||
mFeatureHitsAsyncRequest.abort(); | mFeatureHitsAsyncRequest.abort(); | |||
} | } | |||
QString QgsWFSFeatureDownloader::errorMessageWithReason( const QString &reason ) | QString QgsWFSFeatureDownloader::errorMessageWithReason( const QString &reason ) | |||
{ | { | |||
return tr( "Download of features failed: %1" ).arg( reason ); | return tr( "Download of features failed: %1" ).arg( reason ); | |||
} | } | |||
QgsWFSThreadedFeatureDownloader::QgsWFSThreadedFeatureDownloader( QgsWFSSharedDa ta *shared ) | QgsWFSThreadedFeatureDownloader::QgsWFSThreadedFeatureDownloader( QgsWFSSharedDa ta *shared ) | |||
: mShared( shared ) | : mShared( shared ) | |||
, mRequestMadeFromMainThread( QThread::currentThread() == QApplication::instan ce()->thread() ) | ||||
{ | { | |||
} | } | |||
QgsWFSThreadedFeatureDownloader::~QgsWFSThreadedFeatureDownloader() | QgsWFSThreadedFeatureDownloader::~QgsWFSThreadedFeatureDownloader() | |||
{ | { | |||
stop(); | stop(); | |||
} | } | |||
void QgsWFSThreadedFeatureDownloader::stop() | void QgsWFSThreadedFeatureDownloader::stop() | |||
{ | { | |||
skipping to change at line 929 | skipping to change at line 947 | |||
QMutexLocker locker( &mWaitMutex ); | QMutexLocker locker( &mWaitMutex ); | |||
while ( !mDownloader ) | while ( !mDownloader ) | |||
{ | { | |||
mWaitCond.wait( &mWaitMutex ); | mWaitCond.wait( &mWaitMutex ); | |||
} | } | |||
} | } | |||
void QgsWFSThreadedFeatureDownloader::run() | void QgsWFSThreadedFeatureDownloader::run() | |||
{ | { | |||
// We need to construct it in the run() method (i.e. in the new thread) | // We need to construct it in the run() method (i.e. in the new thread) | |||
mDownloader = new QgsWFSFeatureDownloader( mShared ); | mDownloader = new QgsWFSFeatureDownloader( mShared, mRequestMadeFromMainThread ); | |||
{ | { | |||
QMutexLocker locker( &mWaitMutex ); | QMutexLocker locker( &mWaitMutex ); | |||
mWaitCond.wakeOne(); | mWaitCond.wakeOne(); | |||
} | } | |||
mDownloader->run( true, /* serialize features */ | mDownloader->run( true, /* serialize features */ | |||
mShared->requestLimit() /* user max features */ ); | mShared->requestLimit() /* user max features */ ); | |||
} | } | |||
// ------------------------- | // ------------------------- | |||
skipping to change at line 1135 | skipping to change at line 1153 | |||
void QgsWFSFeatureIterator::connectSignals( QgsWFSFeatureDownloader *downloader ) | void QgsWFSFeatureIterator::connectSignals( QgsWFSFeatureDownloader *downloader ) | |||
{ | { | |||
// We want to run the slot for that signal in the same thread as the sender | // We want to run the slot for that signal in the same thread as the sender | |||
// so as to avoid the list of features to accumulate without control in | // so as to avoid the list of features to accumulate without control in | |||
// memory | // memory | |||
connect( downloader, static_cast<void ( QgsWFSFeatureDownloader::* )( QVector< QgsWFSFeatureGmlIdPair> )>( &QgsWFSFeatureDownloader::featureReceived ), | connect( downloader, static_cast<void ( QgsWFSFeatureDownloader::* )( QVector< QgsWFSFeatureGmlIdPair> )>( &QgsWFSFeatureDownloader::featureReceived ), | |||
this, &QgsWFSFeatureIterator::featureReceivedSynchronous, Qt::DirectC onnection ); | this, &QgsWFSFeatureIterator::featureReceivedSynchronous, Qt::DirectC onnection ); | |||
connect( downloader, &QgsWFSFeatureDownloader::endOfDownload, | connect( downloader, &QgsWFSFeatureDownloader::endOfDownload, | |||
this, &QgsWFSFeatureIterator::endOfDownloadSynchronous, Qt::DirectCon nection ); | this, &QgsWFSFeatureIterator::endOfDownloadSynchronous, Qt::DirectCon nection ); | |||
connect( downloader, &QgsWFSFeatureDownloader::resumeMainThread, | ||||
this, &QgsWFSFeatureIterator::resumeMainThreadSynchronous, Qt::Direct | ||||
Connection ); | ||||
} | } | |||
void QgsWFSFeatureIterator::endOfDownloadSynchronous( bool ) | void QgsWFSFeatureIterator::endOfDownloadSynchronous( bool ) | |||
{ | { | |||
// Wake up waiting loop | // Wake up waiting loop | |||
QMutexLocker locker( &mMutex ); | QMutexLocker locker( &mMutex ); | |||
mDownloadFinished = true; | mDownloadFinished = true; | |||
mWaitCond.wakeOne(); | mWaitCond.wakeOne(); | |||
} | } | |||
void QgsWFSFeatureIterator::resumeMainThreadSynchronous() | ||||
{ | ||||
// Wake up waiting loop | ||||
QMutexLocker locker( &mMutex ); | ||||
mProcessEvents = true; | ||||
mWaitCond.wakeOne(); | ||||
} | ||||
void QgsWFSFeatureIterator::setInterruptionChecker( QgsFeedback *interruptionChe cker ) | void QgsWFSFeatureIterator::setInterruptionChecker( QgsFeedback *interruptionChe cker ) | |||
{ | { | |||
mInterruptionChecker = interruptionChecker; | mInterruptionChecker = interruptionChecker; | |||
} | } | |||
// This method will serialize the receive feature list, first into memory, and | // This method will serialize the receive feature list, first into memory, and | |||
// if it goes above a given threshold, on disk | // if it goes above a given threshold, on disk | |||
void QgsWFSFeatureIterator::featureReceivedSynchronous( const QVector<QgsWFSFeat ureGmlIdPair> &list ) | void QgsWFSFeatureIterator::featureReceivedSynchronous( const QVector<QgsWFSFeat ureGmlIdPair> &list ) | |||
{ | { | |||
QgsDebugMsgLevel( QStringLiteral( "QgsWFSFeatureIterator::featureReceivedSynch ronous %1 features" ).arg( list.size() ), 4 ); | QgsDebugMsgLevel( QStringLiteral( "QgsWFSFeatureIterator::featureReceivedSynch ronous %1 features" ).arg( list.size() ), 4 ); | |||
skipping to change at line 1270 | skipping to change at line 1299 | |||
if ( stmt.step() == SQLITE_ROW ) | if ( stmt.step() == SQLITE_ROW ) | |||
{ | { | |||
f.setId( stmt.columnAsInt64( 0 ) ); | f.setId( stmt.columnAsInt64( 0 ) ); | |||
Q_ASSERT( stmt.step() != SQLITE_ROW ); | Q_ASSERT( stmt.step() != SQLITE_ROW ); | |||
} | } | |||
} | } | |||
return true; | return true; | |||
} | } | |||
const bool requestMadeFromMainThread = QThread::currentThread() == QApplicatio | ||||
n::instance()->thread(); | ||||
// Second step is to wait for features to be notified by the downloader | // Second step is to wait for features to be notified by the downloader | |||
while ( true ) | while ( true ) | |||
{ | { | |||
{ | { | |||
QMutexLocker locker( &mMutex ); | QMutexLocker locker( &mMutex ); | |||
mNewFeaturesReceived = false; | mNewFeaturesReceived = false; | |||
} | } | |||
// Initialize a reader stream if there's a writer stream available | // Initialize a reader stream if there's a writer stream available | |||
if ( !mReaderStream ) | if ( !mReaderStream ) | |||
skipping to change at line 1403 | skipping to change at line 1434 | |||
const int timeout = ( requestTimeout > 0 ) ? | const int timeout = ( requestTimeout > 0 ) ? | |||
std::min( requestTimeout - timeRequestTimeout.elapsed( ), delayCheckInterruption ) : | std::min( requestTimeout - timeRequestTimeout.elapsed( ), delayCheckInterruption ) : | |||
delayCheckInterruption; | delayCheckInterruption; | |||
if ( timeout < 0 ) | if ( timeout < 0 ) | |||
{ | { | |||
mTimeoutOrInterruptionOccurred = true; | mTimeoutOrInterruptionOccurred = true; | |||
mDownloadFinished = true; | mDownloadFinished = true; | |||
break; | break; | |||
} | } | |||
mWaitCond.wait( &mMutex, timeout ); | mWaitCond.wait( &mMutex, timeout ); | |||
if ( requestMadeFromMainThread && mProcessEvents ) | ||||
{ | ||||
QgsApplication::instance()->processEvents(); | ||||
mProcessEvents = false; | ||||
} | ||||
if ( mInterruptionChecker && mInterruptionChecker->isCanceled() ) | if ( mInterruptionChecker && mInterruptionChecker->isCanceled() ) | |||
{ | { | |||
mTimeoutOrInterruptionOccurred = true; | mTimeoutOrInterruptionOccurred = true; | |||
mDownloadFinished = true; | mDownloadFinished = true; | |||
break; | break; | |||
} | } | |||
} | } | |||
} | } | |||
} | } | |||
End of changes. 9 change blocks. | ||||
2 lines changed or deleted | 43 lines changed or added |