Mercurial > hg > svcore
comparison data/fileio/FileSource.cpp @ 384:6f6ab834449d spectrogram-cache-rejig
* Merge from trunk
author | Chris Cannam |
---|---|
date | Wed, 27 Feb 2008 11:59:42 +0000 |
parents | a6fab10ff9e6 |
children |
comparison
equal
deleted
inserted
replaced
337:a6fab10ff9e6 | 384:6f6ab834449d |
---|---|
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(); |
216 if (m_localFilename == "") { | |
217 // QUrl may have mishandled the scheme (e.g. in a DOS path) | |
218 m_localFilename = m_url.toString(); | |
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 | |
204 m_ok = true; | 250 m_ok = true; |
205 if (!QFileInfo(m_localFilename).exists()) { | 251 if (!QFileInfo(m_localFilename).exists()) { |
206 m_lastStatus = 404; | 252 m_lastStatus = 404; |
207 } else { | 253 } else { |
208 m_lastStatus = 200; | 254 m_lastStatus = 200; |
209 } | 255 } |
210 m_done = true; | 256 m_done = true; |
211 return; | 257 return; |
212 } | 258 } |
213 | 259 |
214 if (createCacheFile()) { | |
215 #ifdef DEBUG_FILE_SOURCE | |
216 std::cerr << "FileSource::init: Already have this one" << std::endl; | |
217 #endif | |
218 m_ok = true; | |
219 if (!QFileInfo(m_localFilename).exists()) { | |
220 m_lastStatus = 404; | |
221 } else { | |
222 m_lastStatus = 200; | |
223 } | |
224 m_done = true; | |
225 return; | |
226 } | |
227 | |
228 if (m_localFilename == "") return; | 260 if (m_localFilename == "") return; |
229 m_localFile = new QFile(m_localFilename); | 261 m_localFile = new QFile(m_localFilename); |
230 m_localFile->open(QFile::WriteOnly); | 262 m_localFile->open(QFile::WriteOnly); |
231 | 263 |
232 QString scheme = m_url.scheme().toLower(); | 264 QString scheme = m_url.scheme().toLower(); |
236 << m_url.toString().toStdString() << "\", retrieving" << std::endl; | 268 << m_url.toString().toStdString() << "\", retrieving" << std::endl; |
237 #endif | 269 #endif |
238 | 270 |
239 if (scheme == "http") { | 271 if (scheme == "http") { |
240 initHttp(); | 272 initHttp(); |
273 std::cerr << "FileSource: initHttp succeeded" << std::endl; | |
241 } else if (scheme == "ftp") { | 274 } else if (scheme == "ftp") { |
242 initFtp(); | 275 initFtp(); |
243 } else { | 276 } else { |
244 m_remote = false; | 277 m_remote = false; |
245 m_ok = false; | 278 m_ok = false; |
269 | 302 |
270 m_remoteLocalMap[m_url] = m_localFilename; | 303 m_remoteLocalMap[m_url] = m_localFilename; |
271 m_refCountMap[m_url]++; | 304 m_refCountMap[m_url]++; |
272 m_refCounted = true; | 305 m_refCounted = true; |
273 | 306 |
274 if (showProgress) { | 307 switch (m_progressType) { |
275 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); | |
276 m_progressDialog->hide(); | 315 m_progressDialog->hide(); |
277 connect(&m_progressShowTimer, SIGNAL(timeout()), | 316 connect(&m_progressShowTimer, SIGNAL(timeout()), |
278 this, SLOT(showProgressDialog())); | 317 this, SLOT(showProgressDialog())); |
279 connect(m_progressDialog, SIGNAL(canceled()), this, SLOT(cancelled())); | 318 connect(m_progressDialog, SIGNAL(canceled()), |
319 this, SLOT(cancelled())); | |
280 m_progressShowTimer.setSingleShot(true); | 320 m_progressShowTimer.setSingleShot(true); |
281 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; | |
282 } | 329 } |
283 } | 330 } |
284 } | 331 } |
285 | 332 |
286 void | 333 void |
394 f->abort(); | 441 f->abort(); |
395 f->deleteLater(); | 442 f->deleteLater(); |
396 } | 443 } |
397 delete m_progressDialog; | 444 delete m_progressDialog; |
398 m_progressDialog = 0; | 445 m_progressDialog = 0; |
446 delete m_progressPrinter; | |
447 m_progressPrinter = 0; | |
399 delete m_localFile; // does not actually delete the file | 448 delete m_localFile; // does not actually delete the file |
400 m_localFile = 0; | 449 m_localFile = 0; |
401 } | 450 } |
402 | 451 |
403 bool | 452 bool |
404 FileSource::isRemote(QString fileOrUrl) | 453 FileSource::isRemote(QString fileOrUrl) |
405 { | 454 { |
455 // Note that a "scheme" with length 1 is probably a DOS drive letter | |
406 QString scheme = QUrl(fileOrUrl).scheme().toLower(); | 456 QString scheme = QUrl(fileOrUrl).scheme().toLower(); |
407 return (scheme == "http" || scheme == "ftp"); | 457 if (scheme == "" || scheme == "file" || scheme.length() == 1) return false; |
458 return true; | |
408 } | 459 } |
409 | 460 |
410 bool | 461 bool |
411 FileSource::canHandleScheme(QUrl url) | 462 FileSource::canHandleScheme(QUrl url) |
412 { | 463 { |
464 // Note that a "scheme" with length 1 is probably a DOS drive letter | |
413 QString scheme = url.scheme().toLower(); | 465 QString scheme = url.scheme().toLower(); |
414 return (scheme == "http" || scheme == "ftp" || | 466 return (scheme == "http" || scheme == "ftp" || |
415 scheme == "file" || scheme == ""); | 467 scheme == "file" || scheme == "" || scheme.length() == 1); |
416 } | 468 } |
417 | 469 |
418 bool | 470 bool |
419 FileSource::isAvailable() | 471 FileSource::isAvailable() |
420 { | 472 { |
440 | 492 |
441 void | 493 void |
442 FileSource::waitForData() | 494 FileSource::waitForData() |
443 { | 495 { |
444 while (m_ok && !m_done) { | 496 while (m_ok && !m_done) { |
497 // std::cerr << "FileSource::waitForData: calling QApplication::processEvents" << std::endl; | |
445 QApplication::processEvents(); | 498 QApplication::processEvents(); |
446 } | 499 } |
447 } | 500 } |
448 | 501 |
449 void | 502 void |
793 m_localFilename = filepath; | 846 m_localFilename = filepath; |
794 | 847 |
795 return false; | 848 return false; |
796 } | 849 } |
797 | 850 |
798 FileSourceProgressPrinter::FileSourceProgressPrinter() : | |
799 m_lastProgress(0) | |
800 { | |
801 } | |
802 | |
803 FileSourceProgressPrinter::~FileSourceProgressPrinter() | |
804 { | |
805 if (m_lastProgress > 0 && m_lastProgress != 100) { | |
806 std::cerr << "\r\n"; | |
807 } | |
808 } | |
809 | |
810 void | |
811 FileSourceProgressPrinter::progress(int progress) | |
812 { | |
813 if (progress == m_lastProgress) return; | |
814 if (progress == 100) std::cerr << "\r\n"; | |
815 else std::cerr << "\r" << progress << "%"; | |
816 m_lastProgress = progress; | |
817 } | |
818 |