Portable mode: now allows fully custom folders, but still allows relocation of pcsx2 folder without breaking (install mode unmodified).

Details:
The major differences between install and portable modes should now be:
1. Portable mode doesn't use the registry at all.
2. Portable mode uses the folders inside pcsx2 folder as default (install mode has some default at "my documents").
3. Portable mode tries to save relative paths at the ini file where possible*.

Specifically, portable mode now allows to select custom folders for plugins, bios, etc via the standard UI, which allows using several portable pcsx2 folder sharing the same resources (bios, iso, memcards, etc).

* Relative paths where possible = the following sequence (thanks to pseudonym for the brilliant idea):
1. If the file/folder is inside pcsx2 folder, it's saved as completely relative (to pcsx2.exe)
2. Else, if the file/folder is at the same drive as pcsx2.exe, it's saved as absolute path without the drive letter (e.g. /ISO/...)
3. Else, saved as absolute path, including the drive letter (for linux, without drive letter naturally).

This allows to create a removable drive with (one or more) pcsx2 folder on it, configure all the files/folders to point to the same drive (ISOs, save states, etc), and then take this drive, plug it into another computer (where it will be assigned with a different drive letter), and everything will continue working.

Please test it if you can. Bugs here can be inconvenient...

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4507 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
avihal@gmail.com 2011-03-29 17:41:11 +00:00
parent 97ce1783eb
commit 9c234de3ec
7 changed files with 93 additions and 44 deletions

View File

@ -50,7 +50,7 @@ public:
bool IsSaving() const { return !IsLoading(); }
virtual void Entry( const wxString& var, wxString& value, const wxString defvalue=wxString() )=0;
virtual void Entry( const wxString& var, wxDirName& value, const wxDirName defvalue=wxDirName() )=0;
virtual void Entry( const wxString& var, wxDirName& value, const wxDirName defvalue=wxDirName(), bool isAllowRelative=false )=0;
virtual void Entry( const wxString& var, wxFileName& value, const wxFileName defvalue=wxFileName(), bool isAllowRelative=false )=0;
virtual void Entry( const wxString& var, int& value, const int defvalue=0 )=0;
virtual void Entry( const wxString& var, uint& value, const uint defvalue=0 )=0;
@ -113,7 +113,7 @@ public:
bool IsLoading() const { return true; }
void Entry( const wxString& var, wxString& value, const wxString defvalue=wxEmptyString );
void Entry( const wxString& var, wxDirName& value, const wxDirName defvalue=wxDirName() );
void Entry( const wxString& var, wxDirName& value, const wxDirName defvalue=wxDirName(), bool isAllowRelative=false );
void Entry( const wxString& var, wxFileName& value, const wxFileName defvalue=wxFileName(), bool isAllowRelative=false );
void Entry( const wxString& var, int& value, const int defvalue=0 );
void Entry( const wxString& var, uint& value, const uint defvalue=0 );
@ -151,7 +151,7 @@ public:
bool IsLoading() const { return false; }
void Entry( const wxString& var, wxString& value, const wxString defvalue=wxString() );
void Entry( const wxString& var, wxDirName& value, const wxDirName defvalue=wxDirName() );
void Entry( const wxString& var, wxDirName& value, const wxDirName defvalue=wxDirName(), bool isAllowRelative=false );
void Entry( const wxString& var, wxFileName& value, const wxFileName defvalue=wxFileName(), bool isAllowRelative=false );
void Entry( const wxString& var, int& value, const int defvalue=0 );
void Entry( const wxString& var, uint& value, const uint defvalue=0 );
@ -175,6 +175,7 @@ protected:
// syntax errors. >_<
//
#define IniEntry( varname ) ini.Entry( wxT(#varname), varname, varname )
#define IniEntryDirFile( varname, isAllowRelative ) ini.Entry( wxT(#varname), varname, varname, isAllowRelative )
#define IniBitfield( varname ) varname = ini.EntryBitfield( wxT(#varname), varname, varname )
#define IniBitBool( varname ) varname = ini.EntryBitBool( wxT(#varname), !!varname, varname )

View File

