comparison data/fileio/FileSource.cpp @ 383:94fc0591ea43 1.2-stable

* merge from trunk (1.2 ended up being tracked from trunk, but we may want this branch for fixes later)
author Chris Cannam
date Wed, 27 Feb 2008 10:32:45 +0000
parents 4175a4930186
children
comparison
equal deleted inserted replaced
349:f39d33b0b265 383:94fc0591ea43
12 License, or (at your option) any later version. See the file 12 License, or (at your option) any later version. See the file
13 COPYING included with this distribution for more information. 13 COPYING included with this distribution for more information.
14 */ 14 */
15 15
16 #include "FileSource.h" 16 #include "FileSource.h"
17 #include "ProgressPrinter.h"
18
17 #include "base/TempDirectory.h" 19 #include "base/TempDirectory.h"
18 #include "base/Exceptions.h" 20 #include "base/Exceptions.h"
19 21
20 #include <QHttp> 22 #include <QHttp>
21 #include <QFtp> 23 #include <QFtp>
25 #include <QProgressDialog> 27 #include <QProgressDialog>
26 #include <QHttpResponseHeader> 28 #include <QHttpResponseHeader>
27 29
28 #include <iostream> 30 #include <iostream>
29 31
30 //#define DEBUG_FILE_SOURCE 1 32 #define DEBUG_FILE_SOURCE 1
31 33
32 int 34 int
33 FileSource::m_count = 0; 35 FileSource::m_count = 0;
34 36
35 QMutex 37 QMutex
42 FileSource::m_remoteLocalMap; 44 FileSource::m_remoteLocalMap;
43 45
44 QMutex 46 QMutex
45 FileSource::m_mapMutex; 47 FileSource::m_mapMutex;
46 48
47 FileSource::FileSource(QString fileOrUrl, bool showProgress) : 49 FileSource::FileSource(QString fileOrUrl, ShowProgressType progressType) :
48 m_url(fileOrUrl), 50 m_url(fileOrUrl),
49 m_ftp(0), 51 m_ftp(0),
50 m_http(0), 52 m_http(0),
51 m_localFile(0), 53 m_localFile(0),
52 m_ok(false), 54 m_ok(false),
53 m_lastStatus(0), 55 m_lastStatus(0),
54 m_remote(isRemote(fileOrUrl)), 56 m_remote(isRemote(fileOrUrl)),
55 m_done(false), 57 m_done(false),
56 m_leaveLocalFile(false), 58 m_leaveLocalFile(false),
59 m_progressType(progressType),
60 m_progressPrinter(0),
57 m_progressDialog(0), 61 m_progressDialog(0),
58 m_progressShowTimer(this), 62 m_progressShowTimer(this),
59 m_refCounted(false) 63 m_refCounted(false)
60 { 64 {
61 #ifdef DEBUG_FILE_SOURCE 65 #ifdef DEBUG_FILE_SOURCE
66 std::cerr << "FileSource::FileSource: ERROR: Unsupported scheme in URL \"" << m_url.toString().toStdString() << "\"" << std::endl; 70 std::cerr << "FileSource::FileSource: ERROR: Unsupported scheme in URL \"" << m_url.toString().toStdString() << "\"" << std::endl;
67 m_errorString = tr("Unsupported scheme in URL"); 71 m_errorString = tr("Unsupported scheme in URL");
68 return; 72 return;
69 } 73 }
70 74
71 init(showProgress); 75 init();
72 76
73 if (isRemote() && 77 if (isRemote() &&
74 (fileOrUrl.contains('%') || 78 (fileOrUrl.contains('%') ||
75 fileOrUrl.contains("--"))) { // for IDNA 79 fileOrUrl.contains("--"))) { // for IDNA
76 80
97 m_url.setEncodedUrl(fileOrUrl.toAscii()); 101 m_url.setEncodedUrl(fileOrUrl.toAscii());
98 102
99 m_ok = false; 103 m_ok = false;
100 m_done = false; 104 m_done = false;
101 m_lastStatus = 0; 105 m_lastStatus = 0;
102 init(showProgress); 106 init();
103 } 107 }
104 } 108 }
105 109
106 if (!isRemote()) { 110 if (!isRemote()) {
107 emit statusAvailable(); 111 emit statusAvailable();
108 emit ready(); 112 emit ready();
109 } 113 }
110 } 114 }
111 115
112 FileSource::FileSource(QUrl url, bool showProgress) : 116 FileSource::FileSource(QUrl url, ShowProgressType progressType) :
113 m_url(url), 117 m_url(url),
114 m_ftp(0), 118 m_ftp(0),
115 m_http(0), 119 m_http(0),
116 m_localFile(0), 120 m_localFile(0),
117 m_ok(false), 121 m_ok(false),
118 m_lastStatus(0), 122 m_lastStatus(0),
119 m_remote(isRemote(url.toString())), 123 m_remote(isRemote(url.toString())),
120 m_done(false), 124 m_done(false),
121 m_leaveLocalFile(false), 125 m_leaveLocalFile(false),
126 m_progressType(progressType),
127 m_progressPrinter(0),
122 m_progressDialog(0), 128 m_progressDialog(0),
123 m_progressShowTimer(this), 129 m_progressShowTimer(this),
124 m_refCounted(false) 130 m_refCounted(false)
125 { 131 {
126 #ifdef DEBUG_FILE_SOURCE 132 #ifdef DEBUG_FILE_SOURCE
131 std::cerr << "FileSource::FileSource: ERROR: Unsupported scheme in URL \"" << m_url.toString().toStdString() << "\"" << std::endl; 137 std::cerr << "FileSource::FileSource: ERROR: Unsupported scheme in URL \"" << m_url.toString().toStdString() << "\"" << std::endl;
132 m_errorString = tr("Unsupported scheme in URL"); 138 m_errorString = tr("Unsupported scheme in URL");
133 return; 139 return;
134 } 140 }
135 141
136 init(showProgress); 142 init();
137 } 143 }
138 144
139 FileSource::FileSource(const FileSource &rf) : 145 FileSource::FileSource(const FileSource &rf) :
140 QObject(), 146 QObject(),
141 m_url(rf.m_url), 147 m_url(rf.m_url),
145 m_ok(rf.m_ok), 151 m_ok(rf.m_ok),
146 m_lastStatus(rf.m_lastStatus), 152 m_lastStatus(rf.m_lastStatus),
147 m_remote(rf.m_remote), 153 m_remote(rf.m_remote),
148 m_done(false), 154 m_done(false),
149 m_leaveLocalFile(false), 155 m_leaveLocalFile(false),
156 m_progressType(rf.m_progressType),
157 m_progressPrinter(0),
150 m_progressDialog(0), 158 m_progressDialog(0),
151 m_progressShowTimer(0), 159 m_progressShowTimer(0),
152 m_refCounted(false) 160 m_refCounted(false)
153 { 161 {
154 #ifdef DEBUG_FILE_SOURCE 162 #ifdef DEBUG_FILE_SOURCE
195 203
196 if (isRemote() && !m_leaveLocalFile) deleteCacheFile(); 204 if (isRemote() && !m_leaveLocalFile) deleteCacheFile();
197 } 205 }
198 206
199 void 207 void
200 FileSource::init(bool showProgress) 208 FileSource::init()
201 { 209 {
202 if (!isRemote()) { 210 if (!isRemote()) {
211 #ifdef DEBUG_FILE_SOURCE
212 std::cerr << "FileSource::init: Not a remote URL" << std::endl;
213 #endif
214 bool literal = false;
203 m_localFilename = m_url.toLocalFile(); 215 m_localFilename = m_url.toLocalFile();
204 if (m_localFilename == "") { 216 if (m_localFilename == "") {
205 // QUrl may have mishandled the scheme (e.g. in a DOS path) 217 // QUrl may have mishandled the scheme (e.g. in a DOS path)
206 m_localFilename = m_url.toString(); 218 m_localFilename = m_url.toString();
207 } 219 literal = true;
220 }
221 #ifdef DEBUG_FILE_SOURCE
222 std::cerr << "FileSource::init: URL translates to local filename \""
223 << m_localFilename.toStdString() << "\"" << std::endl;
224 #endif
225 m_ok = true;
226 m_lastStatus = 200;
227
228 if (!QFileInfo(m_localFilename).exists()) {
229 if (literal) {
230 m_lastStatus = 404;
231 } else {
232 // Again, QUrl may have been mistreating us --
233 // e.g. dropping a part that looks like query data
234 m_localFilename = m_url.toString();
235 literal = true;
236 if (!QFileInfo(m_localFilename).exists()) {
237 m_lastStatus = 404;
238 }
239 }
240 }
241
242 m_done = true;
243 return;
244 }
245
246 if (createCacheFile()) {
247 #ifdef DEBUG_FILE_SOURCE
248 std::cerr << "FileSource::init: Already have this one" << std::endl;
249 #endif
208 m_ok = true; 250 m_ok = true;
209 if (!QFileInfo(m_localFilename).exists()) { 251 if (!QFileInfo(m_localFilename).exists()) {
210 m_lastStatus = 404; 252 m_lastStatus = 404;
211 } else { 253 } else {
212 m_lastStatus = 200; 254 m_lastStatus = 200;
213 } 255 }
214 m_done = true; 256 m_done = true;
215 return; 257 return;
216 } 258 }
217 259
218 if (createCacheFile()) {
219 #ifdef DEBUG_FILE_SOURCE
220 std::cerr << "FileSource::init: Already have this one" << std::endl;
221 #endif
222 m_ok = true;
223 if (!QFileInfo(m_localFilename).exists()) {
224 m_lastStatus = 404;
225 } else {
226 m_lastStatus = 200;
227 }
228 m_done = true;
229 return;
230 }
231
232 if (m_localFilename == "") return; 260 if (m_localFilename == "") return;
233 m_localFile = new QFile(m_localFilename); 261 m_localFile = new QFile(m_localFilename);
234 m_localFile->open(QFile::WriteOnly); 262 m_localFile->open(QFile::WriteOnly);
235 263
236 QString scheme = m_url.scheme().toLower(); 264 QString scheme = m_url.scheme().toLower();
240 << m_url.toString().toStdString() << "\", retrieving" << std::endl; 268 << m_url.toString().toStdString() << "\", retrieving" << std::endl;
241 #endif 269 #endif
242 270
243 if (scheme == "http") { 271 if (scheme == "http") {
244 initHttp(); 272 initHttp();
273 std::cerr << "FileSource: initHttp succeeded" << std::endl;
245 } else if (scheme == "ftp") { 274 } else if (scheme == "ftp") {
246 initFtp(); 275 initFtp();
247 } else { 276 } else {
248 m_remote = false; 277 m_remote = false;
249 m_ok = false; 278 m_ok = false;
273 302
274 m_remoteLocalMap[m_url] = m_localFilename; 303 m_remoteLocalMap[m_url] = m_localFilename;
275 m_refCountMap[m_url]++; 304 m_refCountMap[m_url]++;
276 m_refCounted = true; 305 m_refCounted = true;
277 306
278 if (showProgress) { 307 switch (m_progressType) {
279 m_progressDialog = new QProgressDialog(tr("Downloading %1...").arg(m_url.toString()), tr("Cancel"), 0, 100); 308
309 case ProgressNone: break;
310
311 case ProgressDialog:
312 m_progressDialog = new QProgressDialog
313 (tr("Downloading %1...").arg(m_url.toString()),
314 tr("Cancel"), 0, 100);
280 m_progressDialog->hide(); 315 m_progressDialog->hide();
281 connect(&m_progressShowTimer, SIGNAL(timeout()), 316 connect(&m_progressShowTimer, SIGNAL(timeout()),
282 this, SLOT(showProgressDialog())); 317 this, SLOT(showProgressDialog()));
283 connect(m_progressDialog, SIGNAL(canceled()), this, SLOT(cancelled())); 318 connect(m_progressDialog, SIGNAL(canceled()),
319 this, SLOT(cancelled()));
284 m_progressShowTimer.setSingleShot(true); 320 m_progressShowTimer.setSingleShot(true);
285 m_progressShowTimer.start(2000); 321 m_progressShowTimer.start(2000);
322 break;
323
324 case ProgressToConsole:
325 m_progressPrinter = new ProgressPrinter(tr("Downloading..."));
326 connect(this, SIGNAL(progress(int)),
327 m_progressPrinter, SLOT(progress(int)));
328 break;
286 } 329 }
287 } 330 }
288 } 331 }
289 332
290 void 333 void
398 f->abort(); 441 f->abort();
399 f->deleteLater(); 442 f->deleteLater();
400 } 443 }
401 delete m_progressDialog; 444 delete m_progressDialog;
402 m_progressDialog = 0; 445 m_progressDialog = 0;
446 delete m_progressPrinter;
447 m_progressPrinter = 0;
403 delete m_localFile; // does not actually delete the file 448 delete m_localFile; // does not actually delete the file
404 m_localFile = 0; 449 m_localFile = 0;
405 } 450 }
406 451
407 bool 452 bool
447 492
448 void 493 void
449 FileSource::waitForData() 494 FileSource::waitForData()
450 { 495 {
451 while (m_ok && !m_done) { 496 while (m_ok && !m_done) {
497 // std::cerr << "FileSource::waitForData: calling QApplication::processEvents" << std::endl;
452 QApplication::processEvents(); 498 QApplication::processEvents();
453 } 499 }
454 } 500 }
455 501
456 void 502 void
800 m_localFilename = filepath; 846 m_localFilename = filepath;
801 847
802 return false; 848 return false;
803 } 849 }
804 850
805 FileSourceProgressPrinter::FileSourceProgressPrinter() :
806 m_lastProgress(0)
807 {
808 }
809
810 FileSourceProgressPrinter::~FileSourceProgressPrinter()
811 {
812 if (m_lastProgress > 0 && m_lastProgress != 100) {
813 std::cerr << "\r\n";
814 }
815 }
816
817 void
818 FileSourceProgressPrinter::progress(int progress)
819 {
820 if (progress == m_lastProgress) return;
821 if (progress == 100) std::cerr << "\r\n";
822 else std::cerr << "\r" << progress << "%";
823 m_lastProgress = progress;
824 }
825