Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgsnetworkcontentfetcherregistry.cpp 3 : : ------------------- 4 : : begin : April, 2018 5 : : copyright : (C) 2018 by Denis Rouzaud 6 : : email : denis@opengis.ch 7 : : 8 : : ***************************************************************************/ 9 : : 10 : : /*************************************************************************** 11 : : * * 12 : : * This program is free software; you can redistribute it and/or modify * 13 : : * it under the terms of the GNU General Public License as published by * 14 : : * the Free Software Foundation; either version 2 of the License, or * 15 : : * (at your option) any later version. * 16 : : * * 17 : : ***************************************************************************/ 18 : : 19 : : #include "qgsnetworkcontentfetcherregistry.h" 20 : : 21 : : #include "qgsapplication.h" 22 : : #include <QUrl> 23 : : 24 : 10 : QgsNetworkContentFetcherRegistry::~QgsNetworkContentFetcherRegistry() 25 : 10 : { 26 : 5 : QMap<QString, QgsFetchedContent *>::const_iterator it = mFileRegistry.constBegin(); 27 : 5 : for ( ; it != mFileRegistry.constEnd(); ++it ) 28 : : { 29 : 0 : delete it.value(); 30 : 0 : } 31 : 5 : mFileRegistry.clear(); 32 : 10 : } 33 : : 34 : 0 : const QgsFetchedContent *QgsNetworkContentFetcherRegistry::fetch( const QString &url, const FetchingMode fetchingMode ) 35 : : { 36 : : 37 : 0 : if ( mFileRegistry.contains( url ) ) 38 : : { 39 : 0 : return mFileRegistry.value( url ); 40 : : } 41 : : 42 : 0 : QgsFetchedContent *content = new QgsFetchedContent( url, nullptr, QgsFetchedContent::NotStarted ); 43 : : 44 : 0 : mFileRegistry.insert( url, content ); 45 : : 46 : 0 : if ( fetchingMode == DownloadImmediately ) 47 : 0 : content->download(); 48 : : 49 : : 50 : 0 : return content; 51 : 0 : } 52 : : 53 : 0 : QFile *QgsNetworkContentFetcherRegistry::localFile( const QString &filePathOrUrl ) 54 : : { 55 : 0 : QFile *file = nullptr; 56 : 0 : QString path = filePathOrUrl; 57 : : 58 : 0 : if ( !QUrl::fromUserInput( filePathOrUrl ).isLocalFile() ) 59 : : { 60 : 0 : if ( mFileRegistry.contains( path ) ) 61 : : { 62 : 0 : const QgsFetchedContent *content = mFileRegistry.value( path ); 63 : 0 : if ( content && content->status() == QgsFetchedContent::Finished && content->file() ) 64 : : { 65 : 0 : file = content->file(); 66 : 0 : } 67 : : else 68 : : { 69 : : // if the file is not downloaded yet or has failed, return nullptr 70 : : } 71 : 0 : } 72 : : else 73 : : { 74 : : // if registry doesn't contain the URL, return nullptr 75 : : } 76 : 0 : } 77 : : else 78 : : { 79 : 0 : file = new QFile( filePathOrUrl ); 80 : : } 81 : 0 : return file; 82 : 0 : } 83 : : 84 : 0 : QString QgsNetworkContentFetcherRegistry::localPath( const QString &filePathOrUrl ) 85 : : { 86 : 0 : QString path = filePathOrUrl; 87 : : 88 : 0 : if ( !QUrl::fromUserInput( filePathOrUrl ).isLocalFile() ) 89 : : { 90 : 0 : if ( mFileRegistry.contains( path ) ) 91 : : { 92 : 0 : const QgsFetchedContent *content = mFileRegistry.value( path ); 93 : 0 : if ( content->status() == QgsFetchedContent::Finished && !content->filePath().isEmpty() ) 94 : : { 95 : 0 : path = content->filePath(); 96 : 0 : } 97 : : else 98 : : { 99 : : // if the file is not downloaded yet or has failed, return empty string 100 : 0 : path = QString(); 101 : : } 102 : 0 : } 103 : : else 104 : : { 105 : : // if registry doesn't contain the URL, keep path unchanged 106 : : } 107 : 0 : } 108 : 0 : return path; 109 : 0 : } 110 : : 111 : : 112 : : 113 : : 114 : 0 : void QgsFetchedContent::download( bool redownload ) 115 : : { 116 : : 117 : 0 : if ( redownload && status() == QgsFetchedContent::Downloading ) 118 : : { 119 : : { 120 : 0 : if ( mFetchingTask ) 121 : 0 : disconnect( mFetchingTask, &QgsNetworkContentFetcherTask::taskCompleted, this, &QgsFetchedContent::taskCompleted ); 122 : : } 123 : 0 : cancel(); 124 : 0 : } 125 : 0 : if ( redownload || 126 : 0 : status() == QgsFetchedContent::NotStarted || 127 : 0 : status() == QgsFetchedContent::Failed ) 128 : : { 129 : 0 : mFetchingTask = new QgsNetworkContentFetcherTask( mUrl ); 130 : : // use taskCompleted which is main thread rather than fetched signal in worker thread 131 : 0 : connect( mFetchingTask, &QgsNetworkContentFetcherTask::taskCompleted, this, &QgsFetchedContent::taskCompleted ); 132 : 0 : QgsApplication::instance()->taskManager()->addTask( mFetchingTask ); 133 : 0 : mStatus = QgsFetchedContent::Downloading; 134 : 0 : } 135 : : 136 : 0 : } 137 : : 138 : 0 : void QgsFetchedContent::cancel() 139 : : { 140 : 0 : if ( mFetchingTask && mFetchingTask->canCancel() ) 141 : : { 142 : 0 : mFetchingTask->cancel(); 143 : 0 : } 144 : 0 : if ( mFile ) 145 : : { 146 : 0 : mFile->deleteLater(); 147 : 0 : mFilePath = QString(); 148 : 0 : } 149 : 0 : } 150 : : 151 : : 152 : 0 : void QgsFetchedContent::taskCompleted() 153 : : { 154 : 0 : if ( !mFetchingTask || !mFetchingTask->reply() ) 155 : : { 156 : : // if no reply, it has been canceled 157 : 0 : mStatus = QgsFetchedContent::Failed; 158 : 0 : mError = QNetworkReply::OperationCanceledError; 159 : 0 : mFilePath = QString(); 160 : 0 : } 161 : : else 162 : : { 163 : 0 : QNetworkReply *reply = mFetchingTask->reply(); 164 : 0 : if ( reply->error() == QNetworkReply::NoError ) 165 : : { 166 : 0 : QTemporaryFile *tf = new QTemporaryFile( QStringLiteral( "XXXXXX" ) ); 167 : 0 : mFile = tf; 168 : 0 : tf->open(); 169 : 0 : mFile->write( reply->readAll() ); 170 : : // Qt docs notes that on some system if fileName is not called before close, file might get deleted 171 : 0 : mFilePath = tf->fileName(); 172 : 0 : tf->close(); 173 : 0 : mStatus = QgsFetchedContent::Finished; 174 : 0 : } 175 : : else 176 : : { 177 : 0 : mStatus = QgsFetchedContent::Failed; 178 : 0 : mError = reply->error(); 179 : 0 : mFilePath = QString(); 180 : : } 181 : : } 182 : : 183 : 0 : emit fetched(); 184 : 0 : }