@ -94,6 +94,50 @@ public:
return false;
}
bool IsContains( const wxDirName& dir ) const
{
return IsContains( (wxFileName)dir );
}
//Auto relative works as follows:
// 1. if either base or subject are relative, return subject (should never be used with relative paths).
// 2. else if subject is somewhere inside base folder, then result is subject relative to base.
// 3. (windows only, implicitly) else if subject is on the same driveletter as base, result is absolute path of subject without the driveletter.
// 4. else, result is absolute path of subject.
//
// returns ok if both this and base are absolute paths.
static wxString MakeAutoRelativeTo(const wxFileName _subject, const wxString& pathbase)
{
wxFileName subject( _subject );
wxDirName base ( pathbase );
if( base.IsRelative() || subject.IsRelative() )
return subject.GetFullPath();
wxString bv( base.GetVolume() ); bv.MakeUpper();
wxString sv( subject.GetVolume() ); sv.MakeUpper();
if( base.IsContains( subject ) )
{
subject.MakeRelativeTo( base.GetFullPath() );
}
else if( base.HasVolume() && subject.HasVolume() && bv == sv )
{
wxString unusedVolume;
wxString pathSansVolume;
subject.SplitVolume(subject.GetFullPath(), &unusedVolume, &pathSansVolume);
subject = pathSansVolume;
}
//implicit else: this stays fully absolute
return subject.GetFullPath();
}
static wxString MakeAutoRelativeTo(const wxDirName subject, const wxString& pathbase)
{
return MakeAutoRelativeTo( wxFileName( subject ), pathbase );
}
// Returns the number of sub folders in this directory path
size_t GetCount() const { return GetDirCount(); }

View File

