comparison main/MainWindow.cpp @ 86:6113fdda2737

* Add Open Location... * Add support for URLs in Recent Files * Do the right thing with the last location for file open dialogs when opening a URL (i.e. don't change it to the temporary file directory)
author Chris Cannam
date Wed, 10 Jan 2007 12:27:55 +0000
parents 4eae5b521a34
children 8944f3005a15
comparison
equal deleted inserted replaced
85:4eae5b521a34 86:6113fdda2737
661 connect(action, SIGNAL(triggered()), this, SLOT(exportLayer())); 661 connect(action, SIGNAL(triggered()), this, SLOT(exportLayer()));
662 connect(this, SIGNAL(canExportLayer(bool)), action, SLOT(setEnabled(bool))); 662 connect(this, SIGNAL(canExportLayer(bool)), action, SLOT(setEnabled(bool)));
663 menu->addAction(action); 663 menu->addAction(action);
664 664
665 menu->addSeparator(); 665 menu->addSeparator();
666
667 action = new QAction(tr("Open Lo&cation..."), this);
668 action->setShortcut(tr("Ctrl+Shift+O"));
669 action->setStatusTip(tr("Open or import a file from a remote URL"));
670 connect(action, SIGNAL(triggered()), this, SLOT(openLocation()));
671 menu->addAction(action);
672
673 menu->addSeparator();
674
666 m_recentFilesMenu = menu->addMenu(tr("&Recent Files")); 675 m_recentFilesMenu = menu->addMenu(tr("&Recent Files"));
667 setupRecentFilesMenu(); 676 setupRecentFilesMenu();
668 connect(&m_recentFiles, SIGNAL(recentChanged()), 677 connect(&m_recentFiles, SIGNAL(recentChanged()),
669 this, SLOT(setupRecentFilesMenu())); 678 this, SLOT(setupRecentFilesMenu()));
670 679
2208 } 2217 }
2209 2218
2210 MainWindow::FileOpenStatus 2219 MainWindow::FileOpenStatus
2211 MainWindow::openLayerFile(QString path) 2220 MainWindow::openLayerFile(QString path)
2212 { 2221 {
2222 return openLayerFile(path, path);
2223 }
2224
2225 MainWindow::FileOpenStatus
2226 MainWindow::openLayerFile(QString path, QString location)
2227 {
2213 Pane *pane = m_paneStack->getCurrentPane(); 2228 Pane *pane = m_paneStack->getCurrentPane();
2214 2229
2215 if (!pane) { 2230 if (!pane) {
2216 // shouldn't happen, as the menu action should have been disabled 2231 // shouldn't happen, as the menu action should have been disabled
2217 std::cerr << "WARNING: MainWindow::openLayerFile: no current pane" << std::endl; 2232 std::cerr << "WARNING: MainWindow::openLayerFile: no current pane" << std::endl;
2222 // shouldn't happen, as the menu action should have been disabled 2237 // shouldn't happen, as the menu action should have been disabled
2223 std::cerr << "WARNING: MainWindow::openLayerFile: No main model -- hence no default sample rate available" << std::endl; 2238 std::cerr << "WARNING: MainWindow::openLayerFile: No main model -- hence no default sample rate available" << std::endl;
2224 return FileOpenFailed; 2239 return FileOpenFailed;
2225 } 2240 }
2226 2241
2242 bool realFile = (location == path);
2243
2227 if (path.endsWith(".svl") || path.endsWith(".xml")) { 2244 if (path.endsWith(".svl") || path.endsWith(".xml")) {
2228 2245
2229 PaneCallback callback(this); 2246 PaneCallback callback(this);
2230 QFile file(path); 2247 QFile file(path);
2231 2248
2232 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { 2249 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
2233 std::cerr << "ERROR: MainWindow::openLayerFile(" 2250 std::cerr << "ERROR: MainWindow::openLayerFile("
2234 << path.toStdString() 2251 << location.toStdString()
2235 << "): Failed to open file for reading" << std::endl; 2252 << "): Failed to open file for reading" << std::endl;
2236 return FileOpenFailed; 2253 return FileOpenFailed;
2237 } 2254 }
2238 2255
2239 SVFileReader reader(m_document, callback); 2256 SVFileReader reader(m_document, callback);
2242 QXmlInputSource inputSource(&file); 2259 QXmlInputSource inputSource(&file);
2243 reader.parse(inputSource); 2260 reader.parse(inputSource);
2244 2261
2245 if (!reader.isOK()) { 2262 if (!reader.isOK()) {
2246 std::cerr << "ERROR: MainWindow::openLayerFile(" 2263 std::cerr << "ERROR: MainWindow::openLayerFile("
2247 << path.toStdString() 2264 << location.toStdString()
2248 << "): Failed to read XML file: " 2265 << "): Failed to read XML file: "
2249 << reader.getErrorString().toStdString() << std::endl; 2266 << reader.getErrorString().toStdString() << std::endl;
2250 return FileOpenFailed; 2267 return FileOpenFailed;
2251 } 2268 }
2252 2269
2253 m_recentFiles.addFile(path); 2270 m_recentFiles.addFile(location);
2254 registerLastOpenedFilePath(LayerFile, path); // for file dialog 2271
2272 if (realFile) {
2273 registerLastOpenedFilePath(LayerFile, path); // for file dialog
2274 }
2275
2255 return FileOpenSucceeded; 2276 return FileOpenSucceeded;
2256 2277
2257 } else { 2278 } else {
2258 2279
2259 Model *model = DataFileReaderFactory::load(path, getMainModel()->getSampleRate()); 2280 Model *model = DataFileReaderFactory::load(path, getMainModel()->getSampleRate());
2260 2281
2261 if (model) { 2282 if (model) {
2283
2262 Layer *newLayer = m_document->createImportedLayer(model); 2284 Layer *newLayer = m_document->createImportedLayer(model);
2285
2263 if (newLayer) { 2286 if (newLayer) {
2287
2264 m_document->addLayerToView(pane, newLayer); 2288 m_document->addLayerToView(pane, newLayer);
2265 m_recentFiles.addFile(path); 2289 m_recentFiles.addFile(location);
2290
2291 if (realFile) {
2292 registerLastOpenedFilePath(LayerFile, path); // for file dialog
2293 }
2294
2266 return FileOpenSucceeded; 2295 return FileOpenSucceeded;
2267 } 2296 }
2268 } 2297 }
2269 } 2298 }
2270 2299
2333 } 2362 }
2334 2363
2335 MainWindow::FileOpenStatus 2364 MainWindow::FileOpenStatus
2336 MainWindow::openAudioFile(QString path, AudioFileOpenMode mode) 2365 MainWindow::openAudioFile(QString path, AudioFileOpenMode mode)
2337 { 2366 {
2367 return openAudioFile(path, path, mode);
2368 }
2369
2370 MainWindow::FileOpenStatus
2371 MainWindow::openAudioFile(QString path, QString location, AudioFileOpenMode mode)
2372 {
2338 if (!(QFileInfo(path).exists() && 2373 if (!(QFileInfo(path).exists() &&
2339 QFileInfo(path).isFile() && 2374 QFileInfo(path).isFile() &&
2340 QFileInfo(path).isReadable())) { 2375 QFileInfo(path).isReadable())) {
2341 return FileOpenFailed; 2376 return FileOpenFailed;
2342 } 2377 }
2351 return FileOpenFailed; 2386 return FileOpenFailed;
2352 } 2387 }
2353 2388
2354 bool setAsMain = true; 2389 bool setAsMain = true;
2355 static bool prevSetAsMain = true; 2390 static bool prevSetAsMain = true;
2391
2392 bool realFile = (location == path);
2356 2393
2357 if (mode == CreateAdditionalModel) setAsMain = false; 2394 if (mode == CreateAdditionalModel) setAsMain = false;
2358 else if (mode == AskUser) { 2395 else if (mode == AskUser) {
2359 if (m_document->getMainModel()) { 2396 if (m_document->getMainModel()) {
2360 2397
2393 m_document->setMainModel(newModel); 2430 m_document->setMainModel(newModel);
2394 setupMenus(); 2431 setupMenus();
2395 2432
2396 if (m_sessionFile == "") { 2433 if (m_sessionFile == "") {
2397 setWindowTitle(tr("Sonic Visualiser: %1") 2434 setWindowTitle(tr("Sonic Visualiser: %1")
2398 .arg(QFileInfo(path).fileName())); 2435 .arg(QFileInfo(location).fileName()));
2399 CommandHistory::getInstance()->clear(); 2436 CommandHistory::getInstance()->clear();
2400 CommandHistory::getInstance()->documentSaved(); 2437 CommandHistory::getInstance()->documentSaved();
2401 m_documentModified = false; 2438 m_documentModified = false;
2402 } else { 2439 } else {
2403 setWindowTitle(tr("Sonic Visualiser: %1 [%2]") 2440 setWindowTitle(tr("Sonic Visualiser: %1 [%2]")
2404 .arg(QFileInfo(m_sessionFile).fileName()) 2441 .arg(QFileInfo(m_sessionFile).fileName())
2405 .arg(QFileInfo(path).fileName())); 2442 .arg(QFileInfo(location).fileName()));
2406 if (m_documentModified) { 2443 if (m_documentModified) {
2407 m_documentModified = false; 2444 m_documentModified = false;
2408 documentModified(); // so as to restore "(modified)" window title 2445 documentModified(); // so as to restore "(modified)" window title
2409 } 2446 }
2410 } 2447 }
2411 2448
2412 m_audioFile = path; 2449 if (realFile) m_audioFile = path;
2413 2450
2414 } else { // !setAsMain 2451 } else { // !setAsMain
2415 2452
2416 CommandHistory::getInstance()->startCompoundOperation 2453 CommandHistory::getInstance()->startCompoundOperation
2417 (tr("Import \"%1\"").arg(QFileInfo(path).fileName()), true); 2454 (tr("Import \"%1\"").arg(QFileInfo(location).fileName()), true);
2418 2455
2419 m_document->addImportedModel(newModel); 2456 m_document->addImportedModel(newModel);
2420 2457
2421 AddPaneCommand *command = new AddPaneCommand(this); 2458 AddPaneCommand *command = new AddPaneCommand(this);
2422 CommandHistory::getInstance()->addCommand(command); 2459 CommandHistory::getInstance()->addCommand(command);
2438 2475
2439 CommandHistory::getInstance()->endCompoundOperation(); 2476 CommandHistory::getInstance()->endCompoundOperation();
2440 } 2477 }
2441 2478
2442 updateMenuStates(); 2479 updateMenuStates();
2443 m_recentFiles.addFile(path); 2480 m_recentFiles.addFile(location);
2444 registerLastOpenedFilePath(AudioFile, path); // for file dialog 2481 if (realFile) {
2482 registerLastOpenedFilePath(AudioFile, path); // for file dialog
2483 }
2445 m_openingAudioFile = false; 2484 m_openingAudioFile = false;
2446 2485
2447 return FileOpenSucceeded; 2486 return FileOpenSucceeded;
2448 } 2487 }
2449 2488
2625 } 2664 }
2626 } 2665 }
2627 } 2666 }
2628 2667
2629 void 2668 void
2669 MainWindow::openLocation()
2670 {
2671 bool ok = false;
2672 QString text = QInputDialog::getText
2673 (this, tr("Open Location"),
2674 tr("Please enter the URL of the location to open:"),
2675 QLineEdit::Normal, "", &ok);
2676 if (!ok || text.isEmpty()) return;
2677
2678 if (openURL(QUrl(text)) == FileOpenFailed) {
2679 QMessageBox::critical(this, tr("Failed to open location"),
2680 tr("URL \"%1\" could not be opened").arg(text));
2681 }
2682 }
2683
2684 void
2630 MainWindow::openRecentFile() 2685 MainWindow::openRecentFile()
2631 { 2686 {
2632 QObject *obj = sender(); 2687 QObject *obj = sender();
2633 QAction *action = dynamic_cast<QAction *>(obj); 2688 QAction *action = dynamic_cast<QAction *>(obj);
2634 2689
2639 } 2694 }
2640 2695
2641 QString path = action->text(); 2696 QString path = action->text();
2642 if (path == "") return; 2697 if (path == "") return;
2643 2698
2699 QUrl url(path);
2700 if (RemoteFile::canHandleScheme(url)) {
2701 openURL(url);
2702 return;
2703 }
2704
2644 if (path.endsWith("sv")) { 2705 if (path.endsWith("sv")) {
2645 2706
2646 if (!checkSaveModified()) return ; 2707 if (!checkSaveModified()) return ;
2647 2708
2648 if (openSessionFile(path) == FileOpenFailed) { 2709 if (openSessionFile(path) == FileOpenFailed) {
2670 MainWindow::FileOpenStatus 2731 MainWindow::FileOpenStatus
2671 MainWindow::openURL(QUrl url) 2732 MainWindow::openURL(QUrl url)
2672 { 2733 {
2673 if (url.scheme().toLower() == "file") { 2734 if (url.scheme().toLower() == "file") {
2674 return openSomeFile(url.toLocalFile()); 2735 return openSomeFile(url.toLocalFile());
2675 } else if (url.scheme().toLower() != "http" && 2736 } else if (!RemoteFile::canHandleScheme(url)) {
2676 url.scheme().toLower() != "ftp") {
2677 QMessageBox::critical(this, tr("Unsupported scheme in URL"), 2737 QMessageBox::critical(this, tr("Unsupported scheme in URL"),
2678 tr("The URL scheme \"%1\" is not supported") 2738 tr("The URL scheme \"%1\" is not supported")
2679 .arg(url.scheme())); 2739 .arg(url.scheme()));
2680 return FileOpenFailed; 2740 return FileOpenFailed;
2681 } else { 2741 } else {
2687 tr("Failed to download URL \"%1\": %2") 2747 tr("Failed to download URL \"%1\": %2")
2688 .arg(url.toString()).arg(rf.getErrorString())); 2748 .arg(url.toString()).arg(rf.getErrorString()));
2689 return FileOpenFailed; 2749 return FileOpenFailed;
2690 } 2750 }
2691 //!!! and delete the file if we fail to open it here? 2751 //!!! and delete the file if we fail to open it here?
2692 return openSomeFile(rf.getLocalFilename()); 2752 return openSomeFile(rf.getLocalFilename(), url.toString());
2693 } 2753 }
2694 } 2754 }
2695 2755
2696 MainWindow::FileOpenStatus 2756 MainWindow::FileOpenStatus
2697 MainWindow::openSomeFile(QString path, AudioFileOpenMode mode) 2757 MainWindow::openSomeFile(QString path, AudioFileOpenMode mode)
2758 {
2759 return openSomeFile(path, path, mode);
2760 }
2761
2762 MainWindow::FileOpenStatus
2763 MainWindow::openSomeFile(QString path, QString location,
2764 AudioFileOpenMode mode)
2698 { 2765 {
2699 FileOpenStatus status; 2766 FileOpenStatus status;
2700 2767
2701 bool canImportLayer = (getMainModel() != 0 && 2768 bool canImportLayer = (getMainModel() != 0 &&
2702 m_paneStack != 0 && 2769 m_paneStack != 0 &&
2703 m_paneStack->getCurrentPane() != 0); 2770 m_paneStack->getCurrentPane() != 0);
2704 2771
2705 if ((status = openAudioFile(path, mode)) != FileOpenFailed) { 2772 if ((status = openAudioFile(path, location, mode)) != FileOpenFailed) {
2706 return status; 2773 return status;
2707 } else if ((status = openSessionFile(path)) != FileOpenFailed) { 2774 } else if ((status = openSessionFile(path, location)) != FileOpenFailed) {
2708 return status; 2775 return status;
2709 } else if (!canImportLayer) { 2776 } else if (!canImportLayer) {
2710 return FileOpenFailed; 2777 return FileOpenFailed;
2711 } else if ((status = openLayerFile(path)) != FileOpenFailed) { 2778 } else if ((status = openLayerFile(path, location)) != FileOpenFailed) {
2712 return status; 2779 return status;
2713 } else { 2780 } else {
2714 return FileOpenFailed; 2781 return FileOpenFailed;
2715 } 2782 }
2716 } 2783 }
2717 2784
2718 MainWindow::FileOpenStatus 2785 MainWindow::FileOpenStatus
2719 MainWindow::openSessionFile(QString path) 2786 MainWindow::openSessionFile(QString path)
2720 { 2787 {
2788 return openSessionFile(path, path);
2789 }
2790
2791 MainWindow::FileOpenStatus
2792 MainWindow::openSessionFile(QString path, QString location)
2793 {
2721 BZipFileDevice bzFile(path); 2794 BZipFileDevice bzFile(path);
2722 if (!bzFile.open(QIODevice::ReadOnly)) { 2795 if (!bzFile.open(QIODevice::ReadOnly)) {
2723 std::cerr << "Failed to open session file \"" << path.toStdString() 2796 std::cerr << "Failed to open session file \"" << location.toStdString()
2724 << "\": " << bzFile.errorString().toStdString() << std::endl; 2797 << "\": " << bzFile.errorString().toStdString() << std::endl;
2725 return FileOpenFailed; 2798 return FileOpenFailed;
2726 } 2799 }
2727 2800
2728 QString error; 2801 QString error;
2741 } 2814 }
2742 2815
2743 bzFile.close(); 2816 bzFile.close();
2744 2817
2745 bool ok = (error == ""); 2818 bool ok = (error == "");
2819
2820 bool realFile = (location == path);
2746 2821
2747 if (ok) { 2822 if (ok) {
2823
2748 setWindowTitle(tr("Sonic Visualiser: %1") 2824 setWindowTitle(tr("Sonic Visualiser: %1")
2749 .arg(QFileInfo(path).fileName())); 2825 .arg(QFileInfo(location).fileName()));
2750 m_sessionFile = path; 2826
2827 if (realFile) m_sessionFile = path;
2828
2751 setupMenus(); 2829 setupMenus();
2752 CommandHistory::getInstance()->clear(); 2830 CommandHistory::getInstance()->clear();
2753 CommandHistory::getInstance()->documentSaved(); 2831 CommandHistory::getInstance()->documentSaved();
2754 m_documentModified = false; 2832 m_documentModified = false;
2755 updateMenuStates(); 2833 updateMenuStates();
2756 m_recentFiles.addFile(path); 2834
2757 registerLastOpenedFilePath(SessionFile, path); // for file dialog 2835 m_recentFiles.addFile(location);
2836
2837 if (realFile) {
2838 registerLastOpenedFilePath(SessionFile, path); // for file dialog
2839 }
2840
2758 } else { 2841 } else {
2759 setWindowTitle(tr("Sonic Visualiser")); 2842 setWindowTitle(tr("Sonic Visualiser"));
2760 } 2843 }
2761 2844
2762 return ok ? FileOpenSucceeded : FileOpenFailed; 2845 return ok ? FileOpenSucceeded : FileOpenFailed;