annotate widgets/InteractiveFileFinder.cpp @ 1386:fc3d89f88690 spectrogramparam

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