diff --git a/pcsx2/gui/App.h b/pcsx2/gui/App.h index 64a750f575..246c980171 100644 --- a/pcsx2/gui/App.h +++ b/pcsx2/gui/App.h @@ -272,6 +272,7 @@ class StartupOptions public: bool ForceWizard; bool ForceConsole; + bool PortableMode; // Disables the fast boot option when auto-running games. This option only applies // if SysAutoRun is also true. @@ -290,8 +291,9 @@ public: StartupOptions() { ForceWizard = false; - NoFastBoot = false; ForceConsole = false; + PortableMode = false; + NoFastBoot = false; SysAutoRun = false; CdvdSource = CDVDsrc_NoDisc; } @@ -538,9 +540,11 @@ public: void CleanupRestartable(); void CleanupResources(); void WipeUserModeSettings(); - void ReadUserModeSettings(); - bool TestForPortableInstall(); bool TestUserPermissionsRights( const wxDirName& testFolder, wxString& createFailedStr, wxString& accessFailedStr ); + void EstablishAppUserMode(); + + wxConfigBase* ReadUserModeSettings(); + wxConfigBase* TestForPortableInstall(); bool HasPendingSaves() const; void StartPendingSave(); diff --git a/pcsx2/gui/AppConfig.cpp b/pcsx2/gui/AppConfig.cpp index f5c89465ab..6feb9bd4d8 100644 --- a/pcsx2/gui/AppConfig.cpp +++ b/pcsx2/gui/AppConfig.cpp @@ -430,7 +430,7 @@ void App_LoadSaveInstallSettings( IniInterface& ini ) // "Install_Dir" conforms to the NSIS standard install directory key name. // Attempt to load plugins and themes based on the Install Folder. - ini.Entry( L"Install_Dir", InstallFolder, (wxDirName)wxStandardPaths::Get().GetExecutablePath() ); + ini.Entry( L"Install_Dir", InstallFolder, (wxDirName)(wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath()) ); ini.Entry( L"PluginsFolder", PluginsFolder, InstallFolder + PathDefs::Base::Plugins() ); ini.Entry( L"ThemesFolder", ThemesFolder, InstallFolder + PathDefs::Base::Themes() ); diff --git a/pcsx2/gui/AppInit.cpp b/pcsx2/gui/AppInit.cpp index 3ce090875d..0b7b47ada1 100644 --- a/pcsx2/gui/AppInit.cpp +++ b/pcsx2/gui/AppInit.cpp @@ -71,12 +71,12 @@ void Pcsx2App::DetectCpuAndUserMode() .SetUserMsg(_("SSE extensions are not available. PCSX2 requires a cpu that supports the SSE instruction set.")); } - if (!TestForPortableInstall()) - { - ReadUserModeSettings(); - } + EstablishAppUserMode(); - AppConfig_OnChangedSettingsFolder(); + // force unload plugins loaded by the wizard. If we don't do this the recompilers might + // fail to allocate the memory they need to function. + ShutdownPlugins(); + UnloadPlugins(); } void Pcsx2App::OpenMainFrame() @@ -252,6 +252,7 @@ void Pcsx2App::OnInitCmdLine( wxCmdLineParser& parser ) parser.AddOption( wxEmptyString,L"cfgpath", _("changes the configuration file path"), wxCMD_LINE_VAL_STRING ); parser.AddOption( wxEmptyString,L"cfg", _("specifies the PCSX2 configuration file to use"), wxCMD_LINE_VAL_STRING ); parser.AddSwitch( wxEmptyString,L"forcewiz", AddAppName(_("forces %s to start the First-time Wizard")) ); + parser.AddSwitch( wxEmptyString,L"portable", _("enables portable mode operation (requires admin/root access)") ); const PluginInfo* pi = tbl_PluginInfo; do { parser.AddOption( wxEmptyString, pi->GetShortname().Lower(), @@ -344,6 +345,7 @@ bool Pcsx2App::OnCmdLineParsed( wxCmdLineParser& parser ) Startup.NoFastBoot = parser.Found(L"fullboot"); Startup.ForceWizard = parser.Found(L"forcewiz"); + Startup.PortableMode = parser.Found(L"portable"); if( parser.GetParamCount() >= 1 ) { diff --git a/pcsx2/gui/AppUserMode.cpp b/pcsx2/gui/AppUserMode.cpp index 4638cda6f7..39ffae076b 100644 --- a/pcsx2/gui/AppUserMode.cpp +++ b/pcsx2/gui/AppUserMode.cpp @@ -19,10 +19,10 @@ #include "Utilities/HashMap.h" #include "Dialogs/ModalPopups.h" -#include - +#include + #ifdef __WXMSW__ -#include "wx/msw/regconf.h" +#include "wx/msw/regconf.h" #endif DocsModeType DocsFolderMode = DocsFolder_User; @@ -130,17 +130,20 @@ bool Pcsx2App::TestUserPermissionsRights( const wxDirName& testFolder, wxString& // Portable installation mode is typically enabled via the presence of an INI file in the // same directory that PCSX2 is installed to. // -bool Pcsx2App::TestForPortableInstall() +wxConfigBase* Pcsx2App::TestForPortableInstall() { UserLocalDataMode = UserLocalFolder_System; const wxFileName portableIniFile( GetPortableIniPath() ); const wxDirName portableDocsFolder( portableIniFile.GetPath() ); - if (portableIniFile.FileExists()) + if (Startup.PortableMode || portableIniFile.FileExists()) { wxString FilenameStr = portableIniFile.GetFullPath(); - Console.WriteLn( L"(UserMode) Found portable install ini @ %s", FilenameStr.c_str() ); + if (Startup.PortableMode) + Console.WriteLn( L"(UserMode) Portable mode requested via commandline switch!" ); + else + Console.WriteLn( L"(UserMode) Found portable install ini @ %s", FilenameStr.c_str() ); // Just because the portable ini file exists doesn't mean we can actually run in portable // mode. In order to determine our read/write permissions to the PCSX2, we must try to @@ -148,7 +151,6 @@ bool Pcsx2App::TestForPortableInstall() ScopedPtr conf_portable( OpenFileConfig( portableIniFile.GetFullPath() ) ); conf_portable->SetRecordDefaults(false); - wxString iniFolder = conf_portable->Read( L"IniFolder", wxGetCwd() ); while( true ) { @@ -190,7 +192,7 @@ bool Pcsx2App::TestForPortableInstall() case pxID_CUSTOM: // Pretend like the portable ini was never found! - return false; + return NULL; } } @@ -199,10 +201,10 @@ bool Pcsx2App::TestForPortableInstall() // able to run error-free! UserLocalDataMode = UserLocalFolder_Portable; - return true; + return conf_portable.DetachPtr(); } - return false; + return NULL; } // Removes both portable ini and user local ini entry conforming to this instance of PCSX2. @@ -250,11 +252,11 @@ static void DoFirstTimeWizard() // first time startup, so give the user the choice of user mode: while(true) { - // PCSX2's FTWizard allows improptu restarting of the wizard without cancellation. This is - // typically used to change the user's language selection. + // PCSX2's FTWizard allows improptu restarting of the wizard without cancellation. + // This is typically used to change the user's language selection. FirstTimeWizard wiz( NULL ); - if( wiz.RunWizard( wiz.GetUsermodePage() ) ) break; + if( wiz.RunWizard( wiz.GetFirstPage() ) ) break; if (wiz.GetReturnCode() != pxID_RestartWizard) throw Exception::StartupAborted( L"User canceled FirstTime Wizard." ); @@ -262,7 +264,7 @@ static void DoFirstTimeWizard() } } -void Pcsx2App::ReadUserModeSettings() +wxConfigBase* Pcsx2App::ReadUserModeSettings() { // Implementation Notes: // @@ -271,13 +273,8 @@ void Pcsx2App::ReadUserModeSettings() // the old system (CWD-based ini file mess) in favor of a system that simply stores // most core application-level settings in the registry. - // [TODO] : wxWidgets 2.8 does not yet support the Windows Vista/7 APPDATA feature (which - // resolves to c:\programdata\ on standard installs). I'm too lazy to write our own - // register code to uncover the value of CSLID_APPDATA, so until we upgrade wx, we'll - // just store the configuration files in the user local data directory instead. - ScopedPtr conf_install; - + #ifdef __WXMSW__ conf_install = new wxRegConfig(); #else @@ -297,38 +294,33 @@ void Pcsx2App::ReadUserModeSettings() conf_install = OpenFileConfig( usermodefile.GetFullPath() ); #endif + return conf_install.DetachPtr(); +} + + +void Pcsx2App::EstablishAppUserMode() +{ + ScopedPtr conf_install; + + conf_install = TestForPortableInstall(); + if (!conf_install) + conf_install = ReadUserModeSettings(); + conf_install->SetRecordDefaults(false); + // Run the First Time Wizard! + // ---------------------------- + // Wizard is only run once. The status of the wizard having been run is stored in + // the installation ini file, which can be either the portable install (useful for admins) + // or the registry/user local documents position. + bool runWiz; conf_install->Read( L"RunWizard", &runWiz, true ); - if( !Startup.ForceWizard && !runWiz ) - { - IniLoader loader( conf_install ); - App_LoadSaveInstallSettings( loader ); - return; - } + IniLoader loader( conf_install ); + App_LoadSaveInstallSettings( loader ); - // ---------------------------- - // Run the First Time Wizard! - // ---------------------------- - - // Beta Warning! - #if 0 - if( !hasGroup ) - { - wxDialogWithHelpers beta( NULL, _fmt("Welcome to %s %u.%u.%u (r%u)", pxGetAppName().c_str(), PCSX2_VersionHi, PCSX2_VersionMid, PCSX2_VersionLo, SVN_REV )); - beta.SetMinWidth(480); - - beta += beta.Heading( - L"PCSX2 0.9.7 is a work-in-progress. We are in the middle of major rewrites of the user interface, and some parts " - L"of the program have *NOT* been re-implemented yet. Options will be missing or disabled. Horrible crashes might be present. Enjoy!" - ); - beta += StdPadding*2; - beta += new wxButton( &beta, wxID_OK ) | StdCenter(); - beta.ShowModal(); - } - #endif + if( !Startup.ForceWizard && !runWiz ) return; DoFirstTimeWizard(); @@ -340,9 +332,5 @@ void Pcsx2App::ReadUserModeSettings() // Wizard completed successfully, so let's not torture the user with this crap again! conf_install->Write( L"RunWizard", false ); - - // force unload plugins loaded by the wizard. If we don't do this the recompilers might - // fail to allocate the memory they need to function. - ShutdownPlugins(); - UnloadPlugins(); } + diff --git a/pcsx2/gui/Dialogs/FirstTimeWizard.cpp b/pcsx2/gui/Dialogs/FirstTimeWizard.cpp index 5fd9a709db..12d4fde412 100644 --- a/pcsx2/gui/Dialogs/FirstTimeWizard.cpp +++ b/pcsx2/gui/Dialogs/FirstTimeWizard.cpp @@ -21,6 +21,7 @@ #include "Panels/ConfigurationPanels.h" #include #include +#include using namespace Panels; using namespace pxSizerFlags; @@ -56,93 +57,79 @@ Panels::SettingsDirPickerPanel::SettingsDirPickerPanel( wxWindow* parent ) ) ); } -// ---------------------------------------------------------------------------- -FirstTimeWizard::UsermodePage::UsermodePage( wxWizard* parent ) : - ApplicableWizardPage( parent ) +namespace Panels { - SetMinSize( wxSize(640, GetMinHeight()) ); - SetSizer( new wxBoxSizer( wxVERTICAL ) ); - wxPanelWithHelpers& panel( *new wxPanelWithHelpers( this, wxVERTICAL ) ); - - m_dirpick_settings = new SettingsDirPickerPanel( &panel ); - m_panel_LangSel = new LanguageSelectionPanel( &panel ); - m_panel_UserSel = new DocsFolderPickerPanel( &panel ); - - panel += panel.Heading(AddAppName(_("%s is starting from a new or unknown folder and needs to be configured."))).Bold(); - - panel += m_panel_LangSel | StdCenter(); - panel += m_panel_UserSel | pxExpand.Border( wxALL, 8 ); - - panel += 6; - panel += m_dirpick_settings | SubGroup(); - - *this += panel | pxExpand; - - Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler(UsermodePage::OnUsermodeChanged) ); - - Connect( m_panel_UserSel->GetDirPickerId(), wxEVT_COMMAND_DIRPICKER_CHANGED, wxCommandEventHandler(UsermodePage::OnCustomDirChanged) ); -} - -void FirstTimeWizard::UsermodePage::OnUsermodeChanged( wxCommandEvent& evt ) -{ - evt.Skip(); - m_panel_UserSel->Apply(); - g_Conf->Folders.ApplyDefaults(); - m_dirpick_settings->Reset(); -} - -void FirstTimeWizard::UsermodePage::OnCustomDirChanged( wxCommandEvent& evt ) -{ - OnUsermodeChanged( evt ); -} - -bool FirstTimeWizard::UsermodePage::PrepForApply() -{ - wxDirName path( PathDefs::GetDocuments(m_panel_UserSel->GetDocsMode()) ); - - if( path.FileExists() ) + class FirstTimeIntroPanel : public wxPanelWithHelpers { - // FIXME: There's already a file by the same name.. not sure what we should do here. - throw Exception::BadStream( path.ToString() ) - .SetDiagMsg(L"Targeted documents folder is already occupied by a file.") - .SetUserMsg(pxE( "!Notice:DocsFolderFileConflict", - L"PCSX2 cannot create a documents folder in the requested location. " - L"The path name matches an existing file. Delete the file or change the documents location, " - L"and then try again." - )); - } - - if( !path.Exists() ) - { - wxDialogWithHelpers dialog( NULL, _("Create folder?") ); - dialog += dialog.Heading(AddAppName(_("%s will create the following folder for documents. You can change this setting later, at any time."))); - dialog += 12; - dialog += dialog.Heading( path.ToString() ); - - if( wxID_CANCEL == pxIssueConfirmation( dialog, MsgButtons().Custom(_("Create"), "create").Cancel(), L"CreateNewFolder" ) ) - return false; - } - path.Mkdir(); - return true; + public: + FirstTimeIntroPanel( wxWindow* parent ); + virtual ~FirstTimeIntroPanel() throw() {} + }; } -// ---------------------------------------------------------------------------- +Panels::FirstTimeIntroPanel::FirstTimeIntroPanel( wxWindow* parent ) + : wxPanelWithHelpers( parent, wxVERTICAL ) +{ + SetMinWidth( 640 ); + + FastFormatUnicode faqFile; + faqFile.Write( L"file:///%s/Docs/PCSX2 FAQ %u.%u.%u.pdf", + InstallFolder.ToString().c_str(), PCSX2_VersionHi, PCSX2_VersionMid, PCSX2_VersionLo + ); + + wxStaticBoxSizer& langSel = *new wxStaticBoxSizer( wxVERTICAL, this, _("Language selector") ); + + langSel += new Panels::LanguageSelectionPanel( this ) | StdCenter(); + langSel += Label(_("Change this only if you need to.\nThe system default should be fine for most operating systems.")); + + *this += langSel | StdCenter(); + *this += GetCharHeight() * 2; + + *this += Heading(AddAppName(L"Welcome to %s!")).Bold(); + *this += GetCharHeight(); + + *this += Heading(AddAppName( + pxE( "!Wizard:Welcome", + L"This wizard will help guide you through configuring plugins, " + L"memory cards, and BIOS. It is recommended if this is your first time installing " + L"%s that you view the readme and configuration guide." + ) ) + ); + + *this += GetCharHeight() * 2; + + *this += new wxHyperlinkCtrl( this, wxID_ANY, + _("Configuration Guides (online)"), L"http://www.pcsx2.net/guide.php" + ) | pxProportion(1).Center().Border( wxALL, 5 ); + + *this += new wxHyperlinkCtrl( this, wxID_ANY, + _("Readme / FAQ (Offline/PDF)"), faqFile.c_str() + ) | pxProportion(1).Center().Border( wxALL, 5 ); + +} + +// -------------------------------------------------------------------------------------- +// FirstTimeWizard (implementations) +// -------------------------------------------------------------------------------------- FirstTimeWizard::FirstTimeWizard( wxWindow* parent ) : wxWizard( parent, wxID_ANY, AddAppName(_("%s First Time Configuration")) ) - , m_page_usermode ( *new UsermodePage( this ) ) - , m_page_plugins ( *new ApplicableWizardPage( this, &m_page_usermode ) ) + , m_page_intro ( *new ApplicableWizardPage( this ) ) + , m_page_plugins ( *new ApplicableWizardPage( this, &m_page_intro ) ) , m_page_bios ( *new ApplicableWizardPage( this, &m_page_plugins ) ) + , m_panel_Intro ( *new FirstTimeIntroPanel( &m_page_intro )) , m_panel_PluginSel ( *new PluginSelectorPanel( &m_page_plugins ) ) , m_panel_BiosSel ( *new BiosSelectorPanel( &m_page_bios ) ) { // Page 2 - Plugins Panel // Page 3 - Bios Panel + m_page_intro. SetSizer( new wxBoxSizer( wxVERTICAL ) ); m_page_plugins. SetSizer( new wxBoxSizer( wxVERTICAL ) ); m_page_bios. SetSizer( new wxBoxSizer( wxVERTICAL ) ); + m_page_intro += m_panel_Intro | StdExpand(); m_page_plugins += m_panel_PluginSel | StdExpand(); m_page_bios += m_panel_BiosSel | StdExpand(); @@ -157,16 +144,16 @@ FirstTimeWizard::FirstTimeWizard( wxWindow* parent ) ) | StdExpand(); // Assign page indexes as client data - m_page_usermode .SetClientData( (void*)0 ); + m_page_intro .SetClientData( (void*)0 ); m_page_plugins .SetClientData( (void*)1 ); m_page_bios .SetClientData( (void*)2 ); // Build the forward chain: // (backward chain is built during initialization above) - m_page_usermode .SetNext( &m_page_plugins ); + m_page_intro .SetNext( &m_page_plugins ); m_page_plugins .SetNext( &m_page_bios ); - GetPageAreaSizer() += m_page_usermode; + GetPageAreaSizer() += m_page_intro; GetPageAreaSizer() += m_page_plugins; // this doesn't descent from wxDialogWithHelpers, so we need to explicitly diff --git a/pcsx2/gui/Dialogs/ModalPopups.h b/pcsx2/gui/Dialogs/ModalPopups.h index 025e9abdce..874340b4f6 100644 --- a/pcsx2/gui/Dialogs/ModalPopups.h +++ b/pcsx2/gui/Dialogs/ModalPopups.h @@ -26,28 +26,11 @@ class FirstTimeWizard : public wxWizard typedef wxWizard _parent; protected: - class UsermodePage : public ApplicableWizardPage - { - protected: - Panels::DirPickerPanel* m_dirpick_settings; - Panels::LanguageSelectionPanel* m_panel_LangSel; - Panels::DocsFolderPickerPanel* m_panel_UserSel; - - public: - UsermodePage( wxWizard* parent ); - virtual ~UsermodePage() throw() { } - bool PrepForApply(); - - protected: - void OnUsermodeChanged( wxCommandEvent& evt ); - void OnCustomDirChanged( wxCommandEvent& evt ); - }; - -protected: - UsermodePage& m_page_usermode; - wxWizardPageSimple& m_page_plugins; - wxWizardPageSimple& m_page_bios; + wxWizardPageSimple& m_page_intro; + wxWizardPageSimple& m_page_plugins; + wxWizardPageSimple& m_page_bios; + wxPanelWithHelpers& m_panel_Intro; Panels::PluginSelectorPanel& m_panel_PluginSel; Panels::BiosSelectorPanel& m_panel_BiosSel; @@ -55,8 +38,7 @@ public: FirstTimeWizard( wxWindow* parent ); virtual ~FirstTimeWizard() throw(); - wxWizardPage *GetUsermodePage() const { return &m_page_usermode; } - wxWizardPage *GetPostUsermodePage() const { return &m_page_plugins; } + wxWizardPage *GetFirstPage() const { return &m_page_intro; } void ForceEnumPlugins() { diff --git a/pcsx2/gui/Panels/MiscPanelStuff.cpp b/pcsx2/gui/Panels/MiscPanelStuff.cpp index c9c1c19c28..1b3e710d25 100644 --- a/pcsx2/gui/Panels/MiscPanelStuff.cpp +++ b/pcsx2/gui/Panels/MiscPanelStuff.cpp @@ -124,11 +124,11 @@ Panels::LanguageSelectionPanel::LanguageSelectionPanel( wxWindow* parent ) wxButton* applyButton = new wxButton( this, pxID_RestartWizard, _("Apply") ); applyButton->SetToolTip(_("Make this language my default right now!")); - *this += Label(_("Select a language:")) | pxMiddle; *this += 5; *this += m_picker | pxSizerFlags::StdSpace(); *this += 5; *this += applyButton | pxSizerFlags::StdSpace(); + *this += 5; Connect( pxID_RestartWizard, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( LanguageSelectionPanel::OnApplyLanguage_Clicked ) );