Mercurial > hg > svcore
comparison data/fileio/FileSource.cpp @ 706:579b2da21e7a
Make FileSource capable of handling resource files.
Without this, we failed to open the silent resource file used as a placeholder
in templates and thus failed to replace it with the proper file after loading
the template -- the consequence was that (although the right audio file ended
up being shown as the main model) any derived models were not regenerated
author | Chris Cannam |
---|---|
date | Fri, 07 Oct 2011 17:04:09 +0100 |
parents | 1424aa29ae95 |
children | 3b2409646cc0 |
comparison
equal
deleted
inserted
replaced
705:66de0ad10bb3 | 706:579b2da21e7a |
---|---|
75 m_http(0), | 75 m_http(0), |
76 m_localFile(0), | 76 m_localFile(0), |
77 m_preferredContentType(preferredContentType), | 77 m_preferredContentType(preferredContentType), |
78 m_ok(false), | 78 m_ok(false), |
79 m_lastStatus(0), | 79 m_lastStatus(0), |
80 m_resource(fileOrUrl.startsWith(':')), | |
80 m_remote(isRemote(fileOrUrl)), | 81 m_remote(isRemote(fileOrUrl)), |
81 m_done(false), | 82 m_done(false), |
82 m_leaveLocalFile(false), | 83 m_leaveLocalFile(false), |
83 m_reporter(reporter), | 84 m_reporter(reporter), |
84 m_refCounted(false) | 85 m_refCounted(false) |
85 { | 86 { |
87 if (m_resource) { // qrc file | |
88 m_url = QUrl("qrc" + fileOrUrl); | |
89 } | |
90 | |
86 if (m_url.toString() == "") { | 91 if (m_url.toString() == "") { |
87 m_url = QUrl(fileOrUrl, QUrl::TolerantMode); | 92 m_url = QUrl(fileOrUrl, QUrl::TolerantMode); |
88 } | 93 } |
89 | 94 |
90 #ifdef DEBUG_FILE_SOURCE | 95 #ifdef DEBUG_FILE_SOURCE |
91 SVDEBUG << "FileSource::FileSource(" << fileOrUrl << "): url <" << m_url.toString() << ">" << endl; | 96 std::cerr << "FileSource::FileSource(" << fileOrUrl << "): url <" << m_url.toString() << ">" << std::endl; |
92 incCount(m_url.toString()); | 97 incCount(m_url.toString()); |
93 #endif | 98 #endif |
94 | 99 |
95 if (!canHandleScheme(m_url)) { | 100 if (!canHandleScheme(m_url)) { |
96 SVDEBUG << "FileSource::FileSource: ERROR: Unsupported scheme in URL \"" << m_url.toString() << "\"" << endl; | 101 SVDEBUG << "FileSource::FileSource: ERROR: Unsupported scheme in URL \"" << m_url.toString() << "\"" << endl; |
101 init(); | 106 init(); |
102 | 107 |
103 if (!isRemote() && | 108 if (!isRemote() && |
104 !isAvailable()) { | 109 !isAvailable()) { |
105 #ifdef DEBUG_FILE_SOURCE | 110 #ifdef DEBUG_FILE_SOURCE |
106 std::cerr << "FileSource::FileSource: Failed to open local file with URL \"" << m_url.toString() << "; trying again assuming filename was encoded" << std::endl; | 111 std::cerr << "FileSource::FileSource: Failed to open local file with URL \"" << m_url.toString() << "\"; trying again assuming filename was encoded" << std::endl; |
107 #endif | 112 #endif |
108 m_url = QUrl::fromEncoded(fileOrUrl.toAscii()); | 113 m_url = QUrl::fromEncoded(fileOrUrl.toAscii()); |
109 init(); | 114 init(); |
110 } | 115 } |
111 | 116 |
157 m_ftp(0), | 162 m_ftp(0), |
158 m_http(0), | 163 m_http(0), |
159 m_localFile(0), | 164 m_localFile(0), |
160 m_ok(false), | 165 m_ok(false), |
161 m_lastStatus(0), | 166 m_lastStatus(0), |
167 m_resource(false), | |
162 m_remote(isRemote(url.toString())), | 168 m_remote(isRemote(url.toString())), |
163 m_done(false), | 169 m_done(false), |
164 m_leaveLocalFile(false), | 170 m_leaveLocalFile(false), |
165 m_reporter(reporter), | 171 m_reporter(reporter), |
166 m_refCounted(false) | 172 m_refCounted(false) |
189 m_ftp(0), | 195 m_ftp(0), |
190 m_http(0), | 196 m_http(0), |
191 m_localFile(0), | 197 m_localFile(0), |
192 m_ok(rf.m_ok), | 198 m_ok(rf.m_ok), |
193 m_lastStatus(rf.m_lastStatus), | 199 m_lastStatus(rf.m_lastStatus), |
200 m_resource(rf.m_resource), | |
194 m_remote(rf.m_remote), | 201 m_remote(rf.m_remote), |
195 m_done(false), | 202 m_done(false), |
196 m_leaveLocalFile(false), | 203 m_leaveLocalFile(false), |
197 m_reporter(rf.m_reporter), | 204 m_reporter(rf.m_reporter), |
198 m_refCounted(false) | 205 m_refCounted(false) |
253 } | 260 } |
254 | 261 |
255 void | 262 void |
256 FileSource::init() | 263 FileSource::init() |
257 { | 264 { |
258 if (!isRemote()) { | 265 if (isResource()) { |
259 #ifdef DEBUG_FILE_SOURCE | 266 #ifdef DEBUG_FILE_SOURCE |
260 SVDEBUG << "FileSource::init: Not a remote URL" << endl; | 267 std::cerr << "FileSource::init: Is a resource" << std::endl; |
268 #endif | |
269 QString resourceFile = m_url.toString(); | |
270 resourceFile.replace(QRegExp("^qrc:"), ":"); | |
271 | |
272 if (!QFileInfo(resourceFile).exists()) { | |
273 #ifdef DEBUG_FILE_SOURCE | |
274 std::cerr << "FileSource::init: Resource file of this name does not exist, switching to non-resource URL" << std::endl; | |
275 #endif | |
276 m_url = resourceFile; | |
277 m_resource = false; | |
278 } | |
279 } | |
280 | |
281 if (!isRemote() && !isResource()) { | |
282 #ifdef DEBUG_FILE_SOURCE | |
283 std::cerr << "FileSource::init: Not a remote URL" << std::endl; | |
261 #endif | 284 #endif |
262 bool literal = false; | 285 bool literal = false; |
263 m_localFilename = m_url.toLocalFile(); | 286 m_localFilename = m_url.toLocalFile(); |
264 if (m_localFilename == "") { | 287 if (m_localFilename == "") { |
265 // QUrl may have mishandled the scheme (e.g. in a DOS path) | 288 // QUrl may have mishandled the scheme (e.g. in a DOS path) |
267 literal = true; | 290 literal = true; |
268 } | 291 } |
269 m_localFilename = QFileInfo(m_localFilename).absoluteFilePath(); | 292 m_localFilename = QFileInfo(m_localFilename).absoluteFilePath(); |
270 | 293 |
271 #ifdef DEBUG_FILE_SOURCE | 294 #ifdef DEBUG_FILE_SOURCE |
272 SVDEBUG << "FileSource::init: URL translates to local filename \"" | 295 std::cerr << "FileSource::init: URL translates to local filename \"" |
273 << m_localFilename << "\" (with literal=" << literal << ")" << endl; | 296 << m_localFilename << "\" (with literal=" << literal << ")" |
297 << std::endl; | |
274 #endif | 298 #endif |
275 m_ok = true; | 299 m_ok = true; |
276 m_lastStatus = 200; | 300 m_lastStatus = 200; |
277 | 301 |
278 if (!QFileInfo(m_localFilename).exists()) { | 302 if (!QFileInfo(m_localFilename).exists()) { |
279 if (literal) { | 303 if (literal) { |
280 m_lastStatus = 404; | 304 m_lastStatus = 404; |
281 } else { | 305 } else { |
282 #ifdef DEBUG_FILE_SOURCE | 306 #ifdef DEBUG_FILE_SOURCE |
283 SVDEBUG << "FileSource::init: Local file of this name does not exist, trying URL as a literal filename" << endl; | 307 std::cerr << "FileSource::init: Local file of this name does not exist, trying URL as a literal filename" << std::endl; |
284 #endif | 308 #endif |
285 // Again, QUrl may have been mistreating us -- | 309 // Again, QUrl may have been mistreating us -- |
286 // e.g. dropping a part that looks like query data | 310 // e.g. dropping a part that looks like query data |
287 m_localFilename = m_url.toString(); | 311 m_localFilename = m_url.toString(); |
288 literal = true; | 312 literal = true; |
296 return; | 320 return; |
297 } | 321 } |
298 | 322 |
299 if (createCacheFile()) { | 323 if (createCacheFile()) { |
300 #ifdef DEBUG_FILE_SOURCE | 324 #ifdef DEBUG_FILE_SOURCE |
301 SVDEBUG << "FileSource::init: Already have this one" << endl; | 325 std::cerr << "FileSource::init: Already have this one" << std::endl; |
302 #endif | 326 #endif |
303 m_ok = true; | 327 m_ok = true; |
304 if (!QFileInfo(m_localFilename).exists()) { | 328 if (!QFileInfo(m_localFilename).exists()) { |
305 m_lastStatus = 404; | 329 m_lastStatus = 404; |
306 } else { | 330 } else { |
309 m_done = true; | 333 m_done = true; |
310 return; | 334 return; |
311 } | 335 } |
312 | 336 |
313 if (m_localFilename == "") return; | 337 if (m_localFilename == "") return; |
338 | |
314 m_localFile = new QFile(m_localFilename); | 339 m_localFile = new QFile(m_localFilename); |
315 m_localFile->open(QFile::WriteOnly); | 340 m_localFile->open(QFile::WriteOnly); |
316 | 341 |
317 QString scheme = m_url.scheme().toLower(); | 342 if (isResource()) { |
318 | 343 |
319 #ifdef DEBUG_FILE_SOURCE | 344 // Absent resource file case was dealt with at the top -- this |
320 SVDEBUG << "FileSource::init: Don't have local copy of \"" | 345 // is the successful case |
321 << m_url.toString() << "\", retrieving" << endl; | 346 |
322 #endif | 347 QString resourceFileName = m_url.toString(); |
323 | 348 resourceFileName.replace(QRegExp("^qrc:"), ":"); |
324 if (scheme == "http") { | 349 QFile resourceFile(resourceFileName); |
325 initHttp(); | 350 resourceFile.open(QFile::ReadOnly); |
326 #ifdef DEBUG_FILE_SOURCE | 351 QByteArray ba(resourceFile.readAll()); |
327 std::cerr << "FileSource: initHttp succeeded" << std::endl; | 352 |
328 #endif | 353 #ifdef DEBUG_FILE_SOURCE |
329 } else if (scheme == "ftp") { | 354 std::cerr << "Copying " << ba.size() << " bytes from resource file to cache file" << std::endl; |
330 initFtp(); | 355 #endif |
356 | |
357 qint64 written = m_localFile->write(ba); | |
358 m_localFile->close(); | |
359 delete m_localFile; | |
360 m_localFile = 0; | |
361 | |
362 if (written != ba.size()) { | |
363 #ifdef DEBUG_FILE_SOURCE | |
364 std::cerr << "Copy failed (wrote " << written << " bytes)" << std::endl; | |
365 #endif | |
366 m_ok = false; | |
367 return; | |
368 } else { | |
369 m_ok = true; | |
370 m_lastStatus = 200; | |
371 m_done = true; | |
372 } | |
373 | |
331 } else { | 374 } else { |
332 m_remote = false; | 375 |
333 m_ok = false; | 376 QString scheme = m_url.scheme().toLower(); |
377 | |
378 #ifdef DEBUG_FILE_SOURCE | |
379 std::cerr << "FileSource::init: Don't have local copy of \"" | |
380 << m_url.toString() << "\", retrieving" << std::endl; | |
381 #endif | |
382 | |
383 if (scheme == "http") { | |
384 initHttp(); | |
385 #ifdef DEBUG_FILE_SOURCE | |
386 std::cerr << "FileSource: initHttp succeeded" << std::endl; | |
387 #endif | |
388 } else if (scheme == "ftp") { | |
389 initFtp(); | |
390 } else { | |
391 m_remote = false; | |
392 m_ok = false; | |
393 } | |
334 } | 394 } |
335 | 395 |
336 if (m_ok) { | 396 if (m_ok) { |
337 | 397 |
338 QMutexLocker locker(&m_mapMutex); | 398 QMutexLocker locker(&m_mapMutex); |
341 // someone else has been doing the same thing at the same time, | 401 // someone else has been doing the same thing at the same time, |
342 // but has got there first | 402 // but has got there first |
343 cleanup(); | 403 cleanup(); |
344 m_refCountMap[m_url]++; | 404 m_refCountMap[m_url]++; |
345 #ifdef DEBUG_FILE_SOURCE | 405 #ifdef DEBUG_FILE_SOURCE |
346 SVDEBUG << "FileSource::init: Another FileSource has got there first, abandoning our download and using theirs" << endl; | 406 std::cerr << "FileSource::init: Another FileSource has got there first, abandoning our download and using theirs" << std::endl; |
347 #endif | 407 #endif |
348 m_localFilename = m_remoteLocalMap[m_url]; | 408 m_localFilename = m_remoteLocalMap[m_url]; |
349 m_refCounted = true; | 409 m_refCounted = true; |
350 m_ok = true; | 410 m_ok = true; |
351 if (!QFileInfo(m_localFilename).exists()) { | 411 if (!QFileInfo(m_localFilename).exists()) { |
357 | 417 |
358 m_remoteLocalMap[m_url] = m_localFilename; | 418 m_remoteLocalMap[m_url] = m_localFilename; |
359 m_refCountMap[m_url]++; | 419 m_refCountMap[m_url]++; |
360 m_refCounted = true; | 420 m_refCounted = true; |
361 | 421 |
362 if (m_reporter) { | 422 if (m_reporter && !m_done) { |
363 m_reporter->setMessage | 423 m_reporter->setMessage |
364 (tr("Downloading %1...").arg(m_url.toString())); | 424 (tr("Downloading %1...").arg(m_url.toString())); |
365 connect(m_reporter, SIGNAL(cancelled()), this, SLOT(cancelled())); | 425 connect(m_reporter, SIGNAL(cancelled()), this, SLOT(cancelled())); |
366 connect(this, SIGNAL(progress(int)), | 426 connect(this, SIGNAL(progress(int)), |
367 m_reporter, SLOT(setProgress(int))); | 427 m_reporter, SLOT(setProgress(int))); |
515 FileSource::canHandleScheme(QUrl url) | 575 FileSource::canHandleScheme(QUrl url) |
516 { | 576 { |
517 // Note that a "scheme" with length 1 is probably a DOS drive letter | 577 // Note that a "scheme" with length 1 is probably a DOS drive letter |
518 QString scheme = url.scheme().toLower(); | 578 QString scheme = url.scheme().toLower(); |
519 return (scheme == "http" || scheme == "ftp" || | 579 return (scheme == "http" || scheme == "ftp" || |
520 scheme == "file" || scheme == "" || scheme.length() == 1); | 580 scheme == "file" || scheme == "qrc" || |
581 scheme == "" || scheme.length() == 1); | |
521 } | 582 } |
522 | 583 |
523 bool | 584 bool |
524 FileSource::isAvailable() | 585 FileSource::isAvailable() |
525 { | 586 { |
567 | 628 |
568 bool | 629 bool |
569 FileSource::isDone() const | 630 FileSource::isDone() const |
570 { | 631 { |
571 return m_done; | 632 return m_done; |
633 } | |
634 | |
635 bool | |
636 FileSource::isResource() const | |
637 { | |
638 return m_resource; | |
572 } | 639 } |
573 | 640 |
574 bool | 641 bool |
575 FileSource::isRemote() const | 642 FileSource::isRemote() const |
576 { | 643 { |
879 } | 946 } |
880 | 947 |
881 QString filepath(dir.filePath(filename)); | 948 QString filepath(dir.filePath(filename)); |
882 | 949 |
883 #ifdef DEBUG_FILE_SOURCE | 950 #ifdef DEBUG_FILE_SOURCE |
884 SVDEBUG << "FileSource::createCacheFile: URL is \"" << m_url.toString() << "\", dir is \"" << dir.path() << "\", base \"" << base << "\", extension \"" << extension << "\", filebase \"" << filename << "\", filename \"" << filepath << "\"" << endl; | 951 std::cerr << "FileSource::createCacheFile: URL is \"" << m_url.toString() << "\", dir is \"" << dir.path() << "\", base \"" << base << "\", extension \"" << extension << "\", filebase \"" << filename << "\", filename \"" << filepath << "\"" << std::endl; |
885 #endif | 952 #endif |
886 | 953 |
887 QMutexLocker fcLocker(&m_fileCreationMutex); | 954 QMutexLocker fcLocker(&m_fileCreationMutex); |
888 | 955 |
889 ++m_count; | 956 ++m_count; |
916 return ""; | 983 return ""; |
917 } | 984 } |
918 } | 985 } |
919 | 986 |
920 #ifdef DEBUG_FILE_SOURCE | 987 #ifdef DEBUG_FILE_SOURCE |
921 SVDEBUG << "FileSource::createCacheFile: url " | 988 std::cerr << "FileSource::createCacheFile: url " |
922 << m_url.toString() << " -> local filename " | 989 << m_url.toString() << " -> local filename " |
923 << filepath << endl; | 990 << filepath << std::endl; |
924 #endif | 991 #endif |
925 | 992 |
926 m_localFilename = filepath; | 993 m_localFilename = filepath; |
927 | 994 |
928 return false; | 995 return false; |