annotate widgets/InteractiveFileFinder.cpp @ 1212:a1ee3108d1d3 3.0-integration

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