179 lines
4.9 KiB
C++
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); } );
|
|
}
|