Mercurial > hg > sonic-visualiser
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; |