Skip to content

Commit 5610ebe

Browse files
committed
fix crash when redownloading or canceling
1 parent 9d45077 commit 5610ebe

3 files changed

Lines changed: 56 additions & 37 deletions

File tree

‎python/core/qgsnetworkcontentfetcherregistry.sip.in‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ Emitted when the download actually starts
8484
void cancelTriggered();
8585
%Docstring
8686
Emitted when download is canceled.
87+
%End
88+
89+
void taskCompleted();
90+
%Docstring
91+
Emitted when the download is finished (although file not accessible yet)
8792
%End
8893

8994
};
@@ -118,7 +123,7 @@ Create the registry for temporary downloaded files
118123

119124
~QgsNetworkContentFetcherRegistry();
120125

121-
const QgsFetchedContent *fetch( const QUrl &url, const FetchingMode &fetchingMode = DownloadLater );
126+
const QgsFetchedContent *fetch( const QUrl &url, const FetchingMode fetchingMode = DownloadLater );
122127
%Docstring
123128
Initialize a download for the given URL
124129

‎src/core/qgsnetworkcontentfetcherregistry.cpp‎

Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#include "qgsnetworkcontentfetcherregistry.h"
2020

2121
#include "qgsapplication.h"
22-
#include "qgsnetworkcontentfetchertask.h"
2322

2423
QgsNetworkContentFetcherRegistry::QgsNetworkContentFetcherRegistry()
2524
: QObject()
@@ -37,7 +36,7 @@ QgsNetworkContentFetcherRegistry::~QgsNetworkContentFetcherRegistry()
3736
mFileRegistry.clear();
3837
}
3938

