annotate widgets/InteractiveFileFinder.cpp @ 790:7555b8b17e6e tonioni

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