audacia/src/ProjectHistory.cpp

179 lines
4.9 KiB
C++

/**********************************************************************
Audacity: A Digital Audio Editor
ProjectHistory.cpp
Paul Licameli split from ProjectManager.cpp
**********************************************************************/
#include "ProjectHistory.h"
#include "Project.h"
#include "ProjectFileIO.h"
#include "Tags.h"
#include "Track.h"
#include "UndoManager.h"
#include "ViewInfo.h"
static AudacityProject::AttachedObjects::RegisteredFactory sProjectHistoryKey {
[]( AudacityProject &project ) {
return std::make_shared< ProjectHistory >( project );
}
};
ProjectHistory &ProjectHistory::Get( AudacityProject &project )
{
return project.AttachedObjects::Get< ProjectHistory >( sProjectHistoryKey );
}
const ProjectHistory &ProjectHistory::Get( const AudacityProject &project )
{
return Get( const_cast< AudacityProject & >( project ) );
}
ProjectHistory::~ProjectHistory() = default;
//
// Undo/History methods
//
void ProjectHistory::InitialState()
{
auto &project = mProject;
auto &tracks = TrackList::Get( project );
auto &viewInfo = ViewInfo::Get( project );
auto &undoManager = UndoManager::Get( project );
auto &tags = Tags::Get( project );
undoManager.ClearStates();
undoManager.PushState(
&tracks, viewInfo.selectedRegion, tags.shared_from_this(),
XO("Created new project"), {});
undoManager.StateSaved();
}
bool ProjectHistory::UndoAvailable() const
{
auto &project = mProject;
auto &tracks = TrackList::Get( project );
auto &undoManager = UndoManager::Get( project );
return undoManager.UndoAvailable() &&
!tracks.HasPendingTracks();
}
bool ProjectHistory::RedoAvailable() const
{
auto &project = mProject;
auto &tracks = TrackList::Get( project );
auto &undoManager = UndoManager::Get( project );
return undoManager.RedoAvailable() &&
!tracks.HasPendingTracks();
}
namespace {
void AutoSaveOrThrow( ProjectFileIO &projectFileIO )
{
if ( !projectFileIO.AutoSave() )
throw SimpleMessageBoxException{
ExceptionType::Internal,
XO("Automatic database backup failed."),
XO("Warning"),
"Error:_Disk_full_or_not_writable"
};
}
}
void ProjectHistory::PushState(
const TranslatableString &desc, const TranslatableString &shortDesc)
{
PushState(desc, shortDesc, UndoPush::NONE);
}
void ProjectHistory::PushState(const TranslatableString &desc,
const TranslatableString &shortDesc,
UndoPush flags )
{
auto &project = mProject;
auto &projectFileIO = ProjectFileIO::Get( project );
if((flags & UndoPush::NOAUTOSAVE) == UndoPush::NONE)
AutoSaveOrThrow( projectFileIO );
// remaining no-fail operations "commit" the changes of undo manager state
auto &tracks = TrackList::Get( project );
auto &viewInfo = ViewInfo::Get( project );
auto &undoManager = UndoManager::Get( project );
auto &tags = Tags::Get( project );
undoManager.PushState(
&tracks, viewInfo.selectedRegion, tags.shared_from_this(),
desc, shortDesc, flags);
mDirty = true;
}
void ProjectHistory::RollbackState()
{
auto &project = mProject;
auto &undoManager = UndoManager::Get( project );
SetStateTo( undoManager.GetCurrentState(), false );
}
void ProjectHistory::ModifyState(bool bWantsAutoSave)
{
auto &project = mProject;
auto &projectFileIO = ProjectFileIO::Get( project );
if (bWantsAutoSave)
AutoSaveOrThrow( projectFileIO );
// remaining no-fail operations "commit" the changes of undo manager state
auto &tracks = TrackList::Get( project );
auto &viewInfo = ViewInfo::Get( project );
auto &undoManager = UndoManager::Get( project );
auto &tags = Tags::Get( project );
undoManager.ModifyState(
&tracks, viewInfo.selectedRegion, tags.shared_from_this());
}
// LL: Is there a memory leak here as "l" and "t" are not deleted???
// Vaughan, 2010-08-29: No, as "l" is a TrackList* of an Undo stack state.
// Need to keep it and its tracks "t" available for Undo/Redo/SetStateTo.
void ProjectHistory::PopState(const UndoState &state, bool doAutosave)
{
auto &project = mProject;
auto &projectFileIO = ProjectFileIO::Get( project );
if (doAutosave)
AutoSaveOrThrow( projectFileIO );
// remaining no-fail operations "commit" the changes of undo manager state
auto &dstTracks = TrackList::Get( project );
auto &viewInfo = ViewInfo::Get( project );
viewInfo.selectedRegion = state.selectedRegion;
// Restore tags
Tags::Set( project, state.tags );
TrackList *const tracks = state.tracks.get();
dstTracks.Clear();
for (auto t : tracks->Any())
{
dstTracks.Add(t->Duplicate());
}
}
void ProjectHistory::SetStateTo(unsigned int n, bool doAutosave)
{
auto &project = mProject;
auto &undoManager = UndoManager::Get( project );
undoManager.SetStateTo(n,
[this, doAutosave]( const UndoStackElem &elem ){
PopState(elem.state, doAutosave); } );
}