40-
const QgsFetchedContent *QgsNetworkContentFetcherRegistry::fetch( const QUrl &url, const FetchingMode &fetchingMode )
39+
const QgsFetchedContent *QgsNetworkContentFetcherRegistry::fetch( const QUrl &url, const FetchingMode fetchingMode )
4140
{
4241
QMutexLocker locker( &mMutex );
4342
if ( mFileRegistry.contains( url ) )
@@ -46,72 +45,87 @@ const QgsFetchedContent *QgsNetworkContentFetcherRegistry::fetch( const QUrl &ur
4645
}
4746

4847
QgsFetchedContent *content = new QgsFetchedContent( nullptr, QgsFetchedContent::NotStarted );
49-
content->mFetchingTask = new QgsNetworkContentFetcherTask( url );
5048

5149
// start
5250
QObject::connect( content, &QgsFetchedContent::downloadStarted, this, [ = ]( const bool redownload )
5351
{
54-
QMutexLocker locker( &mMutex );
55-
if ( mFileRegistry.contains( url ) && redownload )
52+
if ( redownload && content->status() == QgsFetchedContent::Downloading )
5653
{
57-
QgsFetchedContent *content = mFileRegistry[url];
58-
if ( mFileRegistry.value( url )->status() == QgsFetchedContent::Downloading )
5954
{
60-
content->cancel();
55+
QMutexLocker locker( &mMutex );
56+
if ( content->mFetchingTask )
57+
disconnect( content->mFetchingTask, &QgsNetworkContentFetcherTask::fetched, content, &QgsFetchedContent::taskCompleted );
6158
}
59+
// no locker when calling cancel!
60+
content->cancel();
6261
}
63-
if ( ( mFileRegistry.contains( url ) && mFileRegistry.value( url )->status() == QgsFetchedContent::NotStarted ) || redownload )
62+
QMutexLocker locker( &mMutex );
63+
if ( redownload ||
64+
content->status() == QgsFetchedContent::NotStarted ||
65+
content->status() == QgsFetchedContent::Failed )
6466
{
67+
content->mFetchingTask = new QgsNetworkContentFetcherTask( url );
68+
connect( content->mFetchingTask, &QgsNetworkContentFetcherTask::fetched, content, &QgsFetchedContent::taskCompleted );
6569
QgsApplication::instance()->taskManager()->addTask( content->mFetchingTask );
70+
content->mStatus = QgsFetchedContent::Downloading;
6671
}
6772
} );
6873

6974
// cancel
7075
QObject::connect( content, &QgsFetchedContent::cancelTriggered, this, [ = ]()
7176
{
7277
QMutexLocker locker( &mMutex );
73-
if ( content->mFetchingTask->canCancel() )
78+
if ( content->mFetchingTask && content->mFetchingTask->canCancel() )
7479
{
7580
content->mFetchingTask->cancel();
7681
}
7782
if ( content->mFile )
7883
{
7984
content->mFile->deleteLater();
80-
mFileRegistry[url]->setFilePath( QStringLiteral() );
85+
content->mFilePath = QString();
8186
}
8287
} );
8388

8489
// finished
85-
QObject::connect( content->mFetchingTask, &QgsNetworkContentFetcherTask::fetched, this, [ = ]()
90+
connect( content, &QgsFetchedContent::taskCompleted, this, [ = ]()
8691
{
8792
QMutexLocker locker( &mMutex );
88-
QNetworkReply *reply = content->mFetchingTask->reply();
89-
QgsFetchedContent *content = mFileRegistry.value( url );
90-
if ( reply->error() == QNetworkReply::NoError )
93+
if ( !content->mFetchingTask || !content->mFetchingTask->reply() )
9194
{
92-
QTemporaryFile *tf = new QTemporaryFile( QStringLiteral( "XXXXXX" ) );
93-
content->setFile( tf );
94-
tf->open();
95-
content->mFile->write( reply->readAll() );
96-
// Qt docs notes that on some system if fileName is not called before close, file might get deleted
97-
content->setFilePath( tf->fileName() );
98-
tf->close();
99-
content->setStatus( QgsFetchedContent::Finished );
95+
// if no reply, it has been canceled
96+
content->mStatus = QgsFetchedContent::Failed;
97+
content->mError = QNetworkReply::OperationCanceledError;
98+
content->mFilePath = QString();
10099
}
101100
else
102101
{
103-
content->setStatus( QgsFetchedContent::Failed );
104-
content->setError( reply->error() );
105-
content->setFilePath( QStringLiteral() );
102+
QNetworkReply *reply = content->mFetchingTask->reply();
103+
if ( reply->error() == QNetworkReply::NoError )
104+
{
105+
QTemporaryFile *tf = new QTemporaryFile( QStringLiteral( "XXXXXX" ) );
106+
content->mFile = tf;
107+
tf->open();
108+
content->mFile->write( reply->readAll() );
109+
// Qt docs notes that on some system if fileName is not called before close, file might get deleted
110+
content->mFilePath = tf->fileName();
111+
tf->close();
112+
content->mStatus = QgsFetchedContent::Finished;
113+
}
114+
else
115+
{
116+
content->mStatus = QgsFetchedContent::Failed;
117+
content->mError = reply->error();
118+
content->mFilePath = QString();
119+
}
106120
}
107121
content->emitFetched();
108122
} );
109123

124+
mFileRegistry.insert( url, content );
125+
110126
if ( fetchingMode == DownloadImmediately )
111127
content->download();
112128

113-
mFileRegistry.insert( url, content );
114-
115129
return content;
116130
}
117131

@@ -162,7 +176,7 @@ QString QgsNetworkContentFetcherRegistry::localPath( const QString &filePathOrUr
162176
else
163177
{
164178
// if the file is not downloaded yet or has failed, return empty string
165-
path = QStringLiteral();
179+
path = QString();
166180
}
167181
}
168182
else

‎src/core/qgsnetworkcontentfetcherregistry.h‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929

3030
class QTemporaryFile;
3131

32-
class QgsNetworkContentFetcherTask;
32+
#include "qgstaskmanager.h"
33+
#include "qgsnetworkcontentfetchertask.h"
3334

3435

3536
/**
@@ -94,15 +95,14 @@ class CORE_EXPORT QgsFetchedContent : public QObject
9495
//! Emitted when download is canceled.
9596
void cancelTriggered();
9697

98+
//! Emitted when the download is finished (although file not accessible yet)
99+
void taskCompleted();
100+
97101
private:
98-
void setFile( QTemporaryFile *file ) {mFile = file;}
99-
void setStatus( ContentStatus status ) {mStatus = status;}
100-
void setError( QNetworkReply::NetworkError error ) {mError = error;}
101-
void setFilePath( const QString &filePath ) {mFilePath = filePath;}
102102
void emitFetched() {emit fetched();}
103103
QTemporaryFile *mFile;
104104
QString mFilePath = QStringLiteral();
105-
QgsNetworkContentFetcherTask *mFetchingTask;
105+
QgsNetworkContentFetcherTask *mFetchingTask = nullptr;
106106
ContentStatus mStatus;
107107
QNetworkReply::NetworkError mError = QNetworkReply::NoError;
108108

@@ -145,7 +145,7 @@ class CORE_EXPORT QgsNetworkContentFetcherRegistry : public QObject
145145
* \param fetchingMode defines if the download will start immediately or shall be manually triggered
146146
* \note If the download starts immediately, it will not redownload any already fetched or currently fetching file.
147147
*/
148-
const QgsFetchedContent *fetch( const QUrl &url, const FetchingMode &fetchingMode = DownloadLater );
148+
const QgsFetchedContent *fetch( const QUrl &url, const FetchingMode fetchingMode = DownloadLater );
149149

150150
#ifndef SIP_RUN
151151

0 commit comments

Comments
 (0)