finish edit renaming and handle display errors encountered during rename
This commit is contained in:
@@ -1147,6 +1147,10 @@ These steps will be lost permanently.=These steps will be lost permanently.
|
|||||||
You have %d step edits, the maximum number allowed.=You have %d step edits, the maximum number allowed.
|
You have %d step edits, the maximum number allowed.=You have %d step edits, the maximum number allowed.
|
||||||
You must delete an existing steps edit before creating a new steps edit.=You must delete an existing steps edit before creating a new steps edit.
|
You must delete an existing steps edit before creating a new steps edit.=You must delete an existing steps edit before creating a new steps edit.
|
||||||
|
|
||||||
|
[NotesWriterSM]
|
||||||
|
Error renaming file. Destination file '%s' already exists.=Error renaming file. Destination file '%s' already exists.
|
||||||
|
Error writing file '%s'.=Error writing file '%s'.
|
||||||
|
|
||||||
[ScreenOptionsManageProfiles]
|
[ScreenOptionsManageProfiles]
|
||||||
Are you sure you want to clear all data in the profile '%s'?=Are you sure you want to clear all data in the profile '%s'?
|
Are you sure you want to clear all data in the profile '%s'?=Are you sure you want to clear all data in the profile '%s'?
|
||||||
Are you sure you want to delete the profile '%s'?=Are you sure you want to delete the profile '%s'?
|
Are you sure you want to delete the profile '%s'?=Are you sure you want to delete the profile '%s'?
|
||||||
@@ -1348,6 +1352,7 @@ The folder '%s' appears to be a song folder. All song folders must reside in a
|
|||||||
[SongUtil]
|
[SongUtil]
|
||||||
You must supply a name for your new edit.=You must supply a name for your new edit.
|
You must supply a name for your new edit.=You must supply a name for your new edit.
|
||||||
The name you chose conflicts with another edit. Please use a different name.=The name you chose conflicts with another edit. Please use a different name.
|
The name you chose conflicts with another edit. Please use a different name.=The name you chose conflicts with another edit. Please use a different name.
|
||||||
|
The edit name cannot contain any of the following characters: %s=The edit name cannot contain any of the following characters: %s
|
||||||
|
|
||||||
[SongSort]
|
[SongSort]
|
||||||
FewestPlays=Fewest Plays
|
FewestPlays=Fewest Plays
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "BackgroundUtil.h"
|
#include "BackgroundUtil.h"
|
||||||
#include "ProfileManager.h"
|
#include "ProfileManager.h"
|
||||||
#include "Profile.h"
|
#include "Profile.h"
|
||||||
|
#include "LocalizedString.h"
|
||||||
|
|
||||||
static RString BackgroundChangeToString( const BackgroundChange &bgc )
|
static RString BackgroundChangeToString( const BackgroundChange &bgc )
|
||||||
{
|
{
|
||||||
@@ -272,7 +273,9 @@ RString NotesWriterSM::GetEditFileName( const Song *pSong, const Steps *pSteps )
|
|||||||
return sFile;
|
return sFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NotesWriterSM::WriteEditFileToMachine( const Song *pSong, Steps *pSteps )
|
static LocalizedString DESTINATION_ALREADY_EXISTS ("NotesWriterSM", "Error renaming file. Destination file '%s' already exists.");
|
||||||
|
static LocalizedString ERROR_WRITING_FILE ("NotesWriterSM", "Error writing file '%s'.");
|
||||||
|
bool NotesWriterSM::WriteEditFileToMachine( const Song *pSong, Steps *pSteps, RString &sErrorOut )
|
||||||
{
|
{
|
||||||
RString sDir = PROFILEMAN->GetProfileDir( ProfileSlot_Machine ) + EDIT_STEPS_SUBDIR;
|
RString sDir = PROFILEMAN->GetProfileDir( ProfileSlot_Machine ) + EDIT_STEPS_SUBDIR;
|
||||||
|
|
||||||
@@ -281,12 +284,20 @@ bool NotesWriterSM::WriteEditFileToMachine( const Song *pSong, Steps *pSteps )
|
|||||||
/* Flush dir cache when writing steps, so the old size isn't cached. */
|
/* Flush dir cache when writing steps, so the old size isn't cached. */
|
||||||
FILEMAN->FlushDirCache( Dirname(sPath) );
|
FILEMAN->FlushDirCache( Dirname(sPath) );
|
||||||
|
|
||||||
// TODO: Check to make sure that we're not clobering an existing file before opening.
|
// Check to make sure that we're not clobering an existing file before opening.
|
||||||
|
bool bFileNameChanging =
|
||||||
|
pSteps->GetSavedToDisk() &&
|
||||||
|
pSteps->GetFilename() != sPath;
|
||||||
|
if( bFileNameChanging && DoesFileExist(sPath) )
|
||||||
|
{
|
||||||
|
sErrorOut = ssprintf( DESTINATION_ALREADY_EXISTS.GetValue(), sPath.c_str() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
RageFile f;
|
RageFile f;
|
||||||
if( !f.Open(sPath, RageFile::WRITE | RageFile::SLOW_FLUSH) )
|
if( !f.Open(sPath, RageFile::WRITE | RageFile::SLOW_FLUSH) )
|
||||||
{
|
{
|
||||||
LOG->Warn( "Error opening song file '%s' for writing: %s", sPath.c_str(), f.GetError().c_str() );
|
sErrorOut = ssprintf( ERROR_WRITING_FILE.GetValue(), sPath.c_str() );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,20 +305,20 @@ bool NotesWriterSM::WriteEditFileToMachine( const Song *pSong, Steps *pSteps )
|
|||||||
GetEditFileContents( pSong, pSteps, sTag );
|
GetEditFileContents( pSong, pSteps, sTag );
|
||||||
if( f.PutLine(sTag) == -1 || f.Flush() == -1 )
|
if( f.PutLine(sTag) == -1 || f.Flush() == -1 )
|
||||||
{
|
{
|
||||||
LOG->Warn( "Error writing song file '%s': %s", sPath.c_str(), f.GetError().c_str() );
|
sErrorOut = ssprintf( ERROR_WRITING_FILE.GetValue(), sPath.c_str() );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the file name of the edit has changed since the last save, then delete the old
|
/* If the file name of the edit has changed since the last save, then delete the old
|
||||||
* file after saving the new one. If we delete it first, then we'll lose data on error. */
|
* file after saving the new one. If we delete it first, then we'll lose data on error. */
|
||||||
bool bFileNameChanged =
|
|
||||||
pSteps->GetSavedToDisk() &&
|
|
||||||
pSteps->GetFilename() != sPath;
|
|
||||||
|
|
||||||
if( bFileNameChanged )
|
if( bFileNameChanging )
|
||||||
FILEMAN->Remove( pSteps->GetFilename() );
|
FILEMAN->Remove( pSteps->GetFilename() );
|
||||||
pSteps->SetFilename( sPath );
|
pSteps->SetFilename( sPath );
|
||||||
|
|
||||||
|
/* Flush dir cache or else the new file won't be seen. */
|
||||||
|
FILEMAN->FlushDirCache( Dirname(sPath) );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public:
|
|||||||
bool Write( RString sPath, const Song &out, bool bSavingCache );
|
bool Write( RString sPath, const Song &out, bool bSavingCache );
|
||||||
static void GetEditFileContents( const Song *pSong, const Steps *pSteps, RString &sOut );
|
static void GetEditFileContents( const Song *pSong, const Steps *pSteps, RString &sOut );
|
||||||
RString GetEditFileName( const Song *pSong, const Steps *pSteps );
|
RString GetEditFileName( const Song *pSong, const Steps *pSteps );
|
||||||
bool WriteEditFileToMachine( const Song *pSong, Steps *pSteps );
|
bool WriteEditFileToMachine( const Song *pSong, Steps *pSteps, RString &sErrorOut );
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -2677,10 +2677,13 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector<int> &iAns
|
|||||||
{
|
{
|
||||||
ASSERT( pSteps->IsAnEdit() );
|
ASSERT( pSteps->IsAnEdit() );
|
||||||
|
|
||||||
// XXX show error
|
|
||||||
NotesWriterSM w;
|
NotesWriterSM w;
|
||||||
if( !w.WriteEditFileToMachine(pSong, pSteps) )
|
RString sError;
|
||||||
|
if( !w.WriteEditFileToMachine(pSong,pSteps,sError) )
|
||||||
|
{
|
||||||
|
ScreenPrompt::Prompt( SM_None, sError );
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// HACK: clear undo, so "exit" below knows we don't need to save.
|
// HACK: clear undo, so "exit" below knows we don't need to save.
|
||||||
// This only works because important non-steps data can't be changed in
|
// This only works because important non-steps data can't be changed in
|
||||||
|
|||||||
@@ -14,6 +14,11 @@
|
|||||||
#include "LocalizedString.h"
|
#include "LocalizedString.h"
|
||||||
#include "OptionRowHandler.h"
|
#include "OptionRowHandler.h"
|
||||||
#include "SongUtil.h"
|
#include "SongUtil.h"
|
||||||
|
#include "song.h"
|
||||||
|
#include "ProfileManager.h"
|
||||||
|
#include "Profile.h"
|
||||||
|
#include "SpecialFiles.h"
|
||||||
|
#include "NotesWriterSM.h"
|
||||||
|
|
||||||
AutoScreenMessage( SM_BackFromRename )
|
AutoScreenMessage( SM_BackFromRename )
|
||||||
AutoScreenMessage( SM_BackFromDelete )
|
AutoScreenMessage( SM_BackFromDelete )
|
||||||
@@ -49,6 +54,12 @@ void ScreenOptionsManageEditSteps::Init()
|
|||||||
|
|
||||||
void ScreenOptionsManageEditSteps::BeginScreen()
|
void ScreenOptionsManageEditSteps::BeginScreen()
|
||||||
{
|
{
|
||||||
|
// Reload so that we're consistent with the disk in case the user has been dinking around with their edits.
|
||||||
|
SONGMAN->FreeAllLoadedFromProfile( ProfileSlot_Machine );
|
||||||
|
SONGMAN->LoadAllFromProfileDir( PROFILEMAN->GetProfileDir(ProfileSlot_Machine), ProfileSlot_Machine );
|
||||||
|
GAMESTATE->m_pCurSong.Set( NULL );
|
||||||
|
GAMESTATE->m_pCurSteps[0].Set( NULL );
|
||||||
|
|
||||||
vector<OptionRowHandler*> vHands;
|
vector<OptionRowHandler*> vHands;
|
||||||
|
|
||||||
int iIndex = 0;
|
int iIndex = 0;
|
||||||
@@ -71,7 +82,10 @@ void ScreenOptionsManageEditSteps::BeginScreen()
|
|||||||
{
|
{
|
||||||
vHands.push_back( OptionRowHandlerUtil::MakeNull() );
|
vHands.push_back( OptionRowHandlerUtil::MakeNull() );
|
||||||
OptionRowDefinition &def = vHands.back()->m_Def;
|
OptionRowDefinition &def = vHands.back()->m_Def;
|
||||||
def.m_sName = (*s)->GetDescription();
|
|
||||||
|
Song *pSong = SONGMAN->GetSongFromSteps( *s );
|
||||||
|
|
||||||
|
def.m_sName = pSong->GetTranslitFullTitle() + " - " + (*s)->GetDescription();
|
||||||
def.m_bAllowThemeTitle = false; // not themable
|
def.m_bAllowThemeTitle = false; // not themable
|
||||||
def.m_sExplanationName = "Select Edit Steps";
|
def.m_sExplanationName = "Select Edit Steps";
|
||||||
def.m_vsChoices.clear();
|
def.m_vsChoices.clear();
|
||||||
@@ -133,7 +147,19 @@ void ScreenOptionsManageEditSteps::HandleScreenMessage( const ScreenMessage SM )
|
|||||||
{
|
{
|
||||||
ASSERT( ScreenTextEntry::s_sLastAnswer != "" ); // validate should have assured this
|
ASSERT( ScreenTextEntry::s_sLastAnswer != "" ); // validate should have assured this
|
||||||
|
|
||||||
GAMESTATE->m_pCurSteps[PLAYER_1]->SetDescription( ScreenTextEntry::s_sLastAnswer );
|
Steps *pSteps = GAMESTATE->m_pCurSteps[PLAYER_1];
|
||||||
|
Song *pSong = SONGMAN->GetSongFromSteps( pSteps );
|
||||||
|
|
||||||
|
RString sOldDescription = pSteps->GetDescription();
|
||||||
|
pSteps->SetDescription( ScreenTextEntry::s_sLastAnswer );
|
||||||
|
|
||||||
|
RString sError;
|
||||||
|
NotesWriterSM sm;
|
||||||
|
if( !sm.WriteEditFileToMachine(pSong,pSteps,sError) )
|
||||||
|
{
|
||||||
|
ScreenPrompt::Prompt( SM_None, sError );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
SCREENMAN->SetNewScreen( this->m_sName ); // reload
|
SCREENMAN->SetNewScreen( this->m_sName ); // reload
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -425,10 +425,11 @@ RString SongUtil::MakeUniqueEditDescription( const Song *pSong, StepsType st, co
|
|||||||
|
|
||||||
static LocalizedString YOU_MUST_SUPPLY_NAME ( "SongUtil", "You must supply a name for your new edit." );
|
static LocalizedString YOU_MUST_SUPPLY_NAME ( "SongUtil", "You must supply a name for your new edit." );
|
||||||
static LocalizedString EDIT_NAME_CONFLICTS ( "SongUtil", "The name you chose conflicts with another edit. Please use a different name." );
|
static LocalizedString EDIT_NAME_CONFLICTS ( "SongUtil", "The name you chose conflicts with another edit. Please use a different name." );
|
||||||
|
static LocalizedString EDIT_NAME_CANNOT_CONTAIN ( "SongUtil", "The edit name cannot contain any of the following characters: %s" );
|
||||||
bool SongUtil::ValidateCurrentEditStepsDescription( const RString &sAnswer, RString &sErrorOut )
|
bool SongUtil::ValidateCurrentEditStepsDescription( const RString &sAnswer, RString &sErrorOut )
|
||||||
{
|
{
|
||||||
Steps *pSteps = GAMESTATE->m_pCurSteps[PLAYER_1];
|
Steps *pSteps = GAMESTATE->m_pCurSteps[PLAYER_1];
|
||||||
|
Song *pSong = SONGMAN->GetSongFromSteps( pSteps );
|
||||||
|
|
||||||
ASSERT( pSteps->IsAnEdit() );
|
ASSERT( pSteps->IsAnEdit() );
|
||||||
|
|
||||||
@@ -438,9 +439,16 @@ bool SongUtil::ValidateCurrentEditStepsDescription( const RString &sAnswer, RStr
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Steps name must be unique
|
static const RString sInvalidChars = "\\/:*?\"<>|";
|
||||||
|
if( strpbrk(sAnswer, sInvalidChars) != NULL )
|
||||||
|
{
|
||||||
|
sErrorOut = ssprintf( EDIT_NAME_CANNOT_CONTAIN.GetValue(), sInvalidChars.c_str() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Steps name must be unique for this song.
|
||||||
vector<Steps*> v;
|
vector<Steps*> v;
|
||||||
SONGMAN->GetStepsLoadedFromProfile( v, ProfileSlot_Machine );
|
pSong->GetSteps( v, STEPS_TYPE_INVALID, DIFFICULTY_EDIT );
|
||||||
FOREACH_CONST( Steps*, v, s )
|
FOREACH_CONST( Steps*, v, s )
|
||||||
{
|
{
|
||||||
if( pSteps == *s )
|
if( pSteps == *s )
|
||||||
|
|||||||
Reference in New Issue
Block a user