annotate widgets/InteractiveFileFinder.cpp @ 735:1640a7c753cc tonioni

Short-circuit test for enough space for label -- drastically reduces lag on os/x with qt4
author Chris Cannam
date Thu, 06 Mar 2014 09:43:18 +0000
parents 52e5f6fe31ad
children d0fd7630d32f
rev   line source
Chris@529 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@529 2
Chris@529 3 /*
Chris@529 4 Sonic Visualiser
Chris@529 5 An audio file viewer and annotation editor.
Chris@529 6 Centre for Digital Music, Queen Mary, University of London.
Chris@529 7 This file copyright 2007 QMUL.
Chris@529 8
Chris@529 9 This program is free software; you can redistribute it and/or
Chris@529 10 modify it under the terms of the GNU General Public License as
Chris@529 11 published by the Free Software Foundation; either version 2 of the
Chris@529 12 License, or (at your option) any later version. See the file
Chris@529 13 COPYING included with this distribution for more information.
Chris@529 14 */
Chris@529 15
Chris@529 16 #include "InteractiveFileFinder.h"
Chris@529 17 #include "data/fileio/FileSource.h"
Chris@529 18 #include "data/fileio/AudioFileReaderFactory.h"
Chris@529 19 #include "data/fileio/DataFileReaderFactory.h"
Chris@529 20 #include "rdf/RDFImporter.h"
Chris@529 21 #include "rdf/RDFExporter.h"
Chris@529 22
Chris@529 23 #include <QFileInfo>
Chris@529 24 #include <QMessageBox>
Chris@529 25 #include <QFileDialog>
Chris@529 26 #include <QInputDialog>
Chris@529 27 #include <QImageReader>
Chris@529 28 #include <QSettings>
Chris@529 29
Chris@529 30 #include <iostream>
Chris@529 31
Chris@529 32 InteractiveFileFinder
Chris@529 33 InteractiveFileFinder::m_instance;
Chris@529 34
Chris@529 35 InteractiveFileFinder::InteractiveFileFinder() :
Chris@529 36 m_lastLocatedLocation("")
Chris@529 37 {
Chris@587 38 SVDEBUG << "Registering interactive file finder" << endl;
Chris@529 39 FileFinder::registerFileFinder(this);
Chris@529 40 }
Chris@529 41
Chris@529 42 InteractiveFileFinder::~InteractiveFileFinder()
Chris@529 43 {
Chris@529 44 }
Chris@529 45
Chris@529 46 QString
Chris@529 47 InteractiveFileFinder::getOpenFileName(FileType type, QString fallbackLocation)
Chris@529 48 {
Chris@529 49 QString settingsKey;
Chris@529 50 QString lastPath = fallbackLocation;
Chris@529 51
Chris@529 52 QString title = tr("Select file");
Chris@529 53 QString filter = tr("All files (*.*)");
Chris@529 54
Chris@529 55 switch (type) {
Chris@529 56
Chris@529 57 case SessionFile:
Chris@529 58 settingsKey = "sessionpath";
Chris@529 59 title = tr("Select a session file");
Chris@529 60 filter = tr("Sonic Visualiser session files (*.sv)\nRDF files (%1)\nAll files (*.*)").arg(RDFImporter::getKnownExtensions());
Chris@529 61 break;
Chris@529 62
Chris@529 63 case AudioFile:
Chris@529 64 settingsKey = "audiopath";
Chris@529 65 title = "Select an audio file";
Chris@529 66 filter = tr("Audio files (%1)\nAll files (*.*)")
Chris@529 67 .arg(AudioFileReaderFactory::getKnownExtensions());
Chris@529 68 break;
Chris@529 69
Chris@529 70 case LayerFile:
Chris@529 71 settingsKey = "layerpath";
Chris@529 72 filter = tr("All supported files (%1 %2)\nSonic Visualiser Layer XML files (*.svl)\nComma-separated data files (*.csv)\nSpace-separated .lab files (*.lab)\nRDF files (%2)\nMIDI files (*.mid)\nText files (*.txt)\nAll files (*.*)")
Chris@529 73 .arg(DataFileReaderFactory::getKnownExtensions())
Chris@529 74 .arg(RDFImporter::getKnownExtensions());
Chris@529 75 break;
Chris@529 76
Chris@529 77 case LayerFileNoMidi:
Chris@529 78 settingsKey = "layerpath";
Chris@529 79 filter = tr("All supported files (%1 %2)\nSonic Visualiser Layer XML files (*.svl)\nComma-separated data files (*.csv)\nSpace-separated .lab files (*.lab)\nRDF files (%2)\nText files (*.txt)\nAll files (*.*)")
Chris@529 80 .arg(DataFileReaderFactory::getKnownExtensions())
Chris@529 81 .arg(RDFImporter::getKnownExtensions());
Chris@529 82 break;
Chris@529 83
Chris@705 84 case LayerFileNonSV:
Chris@705 85 settingsKey = "layerpath";
Chris@705 86 filter = tr("All supported files (%1 %2)\nComma-separated data files (*.csv)\nSonic Visualiser Layer XML files (*.svl)\nSpace-separated .lab files (*.lab)\nRDF files (%2)\nMIDI files (*.mid)\nText files (*.txt)\nAll files (*.*)")
Chris@705 87 .arg(DataFileReaderFactory::getKnownExtensions())
Chris@705 88 .arg(RDFImporter::getKnownExtensions());
Chris@705 89 break;
Chris@705 90
Chris@705 91 case LayerFileNoMidiNonSV:
Chris@705 92 settingsKey = "layerpath";
Chris@705 93 filter = tr("All supported files (%1 %2)\nComma-separated data files (*.csv)\nSonic Visualiser Layer XML files (*.svl)\nSpace-separated .lab files (*.lab)\nRDF files (%2)\nText files (*.txt)\nAll files (*.*)")
Chris@705 94 .arg(DataFileReaderFactory::getKnownExtensions())
Chris@705 95 .arg(RDFImporter::getKnownExtensions());
Chris@705 96 break;
Chris@705 97
Chris@529 98 case SessionOrAudioFile:
Chris@529 99 settingsKey = "lastpath";
Chris@529 100 filter = tr("All supported files (*.sv %1 %2)\nSonic Visualiser session files (*.sv)\nAudio files (%2)\nRDF files (%1)\nAll files (*.*)")
Chris@529 101 .arg(RDFImporter::getKnownExtensions())
Chris@529 102 .arg(AudioFileReaderFactory::getKnownExtensions());
Chris@529 103 break;
Chris@529 104
Chris@529 105 case ImageFile:
Chris@529 106 settingsKey = "imagepath";
Chris@529 107 {
Chris@529 108 QStringList fmts;
Chris@529 109 QList<QByteArray> formats = QImageReader::supportedImageFormats();
Chris@529 110 for (QList<QByteArray>::iterator i = formats.begin();
Chris@529 111 i != formats.end(); ++i) {
Chris@529 112 fmts.push_back(QString("*.%1")
Chris@529 113 .arg(QString::fromLocal8Bit(*i).toLower()));
Chris@529 114 }
Chris@529 115 filter = tr("Image files (%1)\nAll files (*.*)").arg(fmts.join(" "));
Chris@529 116 }
Chris@529 117 break;
Chris@529 118
Chris@672 119 case CSVFile:
Chris@672 120 settingsKey = "layerpath";
Chris@672 121 filter = tr("Comma-separated data files (*.csv)\nSpace-separated .lab files (*.lab)\nText files (*.txt)\nAll files (*.*)");
Chris@672 122 break;
Chris@672 123
Chris@529 124 case AnyFile:
Chris@529 125 settingsKey = "lastpath";
Chris@529 126 filter = tr("All supported files (*.sv %1 %2 %3)\nSonic Visualiser session files (*.sv)\nAudio files (%1)\nLayer files (%2)\nRDF files (%3)\nAll files (*.*)")
Chris@529 127 .arg(AudioFileReaderFactory::getKnownExtensions())
Chris@529 128 .arg(DataFileReaderFactory::getKnownExtensions())
Chris@529 129 .arg(RDFImporter::getKnownExtensions());
Chris@529 130 break;
Chris@529 131 };
Chris@529 132
Chris@529 133 if (lastPath == "") {
Chris@529 134 char *home = getenv("HOME");
Chris@529 135 if (home) lastPath = home;
Chris@529 136 else lastPath = ".";
Chris@529 137 } else if (QFileInfo(lastPath).isDir()) {
Chris@529 138 lastPath = QFileInfo(lastPath).canonicalPath();
Chris@529 139 } else {
Chris@529 140 lastPath = QFileInfo(lastPath).absoluteDir().canonicalPath();
Chris@529 141 }
Chris@529 142
Chris@529 143 QSettings settings;
Chris@529 144 settings.beginGroup("FileFinder");
Chris@529 145 lastPath = settings.value(settingsKey, lastPath).toString();
Chris@529 146
Chris@529 147 QString path = "";
Chris@529 148
Chris@529 149 // Use our own QFileDialog just for symmetry with getSaveFileName below
Chris@529 150
Chris@529 151 QFileDialog dialog;
Chris@616 152 dialog.setNameFilters(filter.split('\n'));
Chris@529 153 dialog.setWindowTitle(title);
Chris@529 154 dialog.setDirectory(lastPath);
Chris@529 155
Chris@529 156 dialog.setAcceptMode(QFileDialog::AcceptOpen);
Chris@529 157 dialog.setFileMode(QFileDialog::ExistingFile);
Chris@529 158
Chris@529 159 if (dialog.exec()) {
Chris@529 160 QStringList files = dialog.selectedFiles();
Chris@529 161 if (!files.empty()) path = *files.begin();
Chris@529 162
Chris@529 163 QFileInfo fi(path);
Chris@529 164
Chris@529 165 if (!fi.exists()) {
Chris@529 166
Chris@529 167 QMessageBox::critical(0, tr("File does not exist"),
Chris@529 168 tr("<b>File not found</b><p>File \"%1\" does not exist").arg(path));
Chris@529 169 path = "";
Chris@529 170
Chris@529 171 } else if (!fi.isReadable()) {
Chris@529 172
Chris@529 173 QMessageBox::critical(0, tr("File is not readable"),
Chris@529 174 tr("<b>File is not readable</b><p>File \"%1\" can not be read").arg(path));
Chris@529 175 path = "";
Chris@529 176
Chris@529 177 } else if (fi.isDir()) {
Chris@529 178
Chris@529 179 QMessageBox::critical(0, tr("Directory selected"),
Chris@529 180 tr("<b>Directory selected</b><p>File \"%1\" is a directory").arg(path));
Chris@529 181 path = "";
Chris@529 182
Chris@529 183 } else if (!fi.isFile()) {
Chris@529 184
Chris@529 185 QMessageBox::critical(0, tr("Non-file selected"),
Chris@529 186 tr("<b>Not a file</b><p>Path \"%1\" is not a file").arg(path));
Chris@529 187 path = "";
Chris@529 188
Chris@529 189 } else if (fi.size() == 0) {
Chris@529 190
Chris@529 191 QMessageBox::critical(0, tr("File is empty"),
Chris@529 192 tr("<b>File is empty</b><p>File \"%1\" is empty").arg(path));
Chris@529 193 path = "";
Chris@529 194 }
Chris@529 195 }
Chris@529 196
Chris@529 197 if (path != "") {
Chris@529 198 settings.setValue(settingsKey,
Chris@529 199 QFileInfo(path).absoluteDir().canonicalPath());
Chris@529 200 }
Chris@529 201
Chris@529 202 return path;
Chris@529 203 }
Chris@529 204
Chris@529 205 QString
Chris@529 206 InteractiveFileFinder::getSaveFileName(FileType type, QString fallbackLocation)
Chris@529 207 {
Chris@529 208 QString settingsKey;
Chris@529 209 QString lastPath = fallbackLocation;
Chris@529 210
Chris@529 211 QString title = tr("Select file");
Chris@529 212 QString filter = tr("All files (*.*)");
Chris@529 213
Chris@529 214 switch (type) {
Chris@529 215
Chris@529 216 case SessionFile:
Chris@529 217 settingsKey = "savesessionpath";
Chris@529 218 title = tr("Select a session file");
Chris@529 219 filter = tr("Sonic Visualiser session files (*.sv)\nAll files (*.*)");
Chris@529 220 break;
Chris@529 221
Chris@529 222 case AudioFile:
Chris@529 223 settingsKey = "saveaudiopath";
Chris@529 224 title = "Select an audio file";
Chris@529 225 title = tr("Select a file to export to");
Chris@529 226 filter = tr("WAV audio files (*.wav)\nAll files (*.*)");
Chris@529 227 break;
Chris@529 228
Chris@529 229 case LayerFile:
Chris@529 230 settingsKey = "savelayerpath";
Chris@529 231 title = tr("Select a file to export to");
Chris@529 232 filter = tr("Sonic Visualiser Layer XML files (*.svl)\nComma-separated data files (*.csv)\nRDF/Turtle files (%1)\nMIDI files (*.mid)\nText files (*.txt)\nAll files (*.*)").arg(RDFExporter::getSupportedExtensions());
Chris@529 233 break;
Chris@529 234
Chris@529 235 case LayerFileNoMidi:
Chris@529 236 settingsKey = "savelayerpath";
Chris@529 237 title = tr("Select a file to export to");
Chris@529 238 filter = tr("Sonic Visualiser Layer XML files (*.svl)\nComma-separated data files (*.csv)\nRDF/Turtle files (%1)\nText files (*.txt)\nAll files (*.*)").arg(RDFExporter::getSupportedExtensions());
Chris@529 239 break;
Chris@529 240
Chris@705 241 case LayerFileNonSV:
Chris@705 242 settingsKey = "savelayerpath";
Chris@705 243 title = tr("Select a file to export to");
Chris@705 244 filter = tr("Comma-separated data files (*.csv)\nSonic Visualiser Layer XML files (*.svl)\nRDF/Turtle files (%1)\nMIDI files (*.mid)\nText files (*.txt)\nAll files (*.*)").arg(RDFExporter::getSupportedExtensions());
Chris@705 245 break;
Chris@705 246
Chris@705 247 case LayerFileNoMidiNonSV:
Chris@705 248 settingsKey = "savelayerpath";
Chris@705 249 title = tr("Select a file to export to");
Chris@705 250 filter = tr("Comma-separated data files (*.csv)\nSonic Visualiser Layer XML files (*.svl)\nRDF/Turtle files (%1)\nText files (*.txt)\nAll files (*.*)").arg(RDFExporter::getSupportedExtensions());
Chris@705 251 break;
Chris@705 252
Chris@529 253 case SessionOrAudioFile:
Chris@682 254 cerr << "ERROR: Internal error: InteractiveFileFinder::getSaveFileName: SessionOrAudioFile cannot be used here" << endl;
Chris@529 255 abort();
Chris@529 256
Chris@529 257 case ImageFile:
Chris@529 258 settingsKey = "saveimagepath";
Chris@529 259 title = tr("Select a file to export to");
Chris@529 260 filter = tr("Portable Network Graphics files (*.png)\nAll files (*.*)");
Chris@529 261 break;
Chris@529 262
Chris@672 263 case CSVFile:
Chris@672 264 settingsKey = "savelayerpath";
Chris@672 265 title = tr("Select a file to export to");
Chris@672 266 filter = tr("Comma-separated data files (*.csv)\nText files (*.txt)\nAll files (*.*)");
Chris@672 267 break;
Chris@672 268
Chris@529 269 case AnyFile:
Chris@682 270 cerr << "ERROR: Internal error: InteractiveFileFinder::getSaveFileName: AnyFile cannot be used here" << endl;
Chris@529 271 abort();
Chris@529 272 };
Chris@529 273
Chris@529 274 if (lastPath == "") {
Chris@529 275 char *home = getenv("HOME");
Chris@529 276 if (home) lastPath = home;
Chris@529 277 else lastPath = ".";
Chris@529 278 } else if (QFileInfo(lastPath).isDir()) {
Chris@529 279 lastPath = QFileInfo(lastPath).canonicalPath();
Chris@529 280 } else {
Chris@529 281 lastPath = QFileInfo(lastPath).absoluteDir().canonicalPath();
Chris@529 282 }
Chris@529 283
Chris@529 284 QSettings settings;
Chris@529 285 settings.beginGroup("FileFinder");
Chris@529 286 lastPath = settings.value(settingsKey, lastPath).toString();
Chris@529 287
Chris@529 288 QString path = "";
Chris@529 289
Chris@529 290 // Use our own QFileDialog instead of static functions, as we may
Chris@529 291 // need to adjust the file extension based on the selected filter
Chris@529 292
Chris@529 293 QFileDialog dialog;
Chris@616 294 dialog.setNameFilters(filter.split('\n'));
Chris@529 295 dialog.setWindowTitle(title);
Chris@529 296 dialog.setDirectory(lastPath);
Chris@529 297
Chris@529 298 dialog.setAcceptMode(QFileDialog::AcceptSave);
Chris@529 299 dialog.setFileMode(QFileDialog::AnyFile);
Chris@529 300 dialog.setConfirmOverwrite(false); // we'll do that
Chris@529 301
Chris@529 302 if (type == SessionFile) {
Chris@529 303 dialog.setDefaultSuffix("sv");
Chris@529 304 } else if (type == AudioFile) {
Chris@529 305 dialog.setDefaultSuffix("wav");
Chris@529 306 } else if (type == ImageFile) {
Chris@529 307 dialog.setDefaultSuffix("png");
Chris@672 308 } else if (type == CSVFile) {
Chris@672 309 dialog.setDefaultSuffix("csv");
Chris@529 310 }
Chris@529 311
Chris@529 312 bool good = false;
Chris@529 313
Chris@529 314 while (!good) {
Chris@529 315
Chris@529 316 path = "";
Chris@529 317
Chris@529 318 if (!dialog.exec()) break;
Chris@529 319
Chris@529 320 QStringList files = dialog.selectedFiles();
Chris@529 321 if (files.empty()) break;
Chris@529 322 path = *files.begin();
Chris@529 323
Chris@529 324 QFileInfo fi(path);
Chris@529 325
Chris@682 326 cerr << "type = " << type << ", suffix = " << fi.suffix() << endl;
Chris@529 327
Chris@705 328 if ((type == LayerFile || type == LayerFileNoMidi ||
Chris@705 329 type == LayerFileNonSV || type == LayerFileNoMidiNonSV)
Chris@529 330 && fi.suffix() == "") {
Chris@529 331 QString expectedExtension;
Chris@616 332 QString selectedFilter = dialog.selectedNameFilter();
Chris@529 333 if (selectedFilter.contains(".svl")) {
Chris@529 334 expectedExtension = "svl";
Chris@529 335 } else if (selectedFilter.contains(".txt")) {
Chris@529 336 expectedExtension = "txt";
Chris@529 337 } else if (selectedFilter.contains(".csv")) {
Chris@529 338 expectedExtension = "csv";
Chris@529 339 } else if (selectedFilter.contains(".mid")) {
Chris@529 340 expectedExtension = "mid";
Chris@529 341 } else if (selectedFilter.contains(".ttl")) {
Chris@529 342 expectedExtension = "ttl";
Chris@529 343 }
Chris@682 344 cerr << "expected extension = " << expectedExtension << endl;
Chris@529 345 if (expectedExtension != "") {
Chris@529 346 path = QString("%1.%2").arg(path).arg(expectedExtension);
Chris@529 347 fi = QFileInfo(path);
Chris@529 348 }
Chris@529 349 }
Chris@529 350
Chris@529 351 if (fi.isDir()) {
Chris@529 352 QMessageBox::critical(0, tr("Directory selected"),
Chris@529 353 tr("<b>Directory selected</b><p>File \"%1\" is a directory").arg(path));
Chris@529 354 continue;
Chris@529 355 }
Chris@529 356
Chris@529 357 if (fi.exists()) {
Chris@529 358 if (QMessageBox::question(0, tr("File exists"),
Chris@529 359 tr("<b>File exists</b><p>The file \"%1\" already exists.\nDo you want to overwrite it?").arg(path),
Chris@529 360 QMessageBox::Ok,
Chris@529 361 QMessageBox::Cancel) != QMessageBox::Ok) {
Chris@529 362 continue;
Chris@529 363 }
Chris@529 364 }
Chris@529 365
Chris@529 366 good = true;
Chris@529 367 }
Chris@529 368
Chris@529 369 if (path != "") {
Chris@529 370 settings.setValue(settingsKey,
Chris@529 371 QFileInfo(path).absoluteDir().canonicalPath());
Chris@529 372 }
Chris@529 373
Chris@529 374 return path;
Chris@529 375 }
Chris@529 376
Chris@529 377 void
Chris@529 378 InteractiveFileFinder::registerLastOpenedFilePath(FileType type, QString path)
Chris@529 379 {
Chris@529 380 QString settingsKey;
Chris@529 381
Chris@529 382 switch (type) {
Chris@529 383 case SessionFile:
Chris@529 384 settingsKey = "sessionpath";
Chris@529 385 break;
Chris@529 386
Chris@529 387 case AudioFile:
Chris@529 388 settingsKey = "audiopath";
Chris@529 389 break;
Chris@529 390
Chris@529 391 case LayerFile:
Chris@529 392 settingsKey = "layerpath";
Chris@529 393 break;
Chris@529 394
Chris@529 395 case LayerFileNoMidi:
Chris@529 396 settingsKey = "layerpath";
Chris@529 397 break;
Chris@529 398
Chris@705 399 case LayerFileNonSV:
Chris@705 400 settingsKey = "layerpath";
Chris@705 401 break;
Chris@705 402
Chris@705 403 case LayerFileNoMidiNonSV:
Chris@705 404 settingsKey = "layerpath";
Chris@705 405 break;
Chris@705 406
Chris@529 407 case SessionOrAudioFile:
Chris@529 408 settingsKey = "lastpath";
Chris@529 409 break;
Chris@529 410
Chris@529 411 case ImageFile:
Chris@529 412 settingsKey = "imagepath";
Chris@529 413 break;
Chris@529 414
Chris@672 415 case CSVFile:
Chris@672 416 settingsKey = "layerpath";
Chris@672 417 break;
Chris@672 418
Chris@529 419 case AnyFile:
Chris@529 420 settingsKey = "lastpath";
Chris@529 421 break;
Chris@529 422 }
Chris@529 423
Chris@529 424 if (path != "") {
Chris@529 425 QSettings settings;
Chris@529 426 settings.beginGroup("FileFinder");
Chris@529 427 path = QFileInfo(path).absoluteDir().canonicalPath();
Chris@529 428 settings.setValue(settingsKey, path);
Chris@529 429 settings.setValue("lastpath", path);
Chris@529 430 }
Chris@529 431 }
Chris@529 432
Chris@529 433 QString
Chris@529 434 InteractiveFileFinder::find(FileType type, QString location, QString lastKnownLocation)
Chris@529 435 {
Chris@529 436 if (FileSource::canHandleScheme(location)) {
Chris@529 437 if (FileSource(location).isAvailable()) {
Chris@587 438 SVDEBUG << "InteractiveFileFinder::find: ok, it's available... returning" << endl;
Chris@529 439 return location;
Chris@529 440 }
Chris@529 441 }
Chris@529 442
Chris@529 443 if (QFileInfo(location).exists()) return location;
Chris@529 444
Chris@529 445 QString foundAt = "";
Chris@529 446
Chris@529 447 if ((foundAt = findRelative(location, lastKnownLocation)) != "") {
Chris@529 448 return foundAt;
Chris@529 449 }
Chris@529 450
Chris@529 451 if ((foundAt = findRelative(location, m_lastLocatedLocation)) != "") {
Chris@529 452 return foundAt;
Chris@529 453 }
Chris@529 454
Chris@529 455 return locateInteractive(type, location);
Chris@529 456 }
Chris@529 457
Chris@529 458 QString
Chris@529 459 InteractiveFileFinder::findRelative(QString location, QString relativeTo)
Chris@529 460 {
Chris@529 461 if (relativeTo == "") return "";
Chris@529 462
Chris@587 463 SVDEBUG << "Looking for \"" << location << "\" next to \""
Chris@585 464 << relativeTo << "\"..." << endl;
Chris@529 465
Chris@529 466 QString fileName;
Chris@529 467 QString resolved;
Chris@529 468
Chris@529 469 if (FileSource::isRemote(location)) {
Chris@529 470 fileName = QUrl(location).path().section('/', -1, -1,
Chris@529 471 QString::SectionSkipEmpty);
Chris@529 472 } else {
Chris@529 473 if (QUrl(location).scheme() == "file") {
Chris@529 474 location = QUrl(location).toLocalFile();
Chris@529 475 }
Chris@529 476 fileName = QFileInfo(location).fileName();
Chris@529 477 }
Chris@529 478
Chris@529 479 if (FileSource::isRemote(relativeTo)) {
Chris@529 480 resolved = QUrl(relativeTo).resolved(fileName).toString();
Chris@529 481 if (!FileSource(resolved).isAvailable()) resolved = "";
Chris@682 482 cerr << "resolved: " << resolved << endl;
Chris@529 483 } else {
Chris@529 484 if (QUrl(relativeTo).scheme() == "file") {
Chris@529 485 relativeTo = QUrl(relativeTo).toLocalFile();
Chris@529 486 }
Chris@529 487 resolved = QFileInfo(relativeTo).dir().filePath(fileName);
Chris@529 488 if (!QFileInfo(resolved).exists() ||
Chris@529 489 !QFileInfo(resolved).isFile() ||
Chris@529 490 !QFileInfo(resolved).isReadable()) {
Chris@529 491 resolved = "";
Chris@529 492 }
Chris@529 493 }
Chris@529 494
Chris@529 495 return resolved;
Chris@529 496 }
Chris@529 497
Chris@529 498 QString
Chris@529 499 InteractiveFileFinder::locateInteractive(FileType type, QString thing)
Chris@529 500 {
Chris@529 501 QString question;
Chris@529 502 if (type == AudioFile) {
Chris@529 503 question = tr("<b>File not found</b><p>Audio file \"%1\" could not be opened.\nDo you want to locate it?");
Chris@529 504 } else {
Chris@529 505 question = tr("<b>File not found</b><p>File \"%1\" could not be opened.\nDo you want to locate it?");
Chris@529 506 }
Chris@529 507
Chris@529 508 QString path = "";
Chris@529 509 bool done = false;
Chris@529 510
Chris@529 511 while (!done) {
Chris@529 512
Chris@529 513 int rv = QMessageBox::question
Chris@529 514 (0,
Chris@529 515 tr("Failed to open file"),
Chris@529 516 question.arg(thing),
Chris@529 517 tr("Locate file..."),
Chris@529 518 tr("Use URL..."),
Chris@529 519 tr("Cancel"),
Chris@529 520 0, 2);
Chris@529 521
Chris@529 522 switch (rv) {
Chris@529 523
Chris@529 524 case 0: // Locate file
Chris@529 525
Chris@529 526 if (QFileInfo(thing).dir().exists()) {
Chris@529 527 path = QFileInfo(thing).dir().canonicalPath();
Chris@529 528 }
Chris@529 529
Chris@529 530 path = getOpenFileName(type, path);
Chris@529 531 done = (path != "");
Chris@529 532 break;
Chris@529 533
Chris@529 534 case 1: // Use URL
Chris@529 535 {
Chris@529 536 bool ok = false;
Chris@529 537 path = QInputDialog::getText
Chris@529 538 (0, tr("Use URL"),
Chris@529 539 tr("Please enter the URL to use for this file:"),
Chris@529 540 QLineEdit::Normal, "", &ok);
Chris@529 541
Chris@529 542 if (ok && path != "") {
Chris@529 543 if (FileSource(path).isAvailable()) {
Chris@529 544 done = true;
Chris@529 545 } else {
Chris@529 546 QMessageBox::critical
Chris@529 547 (0, tr("Failed to open location"),
Chris@529 548 tr("<b>Failed to open location</b><p>URL \"%1\" could not be opened").arg(path));
Chris@529 549 path = "";
Chris@529 550 }
Chris@529 551 }
Chris@529 552 break;
Chris@529 553 }
Chris@529 554
Chris@529 555 case 2: // Cancel
Chris@529 556 path = "";
Chris@529 557 done = true;
Chris@529 558 break;
Chris@529 559 }
Chris@529 560 }
Chris@529 561
Chris@529 562 if (path != "") m_lastLocatedLocation = path;
Chris@529 563 return path;
Chris@529 564 }
Chris@529 565
Chris@529 566