diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 425086bb9..4233b2af3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -619,6 +619,7 @@ list( APPEND SOURCES # Standard importers + import/ImportAUP.cpp import/ImportLOF.cpp import/ImportPCM.cpp import/ImportPlugin.h diff --git a/src/ProjectFileManager.cpp b/src/ProjectFileManager.cpp index 4a9176ca5..38c6bd8f0 100644 --- a/src/ProjectFileManager.cpp +++ b/src/ProjectFileManager.cpp @@ -337,7 +337,7 @@ bool ProjectFileManager::DoSave(const FilePath & fileName, const bool fromSaveAs // This version of SaveAs is invoked only from scripting and does not // prompt for a file name -bool ProjectFileManager::SaveAs(const wxString & newFileName, bool addToHistory /*= true*/) +bool ProjectFileManager::SaveAs(const FilePath &newFileName, bool addToHistory /*= true*/) { auto &project = mProject; auto &projectFileIO = ProjectFileIO::Get( project ); @@ -401,93 +401,101 @@ For an audio file that will open in other apps, use 'Export'.\n"); bool bPrompt = (project.mBatchMode == 0) || (projectFileIO.GetFileName().empty()); FilePath fName; + bool bOwnsNewName; - if (bPrompt) { - // JKC: I removed 'wxFD_OVERWRITE_PROMPT' because we are checking - // for overwrite ourselves later, and we disallow it. - // We disallow overwrite because we would have to DELETE the many - // smaller files too, or prompt to move them. - fName = FileNames::SelectFile(FileNames::Operation::Export, - title, - filename.GetPath(), - filename.GetFullName(), - wxT("aup3"), - { FileNames::AudacityProjects }, - wxFD_SAVE | wxRESIZE_BORDER, - &window); - - if (fName.empty()) - return false; - - filename = fName; - }; - - filename.SetExt(wxT("aup3")); - fName = filename.GetFullPath(); - - if (bPrompt && filename.FileExists()) { - // Saving a copy of the project should never overwrite an existing project. - AudacityMessageDialog m( - nullptr, - XO("Saving a copy must not overwrite an existing saved project.\nPlease try again and select an original name."), - XO("Error Saving Copy of Project"), - wxOK|wxICON_ERROR ); - m.ShowModal(); - return false; - } - - bool bOwnsNewName = !projectFileIO.IsTemporary() && ( projectFileIO.GetFileName() == fName ); - // Check to see if the project file already exists, and if it does - // check that the project file 'belongs' to this project. - // otherwise, prompt the user before overwriting. - if (!bOwnsNewName && filename.FileExists()) { - // Ensure that project of same name is not open in another window. - // fName is the destination file. - // mFileName is this project. - // It is possible for mFileName == fName even when this project is not - // saved to disk, and we then need to check the destination file is not - // open in another window. - int mayOverwrite = ( projectFileIO.GetFileName() == fName ) ? 2 : 1; - for ( auto p : AllProjects{} ) { - const wxFileName openProjectName{ ProjectFileIO::Get(*p).GetFileName() }; - if (openProjectName.SameAs(fName)) { - mayOverwrite -= 1; - if (mayOverwrite == 0) - break; - } - } - - if (mayOverwrite > 0) { - /* i18n-hint: In each case, %s is the name - of the file being overwritten.*/ - auto Message = XO("\ -Do you want to overwrite the project:\n\"%s\"?\n\n\ -If you select \"Yes\" the project\n\"%s\"\n\ -will be irreversibly overwritten.").Format( fName, fName ); - - // For safety, there should NOT be an option to hide this warning. - int result = AudacityMessageBox( - Message, - /* i18n-hint: Heading: A warning that a project is about to be overwritten.*/ - XO("Overwrite Project Warning"), - wxYES_NO | wxNO_DEFAULT | wxICON_WARNING, + do { + if (bPrompt) { + // JKC: I removed 'wxFD_OVERWRITE_PROMPT' because we are checking + // for overwrite ourselves later, and we disallow it. + fName = FileNames::SelectFile(FileNames::Operation::Export, + title, + filename.GetPath(), + filename.GetFullName(), + wxT("aup3"), + { FileNames::AudacityProjects }, + wxFD_SAVE | wxRESIZE_BORDER, &window); - if (result != wxYES) { + + if (fName.empty()) return false; - } - } - else - { - // Overwrite disallowed. The destination project is open in another window. + + filename = fName; + }; + + filename.SetExt(wxT("aup3")); + + if (!bPrompt && filename.FileExists()) { + // Saving a copy of the project should never overwrite an existing project. AudacityMessageDialog m( nullptr, - XO("The project was not saved because the selected project is open in another window.\nPlease try again and select an original name."), + XO("The project was not saved because the file name provided would overwrite another project.\nPlease try again and select an original name."), XO("Error Saving Project"), wxOK|wxICON_ERROR ); m.ShowModal(); return false; } - } + + fName = filename.GetFullPath(); + + bOwnsNewName = !projectFileIO.IsTemporary() && ( projectFileIO.GetFileName() == fName ); + // Check to see if the project file already exists, and if it does + // check that the project file 'belongs' to this project. + // otherwise, prompt the user before overwriting. + if (!bOwnsNewName && filename.FileExists()) { + // Ensure that project of same name is not open in another window. + // fName is the destination file. + // mFileName is this project. + // It is possible for mFileName == fName even when this project is not + // saved to disk, and we then need to check the destination file is not + // open in another window. + int mayOverwrite = ( projectFileIO.GetFileName() == fName ) ? 2 : 1; + for ( auto p : AllProjects{} ) { + const wxFileName openProjectName{ ProjectFileIO::Get(*p).GetFileName() }; + if (openProjectName.SameAs(fName)) { + mayOverwrite -= 1; + if (mayOverwrite == 0) + break; + } + } + + if (mayOverwrite > 0) { + /* i18n-hint: In each case, %s is the name + of the file being overwritten.*/ + auto Message = XO("\ + Do you want to overwrite the project:\n\"%s\"?\n\n\ + If you select \"Yes\" the project\n\"%s\"\n\ + will be irreversibly overwritten.").Format( fName, fName ); + + // For safety, there should NOT be an option to hide this warning. + int result = AudacityMessageBox( + Message, + /* i18n-hint: Heading: A warning that a project is about to be overwritten.*/ + XO("Overwrite Project Warning"), + wxYES_NO | wxNO_DEFAULT | wxICON_WARNING, + &window); + if (result == wxNO) { + continue; + } + if (result == wxCANCEL) { + return false; + } + } + else + { + // Overwrite disallowed. The destination project is open in another window. + AudacityMessageDialog m( + nullptr, + XO("The project was not saved because the selected project is open in another window.\nPlease try again and select an original name."), + XO("Error Saving Project"), + wxOK|wxICON_ERROR ); + m.ShowModal(); + continue; + } + } + + break; + } while (bPrompt); + auto success = DoSave(fName, !bOwnsNewName); if (success) { @@ -502,21 +510,25 @@ will be irreversibly overwritten.").Format( fName, fName ); return(success); } -bool ProjectFileManager::SaveCopy() +bool ProjectFileManager::SaveCopy(const FilePath &fileName /* = wxT("") */) { auto &project = mProject; auto &projectFileIO = ProjectFileIO::Get(project); auto &window = GetProjectFrame(project); TitleRestorer Restorer(window, project); // RAII - wxFileName filename; + wxFileName filename = fileName; - if (projectFileIO.IsTemporary()) + if (fileName.empty()) { - filename = FileNames::DefaultToDocumentsFolder(wxT("/SaveAs/Path")); - } - else - { - filename = projectFileIO.GetFileName(); + if (projectFileIO.IsTemporary()) + { + filename = FileNames::DefaultToDocumentsFolder(wxT("/SaveAs/Path")); + } + else + { + filename = projectFileIO.GetFileName(); + filename.SetFullName(wxT("")); + } } // Bug 1304: Set a default file path if none was given. For Save/SaveAs/SaveCopy @@ -526,7 +538,8 @@ bool ProjectFileManager::SaveCopy() } TranslatableString title = - XO("%sSave Copy of Project \"%s\" As...").Format(Restorer.sProjNumber, Restorer.sProjName); + XO("%sSave Copy of Project \"%s\" As...") + .Format(Restorer.sProjNumber, Restorer.sProjName); bool bPrompt = (project.mBatchMode == 0) || (projectFileIO.GetFileName().empty()); FilePath fName; @@ -557,9 +570,8 @@ bool ProjectFileManager::SaveCopy() }; filename.SetExt(wxT("aup3")); - fName = filename.GetFullPath(); - if (bPrompt && filename.FileExists()) + if (filename.FileExists()) { // Saving a copy of the project should never overwrite an existing project. AudacityMessageDialog m(nullptr, @@ -568,9 +580,15 @@ bool ProjectFileManager::SaveCopy() wxOK | wxICON_ERROR); m.ShowModal(); + if (!project.mBatchMode == 0) + { + return false; + } + continue; } + fName = filename.GetFullPath(); break; } while (bPrompt); @@ -582,7 +600,9 @@ bool ProjectFileManager::SaveCopy() XO("The project will not saved because the selected project is open in another window.\nPlease try again and select an original name."), XO("Error Saving Project"), wxOK | wxICON_ERROR); + m.ShowModal(); + return false; } diff --git a/src/ProjectFileManager.h b/src/ProjectFileManager.h index 8670eec96..bbfc13f4f 100644 --- a/src/ProjectFileManager.h +++ b/src/ProjectFileManager.h @@ -56,10 +56,10 @@ public: bool Save(); bool SaveAs(); - bool SaveAs(const wxString & newFileName, bool addToHistory = true); + bool SaveAs(const FilePath &newFileName, bool addToHistory = true); // strProjectPathName is full path for aup except extension bool SaveFromTimerRecording( wxFileName fnFile ); - bool SaveCopy(); + bool SaveCopy(const FilePath &fileName = wxT("")); void Reset(); diff --git a/src/commands/OpenSaveCommands.cpp b/src/commands/OpenSaveCommands.cpp index 39ff35bd8..fbaab47a0 100644 --- a/src/commands/OpenSaveCommands.cpp +++ b/src/commands/OpenSaveCommands.cpp @@ -105,3 +105,30 @@ bool SaveProjectCommand::Apply(const CommandContext &context) else return projectFileManager.SaveAs(mFileName, mbAddToHistory); } + +const ComponentInterfaceSymbol SaveCopyCommand::Symbol +{ XO("Save Copy") }; + +namespace{ BuiltinCommandsModule::Registration< SaveCopyCommand > reg3; } + +bool SaveCopyCommand::DefineParams( ShuttleParams & S ){ + S.Define( mFileName, wxT("Filename"), "name.aup" ); + return true; +} + +void SaveCopyCommand::PopulateOrExchange(ShuttleGui & S) +{ + S.AddSpace(0, 5); + + S.StartMultiColumn(2, wxALIGN_CENTER); + { + S.TieTextBox(XXO("File Name:"),mFileName); + } + S.EndMultiColumn(); +} + +bool SaveCopyCommand::Apply(const CommandContext &context) +{ + auto &projectFileManager = ProjectFileManager::Get( context.project ); + return projectFileManager.SaveCopy(mFileName); +} diff --git a/src/commands/OpenSaveCommands.h b/src/commands/OpenSaveCommands.h index b10c92623..ee869787a 100644 --- a/src/commands/OpenSaveCommands.h +++ b/src/commands/OpenSaveCommands.h @@ -16,6 +16,9 @@ \class SaveProjectCommand \brief Command for saving an Audacity project +\class SaveCopyCommand +\brief Command for saving a copy of currenty project + *//*******************************************************************/ #include "Command.h" @@ -60,3 +63,21 @@ public: bool mbAddToHistory; bool bHasAddToHistory; }; + +class SaveCopyCommand : public AudacityCommand +{ +public: + static const ComponentInterfaceSymbol Symbol; + + // ComponentInterface overrides + ComponentInterfaceSymbol GetSymbol() override {return Symbol;}; + TranslatableString GetDescription() override {return XO("Saves a copy of current project.");}; + bool DefineParams( ShuttleParams & S ) override; + void PopulateOrExchange(ShuttleGui & S) override; + bool Apply(const CommandContext & context) override; + + // AudacityCommand overrides + wxString ManualPage() override {return wxT("Extra_Menu:_Scriptables_II#save_copy");}; +public: + wxString mFileName; +};