@ -108,7 +108,8 @@ void IniLoader::Entry( const wxString& var, wxString& value, const wxString defv
value = defvalue;
}
void IniLoader::Entry( const wxString& var, wxDirName& value, const wxDirName defvalue )
void IniLoader::Entry( const wxString& var, wxDirName& value, const wxDirName defvalue, bool isAllowRelative )
{
wxString dest;
if( m_Config ) m_Config->Read( var, &dest, wxEmptyString );
@ -116,7 +117,14 @@ void IniLoader::Entry( const wxString& var, wxDirName& value, const wxDirName de
if( dest.IsEmpty() )
value = defvalue;
else
{
value = dest;
if( isAllowRelative )
value = g_fullBaseDirName + value;
if( value.IsAbsolute() )
value.Normalize();
}
}
void IniLoader::Entry( const wxString& var, wxFileName& value, const wxFileName defvalue, bool isAllowRelative )
@ -124,8 +132,8 @@ void IniLoader::Entry( const wxString& var, wxFileName& value, const wxFileName
wxString dest( defvalue.GetFullPath() );
if( m_Config ) m_Config->Read( var, &dest, defvalue.GetFullPath() );
value = dest;
if( isAllowRelative && value.IsRelative() )
value = g_fullBaseDirName+value;
if( isAllowRelative )
value = g_fullBaseDirName + value;
if( value.IsAbsolute() )
value.Normalize();
@ -263,28 +271,24 @@ void IniSaver::Entry( const wxString& var, wxString& value, const wxString defva
m_Config->Write( var, value );
}
void IniSaver::Entry( const wxString& var, wxDirName& value, const wxDirName defvalue )
void IniSaver::Entry( const wxString& var, wxDirName& value, const wxDirName defvalue, bool isAllowRelative )
{
if( !m_Config ) return;
wxDirName res(value);
if ( res.IsAbsolute() )
res.Normalize();
if (isAllowRelative)
res = wxDirName::MakeAutoRelativeTo( res, g_fullBaseDirName.ToString() );
/*if( value == defvalue )
m_Config->Write( var, wxString() );
else*/
m_Config->Write( var, value.ToString() );
m_Config->Write( var, res.ToString() );
}
//If isAllowRelative is true, we're saving as relative if the file is somewhere inside the PARENT of pcsx2 folder.
//When a file is saved as relative, it's always relative to pcsx2 main folder (even if the file is outside of it).
//e.g. at the next folder structure, files at ISOs_2 and ISOs_3 will be saved relative, but files at ISOs_1 will be saved absolute.
// -root
// |-ISOs_1
// |-parent_of_pcsx2_folder
// |-ISOs_2
// |-pcsx2_folder
// |-pcsx2.exe
// |-plugins
// | |-...
// |-ISOs_3
void IniSaver::Entry( const wxString& var, wxFileName& value, const wxFileName defvalue, bool isAllowRelative )
{
if( !m_Config ) return;
@ -293,10 +297,8 @@ void IniSaver::Entry( const wxString& var, wxFileName& value, const wxFileName d
if ( res.IsAbsolute() )
res.Normalize();
wxDirName upper( g_fullBaseDirName );
upper.RemoveLast();
if( isAllowRelative && upper.IsContains( value ) )
res.MakeRelativeTo(g_fullBaseDirName.ToString());
if (isAllowRelative)
res = wxDirName::MakeAutoRelativeTo( res, g_fullBaseDirName.ToString() );
m_Config->Write( var, res.GetFullPath() );
}

View File

@ -483,7 +483,7 @@ void App_LoadSaveInstallSettings( IniInterface& ini )
ini.Entry( L"Install_Dir", InstallFolder, (wxDirName)(wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath()) );
SetFullBaseDir( InstallFolder );
ini.Entry( L"PluginsFolder", PluginsFolder, InstallFolder + PathDefs::Base::Plugins() );
//ini.Entry( L"PluginsFolder", PluginsFolder, InstallFolder + PathDefs::Base::Plugins() );
ini.Entry( L"ThemesFolder", ThemesFolder, InstallFolder + PathDefs::Base::Themes() );
ini.Flush();
@ -644,20 +644,20 @@ void AppConfig::FolderOptions::LoadSave( IniInterface& ini )
IniBitBool( UseDefaultLangs );
IniBitBool( UseDefaultPluginsFolder );
//when saving in portable mode, we save empty strings
// --> on load they'll be initialized to default (relative) paths
bool rel = ( ini.IsSaving() && IsPortable() );
wxDirName e(L"");
//when saving in portable mode, we save relative paths if possible
// --> on load, these relative paths will be expanded relative to the exe folder.
bool rel = ( ini.IsLoading() || IsPortable() );
ini.Entry( L"Bios", rel?e:Bios, Bios );
ini.Entry( L"Snapshots", rel?e:Snapshots, Snapshots );
ini.Entry( L"Savestates", rel?e:Savestates, Savestates );
ini.Entry( L"MemoryCards", rel?e:MemoryCards, MemoryCards );
ini.Entry( L"Logs", rel?e:Logs, Logs );
ini.Entry( L"Langs", rel?e:Langs, Langs );
IniEntryDirFile( Bios, rel);
IniEntryDirFile( Snapshots, rel );
IniEntryDirFile( Savestates, rel );
IniEntryDirFile( MemoryCards, rel );
IniEntryDirFile( Logs, rel );
IniEntryDirFile( Langs, rel );
ini.Entry( L"PluginsFolder", PluginsFolder, InstallFolder + PathDefs::Base::Plugins(), rel );
IniEntry( RunIso );
IniEntry( RunELF );
IniEntryDirFile( RunIso, rel );
IniEntryDirFile( RunELF, rel );
if( ini.IsLoading() )
{

View File

@ -107,7 +107,7 @@ Panels::BiosSelectorPanel::BiosSelectorPanel( wxWindow* parent )
m_ComboBox->SetFont( wxFont( m_ComboBox->GetFont().GetPointSize()+1, wxFONTFAMILY_MODERN, wxNORMAL, wxNORMAL, false, L"Lucida Console" ) );
m_ComboBox->SetMinSize( wxSize( wxDefaultCoord, std::max( m_ComboBox->GetMinSize().GetHeight(), 96 ) ) );
if (InstallationMode != InstallMode_Portable)
//if (InstallationMode != InstallMode_Portable)
m_FolderPicker->SetStaticDesc( _("Click the Browse button to select a different folder where PCSX2 will look for PS2 BIOS roms.") );
wxButton* refreshButton = new wxButton( this, wxID_ANY, _("Refresh list") );

View File

@ -117,9 +117,9 @@ void Panels::DirPickerPanel::Init( FoldersEnum_t folderid, const wxString& dialo
// The default path is invalid... What should we do here? hmm..
}
if (InstallationMode == InstallMode_Portable)
InitForPortableMode(normalized);
else
// if (InstallationMode == InstallMode_Portable)
// InitForPortableMode(normalized);
// else
InitForRegisteredMode(normalized, dialogLabel, isCompact);
// wx warns when paths don't exist, but this is typically normal when the wizard
@ -128,9 +128,11 @@ void Panels::DirPickerPanel::Init( FoldersEnum_t folderid, const wxString& dialo
AppStatusEvent_OnSettingsApplied(); // forces default settings based on g_Conf
}
// InitForPortableMode is currently unused because portable now allows fully custom folders.
void Panels::DirPickerPanel::InitForPortableMode( const wxString& normalized )
{
// In portable mode the path is unchangeable, and only a browse button is provided (which
// In portable mode the path is unchangeable, and only a "open in explorer" button is provided (which
// itself is windows-only at this time).
m_textCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY );

View File

@ -375,7 +375,7 @@ Panels::PluginSelectorPanel::ComboBoxPanel::ComboBoxPanel( PluginSelectorPanel*
s_plugin += m_configbutton[pid];
} while( ++pi, pi->shortname != NULL );
if (InstallationMode != InstallMode_Portable)
// if (InstallationMode != InstallMode_Portable)
m_FolderPicker.SetStaticDesc( _("Click the Browse button to select a different folder for PCSX2 plugins.") );
*this += s_plugin | pxExpand;