mirror of
https://github.com/cookiengineer/audacity
synced 2026-03-24 15:15:52 +01:00
Bug2764: Open Project... in Scriptables shouldn't corrupt project...
... Now new project windows are opened when .aup3 files are opened; but behavior chages only in that case. Wherever opening of other files invoked import code, we still do or do not make a new project in exactly the same cases as before; such as, when opening multiple files with File > Open, be sure each imported file still opens in its own separate window. This means the decision whether to open a new project must be lowered into ProjectFileManager, where the type of the file is discovered, and we pass it a function object so it avoids a dependency cycle with ProjectManager. It also means the checking for errors and closing of new projects in case of failure must be replicated at all places where ProjectFileManager::OpenProject is called directly. The class ProjectManager::ProjectChooser simplifies this. Recently introduced calls to SafeToOpenProjectInto(), before ProjectManager::OpenProject(), are now lowered into that class, delaying the safety check so it might also be called where ProjectFileManager is used directly.
This commit is contained in:
@@ -842,9 +842,12 @@ void ProjectManager::OnOpenAudioFile(wxCommandEvent & event)
|
||||
{
|
||||
const wxString &cmd = event.GetString();
|
||||
if (!cmd.empty()) {
|
||||
if (auto project = ProjectFileManager::Get( mProject ).OpenFile(cmd)) {
|
||||
ProjectChooser chooser{ &mProject, true };
|
||||
if (auto project = ProjectFileManager::OpenFile(
|
||||
std::ref(chooser), cmd)) {
|
||||
auto &window = GetProjectFrame( *project );
|
||||
window.RequestUserAttention();
|
||||
chooser.Commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -871,8 +874,6 @@ void ProjectManager::OpenFiles(AudacityProject *proj)
|
||||
if (ProjectFileManager::IsAlreadyOpen(fileName))
|
||||
continue; // Skip ones that are already open.
|
||||
|
||||
if (proj && !SafeToOpenProjectInto(*proj))
|
||||
proj = nullptr;
|
||||
proj = OpenProject( proj, fileName,
|
||||
true /* addtohistory */, false /* reuseNonemptyProject */ );
|
||||
}
|
||||
@@ -901,39 +902,60 @@ bool ProjectManager::SafeToOpenProjectInto(AudacityProject &proj)
|
||||
return true;
|
||||
}
|
||||
|
||||
AudacityProject *ProjectManager::OpenProject(
|
||||
AudacityProject *pProject, const FilePath &fileNameArg,
|
||||
bool addtohistory, bool)
|
||||
ProjectManager::ProjectChooser::~ProjectChooser()
|
||||
{
|
||||
bool success = false;
|
||||
AudacityProject *pNewProject = nullptr;
|
||||
if ( ! pProject )
|
||||
pProject = pNewProject = New();
|
||||
auto cleanup = finally( [&] {
|
||||
if ( pNewProject )
|
||||
GetProjectFrame( *pNewProject ).Close(true);
|
||||
else if ( !success )
|
||||
if (mpUsedProject) {
|
||||
if (mpUsedProject == mpGivenProject) {
|
||||
// Ensure that it happens here: don't wait for the application level
|
||||
// exception handler, because the exception may be intercepted
|
||||
ProjectHistory::Get(*pProject).RollbackState();
|
||||
ProjectHistory::Get(*mpGivenProject).RollbackState();
|
||||
// Any exception now continues propagating
|
||||
} );
|
||||
ProjectFileManager::Get( *pProject ).OpenFile( fileNameArg, addtohistory );
|
||||
|
||||
// The above didn't throw, so change what finally will do
|
||||
success = true;
|
||||
pNewProject = nullptr;
|
||||
|
||||
auto &projectFileIO = ProjectFileIO::Get( *pProject );
|
||||
if( projectFileIO.IsRecovered() ) {
|
||||
auto &window = ProjectWindow::Get( *pProject );
|
||||
window.Zoom( window.GetZoomOfToFit() );
|
||||
// "Project was recovered" replaces "Create new project" in Undo History.
|
||||
auto &undoManager = UndoManager::Get( *pProject );
|
||||
undoManager.RemoveStates(0, 1);
|
||||
}
|
||||
else
|
||||
GetProjectFrame( *mpUsedProject ).Close(true);
|
||||
}
|
||||
}
|
||||
|
||||
return pProject;
|
||||
AudacityProject &
|
||||
ProjectManager::ProjectChooser::operator() ( bool openingProjectFile )
|
||||
{
|
||||
if (mpGivenProject) {
|
||||
// Always check before opening a project file (for safety);
|
||||
// May check even when opening other files
|
||||
// (to preserve old behavior; as with the File > Open command specifying
|
||||
// multiple files of whatever types, so that each gets its own window)
|
||||
bool checkReuse = (openingProjectFile || !mReuseNonemptyProject);
|
||||
if (!checkReuse || SafeToOpenProjectInto(*mpGivenProject))
|
||||
return *(mpUsedProject = mpGivenProject);
|
||||
}
|
||||
return *(mpUsedProject = New());
|
||||
}
|
||||
|
||||
void ProjectManager::ProjectChooser::Commit()
|
||||
{
|
||||
mpUsedProject = nullptr;
|
||||
}
|
||||
|
||||
AudacityProject *ProjectManager::OpenProject(
|
||||
AudacityProject *pGivenProject, const FilePath &fileNameArg,
|
||||
bool addtohistory, bool reuseNonemptyProject)
|
||||
{
|
||||
ProjectManager::ProjectChooser chooser{ pGivenProject, reuseNonemptyProject };
|
||||
if (auto pProject = ProjectFileManager::OpenFile(
|
||||
std::ref(chooser), fileNameArg, addtohistory )) {
|
||||
chooser.Commit();
|
||||
|
||||
auto &projectFileIO = ProjectFileIO::Get( *pProject );
|
||||
if( projectFileIO.IsRecovered() ) {
|
||||
auto &window = ProjectWindow::Get( *pProject );
|
||||
window.Zoom( window.GetZoomOfToFit() );
|
||||
// "Project was recovered" replaces "Create new project" in Undo History.
|
||||
auto &undoManager = UndoManager::Get( *pProject );
|
||||
undoManager.RemoveStates(0, 1);
|
||||
}
|
||||
return pProject;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// This is done to empty out the tracks, but without creating a new project.
|
||||
|
||||
Reference in New Issue
Block a user