annotate widgets/InteractiveFileFinder.cpp @ 1362:d79e21855aef

Add mechanism for saving/loading colour maps by name/id rather than by numerical index, for future compatibility when adding to or changing the supported colour maps. Add two new colour maps (and one old one). Write out backward-compatible numerical indices for use when reloading in older versions. Also add a mechanism to invert the colour map, though I don't think it turns out useful enough to include in the UI.
author Chris Cannam
date Thu, 18 Oct 2018 13:21:56 +0100
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