Mercurial > hg > svcore
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 |