Mercurial > hg > sonic-visualiser
comparison main/MainWindow.cpp @ 197:c08c312b2399
* Make RemoteFile far more pervasive, and use it for local files as well
so that we can handle both transparently. Make it shallow copy with
reference counting, so it can be used by value without having to worry
about the cache file lifetime. Use RemoteFile for MainWindow file-open
functions, etc
author | Chris Cannam |
---|---|
date | Thu, 18 Oct 2007 15:31:20 +0000 |
parents | 61bf55e80080 |
children | 24ac2e4010c5 |
comparison
equal
deleted
inserted
replaced
196:29c356da4ae4 | 197:c08c312b2399 |
---|---|
2523 MainWindow::importAudio() | 2523 MainWindow::importAudio() |
2524 { | 2524 { |
2525 QString path = getOpenFileName(FileFinder::AudioFile); | 2525 QString path = getOpenFileName(FileFinder::AudioFile); |
2526 | 2526 |
2527 if (path != "") { | 2527 if (path != "") { |
2528 if (openAudioFile(path, ReplaceMainModel) == FileOpenFailed) { | 2528 if (openAudio(path, ReplaceMainModel) == FileOpenFailed) { |
2529 QMessageBox::critical(this, tr("Failed to open file"), | 2529 QMessageBox::critical(this, tr("Failed to open file"), |
2530 tr("<b>File open failed</b><p>Audio file \"%1\" could not be opened").arg(path)); | 2530 tr("<b>File open failed</b><p>Audio file \"%1\" could not be opened").arg(path)); |
2531 } | 2531 } |
2532 } | 2532 } |
2533 } | 2533 } |
2536 MainWindow::importMoreAudio() | 2536 MainWindow::importMoreAudio() |
2537 { | 2537 { |
2538 QString path = getOpenFileName(FileFinder::AudioFile); | 2538 QString path = getOpenFileName(FileFinder::AudioFile); |
2539 | 2539 |
2540 if (path != "") { | 2540 if (path != "") { |
2541 if (openAudioFile(path, CreateAdditionalModel) == FileOpenFailed) { | 2541 if (openAudio(path, CreateAdditionalModel) == FileOpenFailed) { |
2542 QMessageBox::critical(this, tr("Failed to open file"), | 2542 QMessageBox::critical(this, tr("Failed to open file"), |
2543 tr("<b>File open failed</b><p>Audio file \"%1\" could not be opened").arg(path)); | 2543 tr("<b>File open failed</b><p>Audio file \"%1\" could not be opened").arg(path)); |
2544 } | 2544 } |
2545 } | 2545 } |
2546 } | 2546 } |
2671 | 2671 |
2672 QString path = getOpenFileName(FileFinder::LayerFile); | 2672 QString path = getOpenFileName(FileFinder::LayerFile); |
2673 | 2673 |
2674 if (path != "") { | 2674 if (path != "") { |
2675 | 2675 |
2676 FileOpenStatus status = openLayerFile(path); | 2676 FileOpenStatus status = openLayer(path); |
2677 | 2677 |
2678 if (status == FileOpenFailed) { | 2678 if (status == FileOpenFailed) { |
2679 QMessageBox::critical(this, tr("Failed to open file"), | 2679 QMessageBox::critical(this, tr("Failed to open file"), |
2680 tr("<b>File open failed</b><p>Layer file %1 could not be opened.").arg(path)); | 2680 tr("<b>File open failed</b><p>Layer file %1 could not be opened.").arg(path)); |
2681 return; | 2681 return; |
2682 } else if (status == FileOpenWrongMode) { | 2682 } else if (status == FileOpenWrongMode) { |
2683 QMessageBox::critical(this, tr("Failed to open file"), | 2683 QMessageBox::critical(this, tr("Failed to open file"), |
2684 tr("<b>Audio required</b><p>Please load at least one audio file before importing annotation data")); | 2684 tr("<b>Audio required</b><p>Please load at least one audio file before importing annotation data")); |
2685 } | 2685 } |
2686 } | |
2687 } | |
2688 | |
2689 MainWindow::FileOpenStatus | |
2690 MainWindow::openLayerFile(QString path) | |
2691 { | |
2692 return openLayerFile(path, path); | |
2693 } | |
2694 | |
2695 MainWindow::FileOpenStatus | |
2696 MainWindow::openLayerFile(QString path, QString location) | |
2697 { | |
2698 Pane *pane = m_paneStack->getCurrentPane(); | |
2699 | |
2700 if (!pane) { | |
2701 // shouldn't happen, as the menu action should have been disabled | |
2702 std::cerr << "WARNING: MainWindow::openLayerFile: no current pane" << std::endl; | |
2703 return FileOpenWrongMode; | |
2704 } | |
2705 | |
2706 if (!getMainModel()) { | |
2707 // shouldn't happen, as the menu action should have been disabled | |
2708 std::cerr << "WARNING: MainWindow::openLayerFile: No main model -- hence no default sample rate available" << std::endl; | |
2709 return FileOpenWrongMode; | |
2710 } | |
2711 | |
2712 bool realFile = (location == path); | |
2713 | |
2714 if (path.endsWith(".svl") || path.endsWith(".xml")) { | |
2715 | |
2716 PaneCallback callback(this); | |
2717 QFile file(path); | |
2718 | |
2719 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { | |
2720 std::cerr << "ERROR: MainWindow::openLayerFile(" | |
2721 << location.toStdString() | |
2722 << "): Failed to open file for reading" << std::endl; | |
2723 return FileOpenFailed; | |
2724 } | |
2725 | |
2726 SVFileReader reader(m_document, callback, location); | |
2727 reader.setCurrentPane(pane); | |
2728 | |
2729 QXmlInputSource inputSource(&file); | |
2730 reader.parse(inputSource); | |
2731 | |
2732 if (!reader.isOK()) { | |
2733 std::cerr << "ERROR: MainWindow::openLayerFile(" | |
2734 << location.toStdString() | |
2735 << "): Failed to read XML file: " | |
2736 << reader.getErrorString().toStdString() << std::endl; | |
2737 return FileOpenFailed; | |
2738 } | |
2739 | |
2740 m_recentFiles.addFile(location); | |
2741 | |
2742 if (realFile) { | |
2743 registerLastOpenedFilePath(FileFinder::LayerFile, path); // for file dialog | |
2744 } | |
2745 | |
2746 return FileOpenSucceeded; | |
2747 | |
2748 } else { | |
2749 | |
2750 try { | |
2751 | |
2752 Model *model = DataFileReaderFactory::load | |
2753 (path, getMainModel()->getSampleRate()); | |
2754 | |
2755 if (model) { | |
2756 | |
2757 Layer *newLayer = m_document->createImportedLayer(model); | |
2758 | |
2759 if (newLayer) { | |
2760 | |
2761 m_document->addLayerToView(pane, newLayer); | |
2762 m_recentFiles.addFile(location); | |
2763 | |
2764 if (realFile) { | |
2765 registerLastOpenedFilePath(FileFinder::LayerFile, path); // for file dialog | |
2766 } | |
2767 | |
2768 return FileOpenSucceeded; | |
2769 } | |
2770 } | |
2771 } catch (DataFileReaderFactory::Exception e) { | |
2772 if (e == DataFileReaderFactory::ImportCancelled) { | |
2773 return FileOpenCancelled; | |
2774 } | |
2775 } | |
2776 } | |
2777 | |
2778 return FileOpenFailed; | |
2779 } | |
2780 | |
2781 MainWindow::FileOpenStatus | |
2782 MainWindow::openImageFile(QString path) | |
2783 { | |
2784 return openImageFile(path, path); | |
2785 } | |
2786 | |
2787 MainWindow::FileOpenStatus | |
2788 MainWindow::openImageFile(QString path, QString location) | |
2789 { | |
2790 Pane *pane = m_paneStack->getCurrentPane(); | |
2791 | |
2792 if (!pane) { | |
2793 // shouldn't happen, as the menu action should have been disabled | |
2794 std::cerr << "WARNING: MainWindow::openImageFile: no current pane" << std::endl; | |
2795 return FileOpenWrongMode; | |
2796 } | |
2797 | |
2798 if (!m_document->getMainModel()) { | |
2799 return FileOpenWrongMode; | |
2800 } | |
2801 | |
2802 bool newLayer = false; | |
2803 | |
2804 ImageLayer *il = dynamic_cast<ImageLayer *>(pane->getSelectedLayer()); | |
2805 if (!il) { | |
2806 for (int i = pane->getLayerCount()-1; i >= 0; --i) { | |
2807 il = dynamic_cast<ImageLayer *>(pane->getLayer(i)); | |
2808 if (il) break; | |
2809 } | |
2810 } | |
2811 if (!il) { | |
2812 il = dynamic_cast<ImageLayer *> | |
2813 (m_document->createEmptyLayer(LayerFactory::Image)); | |
2814 if (!il) return FileOpenFailed; | |
2815 newLayer = true; | |
2816 } | |
2817 | |
2818 // We don't put the image file in Recent Files | |
2819 | |
2820 std::cerr << "openImageFile: trying location \"" << location.toStdString() << "\" in image layer" << std::endl; | |
2821 | |
2822 if (!il->addImage(m_viewManager->getGlobalCentreFrame(), location)) { | |
2823 if (newLayer) { | |
2824 m_document->setModel(il, 0); // releasing its model | |
2825 delete il; | |
2826 } | |
2827 return FileOpenFailed; | |
2828 } else { | |
2829 if (newLayer) { | |
2830 m_document->addLayerToView(pane, il); | |
2831 } | |
2832 m_paneStack->setCurrentLayer(pane, il); | |
2833 return FileOpenSucceeded; | |
2834 } | 2686 } |
2835 } | 2687 } |
2836 | 2688 |
2837 void | 2689 void |
2838 MainWindow::exportLayer() | 2690 MainWindow::exportLayer() |
3004 | 2856 |
3005 delete image; | 2857 delete image; |
3006 } | 2858 } |
3007 | 2859 |
3008 MainWindow::FileOpenStatus | 2860 MainWindow::FileOpenStatus |
3009 MainWindow::openAudioFile(QString path, AudioFileOpenMode mode) | 2861 MainWindow::open(QString fileOrUrl, AudioFileOpenMode mode) |
3010 { | 2862 { |
3011 return openAudioFile(path, path, mode); | 2863 return open(RemoteFile(fileOrUrl), mode); |
3012 } | 2864 } |
3013 | 2865 |
3014 MainWindow::FileOpenStatus | 2866 MainWindow::FileOpenStatus |
3015 MainWindow::openAudioFile(QString path, QString location, AudioFileOpenMode mode) | 2867 MainWindow::open(RemoteFile source, AudioFileOpenMode mode) |
3016 { | 2868 { |
3017 if (!(QFileInfo(path).exists() && | 2869 FileOpenStatus status; |
3018 QFileInfo(path).isFile() && | 2870 |
3019 QFileInfo(path).isReadable())) { | 2871 if (!source.isAvailable()) return FileOpenFailed; |
2872 source.waitForData(); | |
2873 | |
2874 bool canImportLayer = (getMainModel() != 0 && | |
2875 m_paneStack != 0 && | |
2876 m_paneStack->getCurrentPane() != 0); | |
2877 | |
2878 if ((status = openAudio(source, mode)) != FileOpenFailed) { | |
2879 return status; | |
2880 } else if ((status = openSession(source)) != FileOpenFailed) { | |
2881 return status; | |
2882 } else if ((status = openPlaylist(source, mode)) != FileOpenFailed) { | |
2883 return status; | |
2884 } else if (!canImportLayer) { | |
2885 return FileOpenWrongMode; | |
2886 } else if ((status = openImage(source)) != FileOpenFailed) { | |
2887 return status; | |
2888 } else if ((status = openLayer(source)) != FileOpenFailed) { | |
2889 return status; | |
2890 } else { | |
3020 return FileOpenFailed; | 2891 return FileOpenFailed; |
3021 } | 2892 } |
2893 } | |
2894 | |
2895 MainWindow::FileOpenStatus | |
2896 MainWindow::openAudio(RemoteFile source, AudioFileOpenMode mode) | |
2897 { | |
2898 std::cerr << "MainWindow::openAudio(" << source.getLocation().toStdString() << ")" << std::endl; | |
2899 | |
2900 if (!source.isAvailable()) return FileOpenFailed; | |
2901 source.waitForData(); | |
3022 | 2902 |
3023 m_openingAudioFile = true; | 2903 m_openingAudioFile = true; |
3024 | 2904 |
3025 size_t rate = 0; | 2905 size_t rate = 0; |
3026 | 2906 |
3027 if (Preferences::getInstance()->getResampleOnLoad()) { | 2907 if (Preferences::getInstance()->getResampleOnLoad()) { |
3028 rate = m_playSource->getSourceSampleRate(); | 2908 rate = m_playSource->getSourceSampleRate(); |
3029 } | 2909 } |
3030 | 2910 |
3031 WaveFileModel *newModel = new WaveFileModel(path, location, rate); | 2911 WaveFileModel *newModel = new WaveFileModel(source, rate); |
3032 | 2912 |
3033 if (!newModel->isOK()) { | 2913 if (!newModel->isOK()) { |
3034 delete newModel; | 2914 delete newModel; |
3035 m_openingAudioFile = false; | 2915 m_openingAudioFile = false; |
3036 return FileOpenFailed; | 2916 return FileOpenFailed; |
3037 } | 2917 } |
3038 | 2918 |
3039 bool realFile = (location == path); | |
3040 | |
3041 std::cerr << "mode = " << mode << std::endl; | 2919 std::cerr << "mode = " << mode << std::endl; |
3042 | 2920 |
3043 if (mode == AskUser) { | 2921 if (mode == AskUser) { |
3044 if (getMainModel()) { | 2922 if (getMainModel()) { |
3045 | |
3046 std::cerr << "ask user, have main model" << std::endl; | |
3047 | 2923 |
3048 static bool prevSetAsMain = true; | 2924 static bool prevSetAsMain = true; |
3049 bool setAsMain = true; | 2925 bool setAsMain = true; |
3050 | 2926 |
3051 QStringList items; | 2927 QStringList items; |
3075 } | 2951 } |
3076 } | 2952 } |
3077 | 2953 |
3078 if (mode == ReplaceCurrentPane) { | 2954 if (mode == ReplaceCurrentPane) { |
3079 | 2955 |
3080 // std::cerr << "replace current pane" << std::endl; | |
3081 | |
3082 Pane *pane = m_paneStack->getCurrentPane(); | 2956 Pane *pane = m_paneStack->getCurrentPane(); |
3083 if (pane) { | 2957 if (pane) { |
3084 // std::cerr << "have pane" << std::endl; | |
3085 | |
3086 if (getMainModel()) { | 2958 if (getMainModel()) { |
3087 // std::cerr << "have main model" << std::endl; | |
3088 | |
3089 View::ModelSet models(pane->getModels()); | 2959 View::ModelSet models(pane->getModels()); |
3090 if (models.find(getMainModel()) != models.end()) { | 2960 if (models.find(getMainModel()) != models.end()) { |
3091 // std::cerr << "main model is in pane, setting to ReplaceMainModel" << std::endl; | |
3092 mode = ReplaceMainModel; | 2961 mode = ReplaceMainModel; |
3093 } | 2962 } |
3094 } else { | 2963 } else { |
3095 // std::cerr << "no main model, setting to ReplaceMainModel" << std::endl; | |
3096 mode = ReplaceMainModel; | 2964 mode = ReplaceMainModel; |
3097 } | 2965 } |
3098 } else { | 2966 } else { |
3099 // std::cerr << "no pane, setting to CreateAdditionalModel" << std::endl; | |
3100 mode = CreateAdditionalModel; | 2967 mode = CreateAdditionalModel; |
3101 } | 2968 } |
3102 } | 2969 } |
3103 | 2970 |
3104 if (mode == CreateAdditionalModel && !getMainModel()) { | 2971 if (mode == CreateAdditionalModel && !getMainModel()) { |
3105 // std::cerr << "mode is CreateAdditionalModel and no main model, setting to ReplaceMainModel" << std::endl; | |
3106 mode = ReplaceMainModel; | 2972 mode = ReplaceMainModel; |
3107 } | 2973 } |
3108 | |
3109 // std::cerr << "mode now " << mode << std::endl; | |
3110 | 2974 |
3111 if (mode == ReplaceMainModel) { | 2975 if (mode == ReplaceMainModel) { |
3112 | 2976 |
3113 Model *prevMain = getMainModel(); | 2977 Model *prevMain = getMainModel(); |
3114 if (prevMain) { | 2978 if (prevMain) { |
3120 m_document->setMainModel(newModel); | 2984 m_document->setMainModel(newModel); |
3121 setupMenus(); | 2985 setupMenus(); |
3122 | 2986 |
3123 if (m_sessionFile == "") { | 2987 if (m_sessionFile == "") { |
3124 setWindowTitle(tr("Sonic Visualiser: %1") | 2988 setWindowTitle(tr("Sonic Visualiser: %1") |
3125 .arg(QFileInfo(location).fileName())); | 2989 .arg(source.getLocation())); |
3126 CommandHistory::getInstance()->clear(); | 2990 CommandHistory::getInstance()->clear(); |
3127 CommandHistory::getInstance()->documentSaved(); | 2991 CommandHistory::getInstance()->documentSaved(); |
3128 m_documentModified = false; | 2992 m_documentModified = false; |
3129 } else { | 2993 } else { |
3130 setWindowTitle(tr("Sonic Visualiser: %1 [%2]") | 2994 setWindowTitle(tr("Sonic Visualiser: %1 [%2]") |
3131 .arg(QFileInfo(m_sessionFile).fileName()) | 2995 .arg(QFileInfo(m_sessionFile).fileName()) |
3132 .arg(QFileInfo(location).fileName())); | 2996 .arg(source.getLocation())); |
3133 if (m_documentModified) { | 2997 if (m_documentModified) { |
3134 m_documentModified = false; | 2998 m_documentModified = false; |
3135 documentModified(); // so as to restore "(modified)" window title | 2999 documentModified(); // so as to restore "(modified)" window title |
3136 } | 3000 } |
3137 } | 3001 } |
3138 | 3002 |
3139 if (realFile) m_audioFile = path; | 3003 if (!source.isRemote()) m_audioFile = source.getLocalFilename(); |
3140 | 3004 |
3141 } else if (mode == CreateAdditionalModel) { | 3005 } else if (mode == CreateAdditionalModel) { |
3142 | 3006 |
3143 CommandHistory::getInstance()->startCompoundOperation | 3007 CommandHistory::getInstance()->startCompoundOperation |
3144 (tr("Import \"%1\"").arg(QFileInfo(location).fileName()), true); | 3008 (tr("Import \"%1\"").arg(source.getLocation()), true); |
3145 | 3009 |
3146 m_document->addImportedModel(newModel); | 3010 m_document->addImportedModel(newModel); |
3147 | 3011 |
3148 AddPaneCommand *command = new AddPaneCommand(this); | 3012 AddPaneCommand *command = new AddPaneCommand(this); |
3149 CommandHistory::getInstance()->addCommand(command); | 3013 CommandHistory::getInstance()->addCommand(command); |
3183 break; | 3047 break; |
3184 } | 3048 } |
3185 } | 3049 } |
3186 | 3050 |
3187 CommandHistory::getInstance()->startCompoundOperation | 3051 CommandHistory::getInstance()->startCompoundOperation |
3188 (tr("Import \"%1\"").arg(QFileInfo(location).fileName()), true); | 3052 (tr("Import \"%1\"").arg(source.getLocation()), true); |
3189 | 3053 |
3190 m_document->addImportedModel(newModel); | 3054 m_document->addImportedModel(newModel); |
3191 | 3055 |
3192 if (replace) { | 3056 if (replace) { |
3193 m_document->removeLayerFromView(pane, replace); | 3057 m_document->removeLayerFromView(pane, replace); |
3201 | 3065 |
3202 CommandHistory::getInstance()->endCompoundOperation(); | 3066 CommandHistory::getInstance()->endCompoundOperation(); |
3203 } | 3067 } |
3204 | 3068 |
3205 updateMenuStates(); | 3069 updateMenuStates(); |
3206 m_recentFiles.addFile(location); | 3070 m_recentFiles.addFile(source.getLocation()); |
3207 if (realFile) { | 3071 if (!source.isRemote()) { |
3208 registerLastOpenedFilePath(FileFinder::AudioFile, path); // for file dialog | 3072 // for file dialog |
3073 registerLastOpenedFilePath(FileFinder::AudioFile, | |
3074 source.getLocalFilename()); | |
3209 } | 3075 } |
3210 m_openingAudioFile = false; | 3076 m_openingAudioFile = false; |
3211 | 3077 |
3212 currentPaneChanged(m_paneStack->getCurrentPane()); | 3078 currentPaneChanged(m_paneStack->getCurrentPane()); |
3213 | 3079 |
3214 return FileOpenSucceeded; | 3080 return FileOpenSucceeded; |
3215 } | 3081 } |
3216 | 3082 |
3217 MainWindow::FileOpenStatus | 3083 MainWindow::FileOpenStatus |
3218 MainWindow::openPlaylistFile(QString path, AudioFileOpenMode mode) | 3084 MainWindow::openPlaylist(RemoteFile source, AudioFileOpenMode mode) |
3219 { | 3085 { |
3220 return openPlaylistFile(path, path, mode); | |
3221 } | |
3222 | |
3223 MainWindow::FileOpenStatus | |
3224 MainWindow::openPlaylistFile(QString path, QString location, AudioFileOpenMode mode) | |
3225 { | |
3226 if (!(QFileInfo(path).exists() && | |
3227 QFileInfo(path).isFile() && | |
3228 QFileInfo(path).isReadable())) { | |
3229 return FileOpenFailed; | |
3230 } | |
3231 | |
3232 std::set<QString> extensions; | 3086 std::set<QString> extensions; |
3233 PlaylistFileReader::getSupportedExtensions(extensions); | 3087 PlaylistFileReader::getSupportedExtensions(extensions); |
3234 QString extension = QFileInfo(path).suffix(); | 3088 QString extension = source.getExtension(); |
3235 if (extensions.find(extension) == extensions.end()) return FileOpenFailed; | 3089 if (extensions.find(extension) == extensions.end()) return FileOpenFailed; |
3236 | 3090 |
3237 PlaylistFileReader reader(path); | 3091 if (!source.isAvailable()) return FileOpenFailed; |
3092 source.waitForData(); | |
3093 | |
3094 PlaylistFileReader reader(source.getLocalFilename()); | |
3238 if (!reader.isOK()) return FileOpenFailed; | 3095 if (!reader.isOK()) return FileOpenFailed; |
3239 | 3096 |
3240 PlaylistFileReader::Playlist playlist = reader.load(); | 3097 PlaylistFileReader::Playlist playlist = reader.load(); |
3241 | 3098 |
3242 bool someSuccess = false; | 3099 bool someSuccess = false; |
3243 | 3100 |
3244 for (PlaylistFileReader::Playlist::const_iterator i = playlist.begin(); | 3101 for (PlaylistFileReader::Playlist::const_iterator i = playlist.begin(); |
3245 i != playlist.end(); ++i) { | 3102 i != playlist.end(); ++i) { |
3246 | 3103 |
3247 FileOpenStatus status = openURL(*i, mode); | 3104 FileOpenStatus status = openAudio(*i, mode); |
3248 | 3105 |
3249 if (status == FileOpenCancelled) { | 3106 if (status == FileOpenCancelled) { |
3250 return FileOpenCancelled; | 3107 return FileOpenCancelled; |
3251 } | 3108 } |
3252 | 3109 |
3256 } | 3113 } |
3257 } | 3114 } |
3258 | 3115 |
3259 if (someSuccess) return FileOpenSucceeded; | 3116 if (someSuccess) return FileOpenSucceeded; |
3260 else return FileOpenFailed; | 3117 else return FileOpenFailed; |
3118 } | |
3119 | |
3120 MainWindow::FileOpenStatus | |
3121 MainWindow::openLayer(RemoteFile source) | |
3122 { | |
3123 Pane *pane = m_paneStack->getCurrentPane(); | |
3124 | |
3125 if (!pane) { | |
3126 // shouldn't happen, as the menu action should have been disabled | |
3127 std::cerr << "WARNING: MainWindow::openLayer: no current pane" << std::endl; | |
3128 return FileOpenWrongMode; | |
3129 } | |
3130 | |
3131 if (!getMainModel()) { | |
3132 // shouldn't happen, as the menu action should have been disabled | |
3133 std::cerr << "WARNING: MainWindow::openLayer: No main model -- hence no default sample rate available" << std::endl; | |
3134 return FileOpenWrongMode; | |
3135 } | |
3136 | |
3137 if (!source.isAvailable()) return FileOpenFailed; | |
3138 source.waitForData(); | |
3139 | |
3140 QString path = source.getLocalFilename(); | |
3141 | |
3142 if (source.getExtension() == "svl" || source.getExtension() == "xml") { | |
3143 | |
3144 PaneCallback callback(this); | |
3145 QFile file(path); | |
3146 | |
3147 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { | |
3148 std::cerr << "ERROR: MainWindow::openLayer(" | |
3149 << source.getLocation().toStdString() | |
3150 << "): Failed to open file for reading" << std::endl; | |
3151 return FileOpenFailed; | |
3152 } | |
3153 | |
3154 SVFileReader reader(m_document, callback, source.getLocation()); | |
3155 reader.setCurrentPane(pane); | |
3156 | |
3157 QXmlInputSource inputSource(&file); | |
3158 reader.parse(inputSource); | |
3159 | |
3160 if (!reader.isOK()) { | |
3161 std::cerr << "ERROR: MainWindow::openLayer(" | |
3162 << source.getLocation().toStdString() | |
3163 << "): Failed to read XML file: " | |
3164 << reader.getErrorString().toStdString() << std::endl; | |
3165 return FileOpenFailed; | |
3166 } | |
3167 | |
3168 m_recentFiles.addFile(source.getLocation()); | |
3169 | |
3170 if (!source.isRemote()) { | |
3171 registerLastOpenedFilePath(FileFinder::LayerFile, path); // for file dialog | |
3172 } | |
3173 | |
3174 } else { | |
3175 | |
3176 try { | |
3177 | |
3178 Model *model = DataFileReaderFactory::load | |
3179 (path, getMainModel()->getSampleRate()); | |
3180 | |
3181 if (model) { | |
3182 | |
3183 Layer *newLayer = m_document->createImportedLayer(model); | |
3184 | |
3185 if (newLayer) { | |
3186 | |
3187 m_document->addLayerToView(pane, newLayer); | |
3188 m_recentFiles.addFile(source.getLocation()); | |
3189 | |
3190 if (!source.isRemote()) { | |
3191 registerLastOpenedFilePath | |
3192 (FileFinder::LayerFile, | |
3193 path); // for file dialog | |
3194 } | |
3195 | |
3196 return FileOpenSucceeded; | |
3197 } | |
3198 } | |
3199 } catch (DataFileReaderFactory::Exception e) { | |
3200 if (e == DataFileReaderFactory::ImportCancelled) { | |
3201 return FileOpenCancelled; | |
3202 } | |
3203 } | |
3204 } | |
3205 | |
3206 source.setLeaveLocalFile(true); | |
3207 return FileOpenFailed; | |
3208 } | |
3209 | |
3210 MainWindow::FileOpenStatus | |
3211 MainWindow::openImage(RemoteFile source) | |
3212 { | |
3213 Pane *pane = m_paneStack->getCurrentPane(); | |
3214 | |
3215 if (!pane) { | |
3216 // shouldn't happen, as the menu action should have been disabled | |
3217 std::cerr << "WARNING: MainWindow::openImage: no current pane" << std::endl; | |
3218 return FileOpenWrongMode; | |
3219 } | |
3220 | |
3221 if (!m_document->getMainModel()) { | |
3222 return FileOpenWrongMode; | |
3223 } | |
3224 | |
3225 bool newLayer = false; | |
3226 | |
3227 ImageLayer *il = dynamic_cast<ImageLayer *>(pane->getSelectedLayer()); | |
3228 if (!il) { | |
3229 for (int i = pane->getLayerCount()-1; i >= 0; --i) { | |
3230 il = dynamic_cast<ImageLayer *>(pane->getLayer(i)); | |
3231 if (il) break; | |
3232 } | |
3233 } | |
3234 if (!il) { | |
3235 il = dynamic_cast<ImageLayer *> | |
3236 (m_document->createEmptyLayer(LayerFactory::Image)); | |
3237 if (!il) return FileOpenFailed; | |
3238 newLayer = true; | |
3239 } | |
3240 | |
3241 // We don't put the image file in Recent Files | |
3242 | |
3243 std::cerr << "openImage: trying location \"" << source.getLocation().toStdString() << "\" in image layer" << std::endl; | |
3244 | |
3245 if (!il->addImage(m_viewManager->getGlobalCentreFrame(), source.getLocation())) { | |
3246 if (newLayer) { | |
3247 m_document->setModel(il, 0); // releasing its model | |
3248 delete il; | |
3249 } | |
3250 return FileOpenFailed; | |
3251 } else { | |
3252 if (newLayer) { | |
3253 m_document->addLayerToView(pane, il); | |
3254 } | |
3255 m_paneStack->setCurrentLayer(pane, il); | |
3256 } | |
3257 | |
3258 return FileOpenSucceeded; | |
3259 } | |
3260 | |
3261 MainWindow::FileOpenStatus | |
3262 MainWindow::openSession(RemoteFile source) | |
3263 { | |
3264 if (!source.isAvailable()) return FileOpenFailed; | |
3265 if (source.getExtension() != "sv") return FileOpenFailed; | |
3266 source.waitForData(); | |
3267 | |
3268 BZipFileDevice bzFile(source.getLocalFilename()); | |
3269 if (!bzFile.open(QIODevice::ReadOnly)) return FileOpenFailed; | |
3270 | |
3271 if (!checkSaveModified()) return FileOpenCancelled; | |
3272 | |
3273 QString error; | |
3274 closeSession(); | |
3275 createDocument(); | |
3276 | |
3277 PaneCallback callback(this); | |
3278 m_viewManager->clearSelections(); | |
3279 | |
3280 SVFileReader reader(m_document, callback, source.getLocation()); | |
3281 QXmlInputSource inputSource(&bzFile); | |
3282 reader.parse(inputSource); | |
3283 | |
3284 if (!reader.isOK()) { | |
3285 error = tr("SV XML file read error:\n%1").arg(reader.getErrorString()); | |
3286 } | |
3287 | |
3288 bzFile.close(); | |
3289 | |
3290 bool ok = (error == ""); | |
3291 | |
3292 if (ok) { | |
3293 | |
3294 setWindowTitle(tr("Sonic Visualiser: %1") | |
3295 .arg(source.getLocation())); | |
3296 | |
3297 if (!source.isRemote()) m_sessionFile = source.getLocalFilename(); | |
3298 | |
3299 setupMenus(); | |
3300 CommandHistory::getInstance()->clear(); | |
3301 CommandHistory::getInstance()->documentSaved(); | |
3302 m_documentModified = false; | |
3303 updateMenuStates(); | |
3304 | |
3305 m_recentFiles.addFile(source.getLocation()); | |
3306 | |
3307 if (!source.isRemote()) { | |
3308 // for file dialog | |
3309 registerLastOpenedFilePath(FileFinder::SessionFile, | |
3310 source.getLocalFilename()); | |
3311 } | |
3312 | |
3313 } else { | |
3314 setWindowTitle(tr("Sonic Visualiser")); | |
3315 } | |
3316 | |
3317 return ok ? FileOpenSucceeded : FileOpenFailed; | |
3261 } | 3318 } |
3262 | 3319 |
3263 void | 3320 void |
3264 MainWindow::createPlayTarget() | 3321 MainWindow::createPlayTarget() |
3265 { | 3322 { |
3404 | 3461 |
3405 QString path = getOpenFileName(FileFinder::SessionFile); | 3462 QString path = getOpenFileName(FileFinder::SessionFile); |
3406 | 3463 |
3407 if (path.isEmpty()) return; | 3464 if (path.isEmpty()) return; |
3408 | 3465 |
3409 if (openSessionFile(path) == FileOpenFailed) { | 3466 if (openSession(path) == FileOpenFailed) { |
3410 QMessageBox::critical(this, tr("Failed to open file"), | 3467 QMessageBox::critical(this, tr("Failed to open file"), |
3411 tr("<b>File open failed</b><p>Session file \"%1\" could not be opened").arg(path)); | 3468 tr("<b>File open failed</b><p>Session file \"%1\" could not be opened").arg(path)); |
3412 } | 3469 } |
3413 } | 3470 } |
3414 | 3471 |
3421 | 3478 |
3422 QString path = getOpenFileName(FileFinder::AnyFile); | 3479 QString path = getOpenFileName(FileFinder::AnyFile); |
3423 | 3480 |
3424 if (path.isEmpty()) return; | 3481 if (path.isEmpty()) return; |
3425 | 3482 |
3426 FileOpenStatus status = openSomeFile(path, AskUser); | 3483 FileOpenStatus status = open(path, AskUser); |
3427 | 3484 |
3428 if (status == FileOpenFailed) { | 3485 if (status == FileOpenFailed) { |
3429 QMessageBox::critical(this, tr("Failed to open file"), | 3486 QMessageBox::critical(this, tr("Failed to open file"), |
3430 tr("<b>File open failed</b><p>File \"%1\" could not be opened").arg(path)); | 3487 tr("<b>File open failed</b><p>File \"%1\" could not be opened").arg(path)); |
3431 } else if (status == FileOpenWrongMode) { | 3488 } else if (status == FileOpenWrongMode) { |
3451 | 3508 |
3452 settings.setValue("lastremote", text); | 3509 settings.setValue("lastremote", text); |
3453 | 3510 |
3454 if (text.isEmpty()) return; | 3511 if (text.isEmpty()) return; |
3455 | 3512 |
3456 FileOpenStatus status = openURL(QUrl(text)); | 3513 FileOpenStatus status = open(text); |
3457 | 3514 |
3458 if (status == FileOpenFailed) { | 3515 if (status == FileOpenFailed) { |
3459 QMessageBox::critical(this, tr("Failed to open location"), | 3516 QMessageBox::critical(this, tr("Failed to open location"), |
3460 tr("<b>Open failed</b><p>URL \"%1\" could not be opened").arg(text)); | 3517 tr("<b>Open failed</b><p>URL \"%1\" could not be opened").arg(text)); |
3461 } else if (status == FileOpenWrongMode) { | 3518 } else if (status == FileOpenWrongMode) { |
3477 } | 3534 } |
3478 | 3535 |
3479 QString path = action->text(); | 3536 QString path = action->text(); |
3480 if (path == "") return; | 3537 if (path == "") return; |
3481 | 3538 |
3482 FileOpenStatus status = openURL(path); | 3539 FileOpenStatus status = open(path); |
3483 | 3540 |
3484 if (status == FileOpenFailed) { | 3541 if (status == FileOpenFailed) { |
3485 QMessageBox::critical(this, tr("Failed to open location"), | 3542 QMessageBox::critical(this, tr("Failed to open location"), |
3486 tr("<b>Open failed</b><p>File or URL \"%1\" could not be opened").arg(path)); | 3543 tr("<b>Open failed</b><p>File or URL \"%1\" could not be opened").arg(path)); |
3487 } else if (status == FileOpenWrongMode) { | 3544 } else if (status == FileOpenWrongMode) { |
3488 QMessageBox::critical(this, tr("Failed to open location"), | 3545 QMessageBox::critical(this, tr("Failed to open location"), |
3489 tr("<b>Audio required</b><p>Please load at least one audio file before importing annotation data")); | 3546 tr("<b>Audio required</b><p>Please load at least one audio file before importing annotation data")); |
3490 } | 3547 } |
3491 } | 3548 } |
3492 | 3549 |
3493 MainWindow::FileOpenStatus | |
3494 MainWindow::openURL(QUrl url, AudioFileOpenMode mode) | |
3495 { | |
3496 if (url.scheme().toLower() == "file" || url.scheme() == "") { | |
3497 | |
3498 return openSomeFile(url.toLocalFile(), mode); | |
3499 | |
3500 } else if (!RemoteFile::canHandleScheme(url)) { | |
3501 | |
3502 QMessageBox::critical(this, tr("Unsupported scheme in URL"), | |
3503 tr("<b>Download failed</b><p>The URL scheme \"%1\" is not supported") | |
3504 .arg(url.scheme())); | |
3505 return FileOpenFailed; | |
3506 | |
3507 } else { | |
3508 RemoteFile rf(url); | |
3509 rf.wait(); | |
3510 if (!rf.isOK()) { | |
3511 QMessageBox::critical(this, tr("File download failed"), | |
3512 tr("<b>Download failed</b><p>Failed to download URL \"%1\": %2") | |
3513 .arg(url.toString()).arg(rf.getErrorString())); | |
3514 return FileOpenFailed; | |
3515 } | |
3516 FileOpenStatus status; | |
3517 if ((status = openSomeFile(rf.getLocalFilename(), url.toString(), | |
3518 mode)) != | |
3519 FileOpenSucceeded) { | |
3520 rf.deleteLocalFile(); | |
3521 } | |
3522 return status; | |
3523 } | |
3524 } | |
3525 | |
3526 MainWindow::FileOpenStatus | |
3527 MainWindow::openURL(QString ustr, AudioFileOpenMode mode) | |
3528 { | |
3529 // This function is used when we don't know whether the string is | |
3530 // an encoded or human-readable url | |
3531 | |
3532 QUrl url(ustr); | |
3533 | |
3534 if (url.scheme().toLower() == "file" || url.scheme() == "") { | |
3535 | |
3536 FileOpenStatus status = openSomeFile(url.toLocalFile(), mode); | |
3537 if (status == FileOpenFailed) { | |
3538 url.setEncodedUrl(ustr.toAscii()); | |
3539 status = openSomeFile(url.toLocalFile(), mode); | |
3540 } | |
3541 return status; | |
3542 | |
3543 } else if (!RemoteFile::canHandleScheme(url)) { | |
3544 | |
3545 QMessageBox::critical(this, tr("Unsupported scheme in URL"), | |
3546 tr("<b>Download failed</b><p>The URL scheme \"%1\" is not supported") | |
3547 .arg(url.scheme())); | |
3548 return FileOpenFailed; | |
3549 | |
3550 } else { | |
3551 RemoteFile rf(url); | |
3552 rf.wait(); | |
3553 if (!rf.isOK()) { | |
3554 // rf was created on the assumption that ustr was | |
3555 // human-readable. Let's try again, this time assuming it | |
3556 // was already encoded. | |
3557 std::cerr << "MainWindow::openURL: Failed to retrieve URL \"" | |
3558 << ustr.toStdString() << "\" as human-readable URL; " | |
3559 << "trying again treating it as encoded URL" | |
3560 << std::endl; | |
3561 url.setEncodedUrl(ustr.toAscii()); | |
3562 return openURL(url, mode); | |
3563 } | |
3564 | |
3565 FileOpenStatus status; | |
3566 if ((status = openSomeFile(rf.getLocalFilename(), ustr, mode)) != | |
3567 FileOpenSucceeded) { | |
3568 rf.deleteLocalFile(); | |
3569 } | |
3570 return status; | |
3571 } | |
3572 } | |
3573 | |
3574 MainWindow::FileOpenStatus | |
3575 MainWindow::openSomeFile(QString path, AudioFileOpenMode mode) | |
3576 { | |
3577 return openSomeFile(path, path, mode); | |
3578 } | |
3579 | |
3580 MainWindow::FileOpenStatus | |
3581 MainWindow::openSomeFile(QString path, QString location, | |
3582 AudioFileOpenMode mode) | |
3583 { | |
3584 FileOpenStatus status; | |
3585 | |
3586 bool canImportLayer = (getMainModel() != 0 && | |
3587 m_paneStack != 0 && | |
3588 m_paneStack->getCurrentPane() != 0); | |
3589 | |
3590 if ((status = openPlaylistFile(path, location, mode)) != FileOpenFailed) { | |
3591 return status; | |
3592 } else if ((status = openAudioFile(path, location, mode)) != FileOpenFailed) { | |
3593 return status; | |
3594 } else if (QFileInfo(path).suffix().toLower() == "sv" && | |
3595 (status = openSessionFile(path, location)) != FileOpenFailed) { | |
3596 return status; | |
3597 } else if (!canImportLayer) { | |
3598 return FileOpenWrongMode; | |
3599 } else if ((status = openImageFile(path, location)) != FileOpenFailed) { | |
3600 return status; | |
3601 } else if ((status = openLayerFile(path, location)) != FileOpenFailed) { | |
3602 return status; | |
3603 } else { | |
3604 return FileOpenFailed; | |
3605 } | |
3606 } | |
3607 | |
3608 MainWindow::FileOpenStatus | |
3609 MainWindow::openSessionFile(QString path) | |
3610 { | |
3611 return openSessionFile(path, path); | |
3612 } | |
3613 | |
3614 MainWindow::FileOpenStatus | |
3615 MainWindow::openSessionFile(QString path, QString location) | |
3616 { | |
3617 BZipFileDevice bzFile(path); | |
3618 if (!bzFile.open(QIODevice::ReadOnly)) { | |
3619 std::cerr << "Failed to open session file \"" << location.toStdString() | |
3620 << "\": " << bzFile.errorString().toStdString() << std::endl; | |
3621 return FileOpenFailed; | |
3622 } | |
3623 | |
3624 if (!checkSaveModified()) return FileOpenCancelled; | |
3625 | |
3626 QString error; | |
3627 closeSession(); | |
3628 createDocument(); | |
3629 | |
3630 PaneCallback callback(this); | |
3631 m_viewManager->clearSelections(); | |
3632 | |
3633 SVFileReader reader(m_document, callback, location); | |
3634 QXmlInputSource inputSource(&bzFile); | |
3635 reader.parse(inputSource); | |
3636 | |
3637 if (!reader.isOK()) { | |
3638 error = tr("SV XML file read error:\n%1").arg(reader.getErrorString()); | |
3639 } | |
3640 | |
3641 bzFile.close(); | |
3642 | |
3643 bool ok = (error == ""); | |
3644 | |
3645 bool realFile = (location == path); | |
3646 | |
3647 if (ok) { | |
3648 | |
3649 setWindowTitle(tr("Sonic Visualiser: %1") | |
3650 .arg(QFileInfo(location).fileName())); | |
3651 | |
3652 if (realFile) m_sessionFile = path; | |
3653 | |
3654 setupMenus(); | |
3655 CommandHistory::getInstance()->clear(); | |
3656 CommandHistory::getInstance()->documentSaved(); | |
3657 m_documentModified = false; | |
3658 updateMenuStates(); | |
3659 | |
3660 m_recentFiles.addFile(location); | |
3661 | |
3662 if (realFile) { | |
3663 registerLastOpenedFilePath(FileFinder::SessionFile, path); // for file dialog | |
3664 } | |
3665 | |
3666 } else { | |
3667 setWindowTitle(tr("Sonic Visualiser")); | |
3668 } | |
3669 | |
3670 return ok ? FileOpenSucceeded : FileOpenFailed; | |
3671 } | |
3672 | |
3673 void | 3550 void |
3674 MainWindow::paneDropAccepted(Pane *pane, QStringList uriList) | 3551 MainWindow::paneDropAccepted(Pane *pane, QStringList uriList) |
3675 { | 3552 { |
3676 if (pane) m_paneStack->setCurrentPane(pane); | 3553 if (pane) m_paneStack->setCurrentPane(pane); |
3677 | 3554 |
3678 for (QStringList::iterator i = uriList.begin(); i != uriList.end(); ++i) { | 3555 for (QStringList::iterator i = uriList.begin(); i != uriList.end(); ++i) { |
3679 | 3556 |
3680 FileOpenStatus status = openURL(*i, ReplaceCurrentPane); | 3557 FileOpenStatus status = open(*i, ReplaceCurrentPane); |
3681 | 3558 |
3682 if (status == FileOpenFailed) { | 3559 if (status == FileOpenFailed) { |
3683 QMessageBox::critical(this, tr("Failed to open dropped URL"), | 3560 QMessageBox::critical(this, tr("Failed to open dropped URL"), |
3684 tr("<b>Open failed</b><p>Dropped URL \"%1\" could not be opened").arg(*i)); | 3561 tr("<b>Open failed</b><p>Dropped URL \"%1\" could not be opened").arg(*i)); |
3685 } else if (status == FileOpenWrongMode) { | 3562 } else if (status == FileOpenWrongMode) { |
5055 if (message.getMethod() == "open") { | 4932 if (message.getMethod() == "open") { |
5056 | 4933 |
5057 if (message.getArgCount() == 1 && | 4934 if (message.getArgCount() == 1 && |
5058 message.getArg(0).canConvert(QVariant::String)) { | 4935 message.getArg(0).canConvert(QVariant::String)) { |
5059 QString path = message.getArg(0).toString(); | 4936 QString path = message.getArg(0).toString(); |
5060 if (openSomeFile(path, ReplaceMainModel) != FileOpenSucceeded) { | 4937 if (open(path, ReplaceMainModel) != FileOpenSucceeded) { |
5061 std::cerr << "MainWindow::handleOSCMessage: File open failed for path \"" | 4938 std::cerr << "MainWindow::handleOSCMessage: File open failed for path \"" |
5062 << path.toStdString() << "\"" << std::endl; | 4939 << path.toStdString() << "\"" << std::endl; |
5063 } | 4940 } |
5064 //!!! we really need to spin here and not return until the | 4941 //!!! we really need to spin here and not return until the |
5065 // file has been completely decoded... | 4942 // file has been completely decoded... |
5068 } else if (message.getMethod() == "openadditional") { | 4945 } else if (message.getMethod() == "openadditional") { |
5069 | 4946 |
5070 if (message.getArgCount() == 1 && | 4947 if (message.getArgCount() == 1 && |
5071 message.getArg(0).canConvert(QVariant::String)) { | 4948 message.getArg(0).canConvert(QVariant::String)) { |
5072 QString path = message.getArg(0).toString(); | 4949 QString path = message.getArg(0).toString(); |
5073 if (openSomeFile(path, CreateAdditionalModel) != FileOpenSucceeded) { | 4950 if (open(path, CreateAdditionalModel) != FileOpenSucceeded) { |
5074 std::cerr << "MainWindow::handleOSCMessage: File open failed for path \"" | 4951 std::cerr << "MainWindow::handleOSCMessage: File open failed for path \"" |
5075 << path.toStdString() << "\"" << std::endl; | 4952 << path.toStdString() << "\"" << std::endl; |
5076 } | 4953 } |
5077 } | 4954 } |
5078 | 4955 |
5085 message.getArg(0).canConvert(QVariant::Int)) { | 4962 message.getArg(0).canConvert(QVariant::Int)) { |
5086 n = message.getArg(0).toInt() - 1; | 4963 n = message.getArg(0).toInt() - 1; |
5087 } | 4964 } |
5088 std::vector<QString> recent = m_recentFiles.getRecent(); | 4965 std::vector<QString> recent = m_recentFiles.getRecent(); |
5089 if (n >= 0 && n < int(recent.size())) { | 4966 if (n >= 0 && n < int(recent.size())) { |
5090 if (openSomeFile(recent[n], ReplaceMainModel) != FileOpenSucceeded) { | 4967 if (open(recent[n], ReplaceMainModel) != FileOpenSucceeded) { |
5091 std::cerr << "MainWindow::handleOSCMessage: File open failed for path \"" | 4968 std::cerr << "MainWindow::handleOSCMessage: File open failed for path \"" |
5092 << recent[n].toStdString() << "\"" << std::endl; | 4969 << recent[n].toStdString() << "\"" << std::endl; |
5093 } | 4970 } |
5094 } | 4971 } |
5095 | 4972 |