diff --git a/common/include/Utilities/IniInterface.h b/common/include/Utilities/IniInterface.h index 957015510c..35764f7670 100644 --- a/common/include/Utilities/IniInterface.h +++ b/common/include/Utilities/IniInterface.h @@ -51,7 +51,7 @@ public: 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, wxFileName& value, const wxFileName defvalue=wxFileName() )=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; virtual void Entry( const wxString& var, bool& value, const bool defvalue=false )=0; @@ -114,7 +114,7 @@ public: 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, wxFileName& value, const wxFileName defvalue=wxFileName() ); + 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 ); void Entry( const wxString& var, bool& value, const bool defvalue=false ); @@ -152,7 +152,7 @@ public: 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, wxFileName& value, const wxFileName defvalue=wxFileName() ); + 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 ); void Entry( const wxString& var, bool& value, const bool defvalue=false ); @@ -180,3 +180,7 @@ protected: #define IniBitfieldEx( varname, textname ) varname = ini.EntryBitfield( wxT(textname), varname, varname ) #define IniBitBoolEx( varname, textname ) varname = ini.EntryBitBool( wxT(textname), !!varname, varname ) + +//used for filenames and folder names as ini values. +//Set to app root folder, so all files and folders which are inside appRoot will be written as relative. +void SetFullBaseDir( wxDirName appRoot ); diff --git a/common/include/Utilities/Path.h b/common/include/Utilities/Path.h index 4945ec8639..509923230e 100644 --- a/common/include/Utilities/Path.h +++ b/common/include/Utilities/Path.h @@ -72,6 +72,28 @@ public: return wxFileName::SameAs( filepath ); } + //Returns true if the file is somewhere inside this directory (and both file and directory are not relative). + bool IsContains( const wxFileName& file ) const + { + if( this->IsRelative() || file.IsRelative() ) + return false; + + wxFileName f( file ); + + while( 1 ) + { + if( this->SameAs( wxDirName(f.GetPath()) ) ) + return true; + + if( f.GetDirCount() == 0 ) + return false; + + f.RemoveLastDir(); + } + + return false; + } + // Returns the number of sub folders in this directory path size_t GetCount() const { return GetDirCount(); } diff --git a/common/src/Utilities/IniInterface.cpp b/common/src/Utilities/IniInterface.cpp index 1f6a97a02c..724395660d 100644 --- a/common/src/Utilities/IniInterface.cpp +++ b/common/src/Utilities/IniInterface.cpp @@ -26,6 +26,12 @@ const wxRect wxDefaultRect( wxDefaultCoord, wxDefaultCoord, wxDefaultCoord, wxDe template struct FixedInt<100>; template struct FixedInt<256>; +wxDirName g_fullBaseDirName = wxDirName(L""); +void SetFullBaseDir( wxDirName appRoot ) +{ + g_fullBaseDirName = appRoot; +} + static int _calcEnumLength( const wxChar* const* enumArray ) { int cnt = 0; @@ -113,11 +119,19 @@ void IniLoader::Entry( const wxString& var, wxDirName& value, const wxDirName de value = dest; } -void IniLoader::Entry( const wxString& var, wxFileName& value, const wxFileName defvalue ) +void IniLoader::Entry( const wxString& var, wxFileName& value, const wxFileName defvalue, bool isAllowRelative ) { 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( value.IsAbsolute() ) + value.Normalize(); + + if (value.HasVolume()) + value.SetVolume(value.GetVolume().Upper()); } void IniLoader::Entry( const wxString& var, int& value, const int defvalue ) @@ -259,10 +273,32 @@ void IniSaver::Entry( const wxString& var, wxDirName& value, const wxDirName def m_Config->Write( var, value.ToString() ); } -void IniSaver::Entry( const wxString& var, wxFileName& value, const wxFileName defvalue ) +//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; - m_Config->Write( var, value.GetFullPath() ); + wxFileName res(value); + + if ( res.IsAbsolute() ) + res.Normalize(); + + wxDirName upper( g_fullBaseDirName ); + upper.RemoveLast(); + if( isAllowRelative && upper.IsContains( value ) ) + res.MakeRelativeTo(g_fullBaseDirName.ToString()); + + m_Config->Write( var, res.GetFullPath() ); } void IniSaver::Entry( const wxString& var, int& value, const int defvalue ) diff --git a/pcsx2/gui/AppConfig.cpp b/pcsx2/gui/AppConfig.cpp index b8390caa0c..14cb8552c9 100644 --- a/pcsx2/gui/AppConfig.cpp +++ b/pcsx2/gui/AppConfig.cpp @@ -406,6 +406,11 @@ wxString AppConfig::FullpathToMcd( uint slot ) const return Path::Combine( Folders.MemoryCards, Mcd[slot].Filename ); } +bool IsPortable() +{ + return InstallationMode==InstallMode_Portable; +} + AppConfig::AppConfig() : MainGuiPosition( wxDefaultPosition ) , SysSettingsTabName( L"Cpu" ) @@ -471,6 +476,8 @@ void App_LoadSaveInstallSettings( IniInterface& ini ) // Attempt to load plugins and themes based on the Install Folder. 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"ThemesFolder", ThemesFolder, InstallFolder + PathDefs::Base::Themes() ); @@ -530,7 +537,10 @@ void AppConfig::LoadSaveRootItems( IniInterface& ini ) IniEntry( Toolbar_ImageSize ); IniEntry( Toolbar_ShowLabels ); - IniEntry( CurrentIso ); + wxFileName res(CurrentIso); + ini.Entry( L"CurrentIso", res, res, ini.IsLoading() || IsPortable() ); + CurrentIso = res.GetFullPath(); + IniEntry( CurrentELF ); IniEntry( EnableSpeedHacks ); @@ -631,7 +641,7 @@ void AppConfig::FolderOptions::LoadSave( IniInterface& ini ) //when saving in portable mode, we save empty strings // --> on load they'll be initialized to default (relative) paths - bool rel = ( ini.IsSaving() && (InstallationMode==InstallMode_Portable) ); + bool rel = ( ini.IsSaving() && IsPortable() ); wxDirName e(L""); ini.Entry( L"Bios", rel?e:Bios, Bios ); @@ -669,7 +679,7 @@ void AppConfig::FilenameOptions::LoadSave( IniInterface& ini ) //when saving in portable mode, we just save the non-full-path filename // --> on load they'll be initialized with default (relative) paths (works both for plugins and bios) //note: this will break if converting from install to portable, and custom folders are used. We can live with that. - bool needRelativeName = ini.IsSaving() && (InstallationMode==InstallMode_Portable); + bool needRelativeName = ini.IsSaving() && IsPortable(); for( int i=0; im_firstIdForMenuItems_or_wxID_ANY + id; curitem.ItemPtr = m_Menu->Append( wxid, Path::GetFilename(curitem.Filename), curitem.Filename, wxITEM_RADIO ); + bool exists = wxFileExists( curitem.Filename ); - if( m_cursel == id ) + if( m_cursel == id && exists ) curitem.ItemPtr->Check(); + + if ( !exists ) + curitem.ItemPtr->Enable( false ); } void RecentIsoManager::LoadListFrom( IniInterface& ini ) @@ -189,9 +193,9 @@ void RecentIsoManager::LoadListFrom( IniInterface& ini ) ScopedIniGroup groupie( ini, L"RecentIso" ); for( uint i=0; iCurrentIso ); @@ -220,7 +224,7 @@ void RecentIsoManager::AppStatusEvent_OnUiSettingsLoadSave( const AppSettingsEve int cnt = m_Items.size(); for( int i=0; i