diff --git a/pcsx2/Sio.cpp b/pcsx2/Sio.cpp index 1bf3b3e7f2..f741315a33 100644 --- a/pcsx2/Sio.cpp +++ b/pcsx2/Sio.cpp @@ -29,7 +29,34 @@ static const mc_command_0x26_tag mc_sizeinfo_8mb= {'+', 512, 16, 0x4000, 0x52, 0 // Ejection timeout management belongs in the MemoryCardFile plugin, except the plugin // interface is not yet complete. + +// FORCED_MCD_EJECTION_TIMEOUT is used internally when loading a savestate. +// FORCED_MCD_EJECTION_TIMEOUT_SHORT is used for SetForceMcdEjectTimeoutNow() which is called from outside (e.g., the mcd manager). +#define FORCED_MCD_EJECTION_TIMEOUT 128 +#define FORCED_MCD_EJECTION_TIMEOUT_SHORT 64 static int m_ForceEjectionTimeout[2]; +static int m_debug_lastForceEjectionTimeout[2] ={0}; + +wxString GetTimeMsStr(){ + wxDateTime unow=wxDateTime::UNow(); + wxString res; + res.Printf(L"%s.%03d", unow.Format(L"%H:%M:%S").c_str(), (int)unow.GetMillisecond() ); + return res; +} +void _SetForceMcdEjectTimeoutNow(int port, int slot, int mcdEjectTimeoutInSioAccesses) +{ + m_ForceEjectionTimeout[port]=mcdEjectTimeoutInSioAccesses; +} + +//allow timeout also for the mcd manager panel +void SetForceMcdEjectTimeoutNow() +{ + const int slot=0; + int port=0; + for (port=0; port<2; port++) + _SetForceMcdEjectTimeoutNow(port, slot, FORCED_MCD_EJECTION_TIMEOUT_SHORT); +} + // SIO Inline'd IRQs : Calls the SIO interrupt handlers directly instead of // feeding them through the IOP's branch test. (see SIO.H for details) @@ -670,10 +697,17 @@ void InitializeSIO(u8 value) // (ejection is only supported for the default non-multitap cards at this time) bool forceEject = false; - if( slot == 0 && m_ForceEjectionTimeout[port] ) + if( slot == 0 && m_ForceEjectionTimeout[port]>0 ) { + if( m_debug_lastForceEjectionTimeout[port] == 0 && SysPlugins.McdIsPresent( port, slot ) ) + Console.Warning( L"[%s] Auto-ejecting memcard [port:%d, slot:%d]", GetTimeMsStr().c_str(), port, slot ); + --m_ForceEjectionTimeout[port]; forceEject = true; + + if( m_ForceEjectionTimeout[port] == 0 && SysPlugins.McdIsPresent( port, slot )) + Console.Warning( L"[%s] Re-inserting auto-ejected memcard [port:%d, slot:%d]", GetTimeMsStr().c_str(), port, slot); + m_debug_lastForceEjectionTimeout[port] = m_ForceEjectionTimeout[port]; } if( !forceEject && SysPlugins.McdIsPresent( port, slot ) ) @@ -771,7 +805,8 @@ void SaveStateBase::sioFreeze() if( newCRC != m_mcdCRCs[port][slot] ) { //m_mcdCRCs[port][slot] = newCRC; - m_ForceEjectionTimeout[port] = 128; + //m_ForceEjectionTimeout[port] = 128; + _SetForceMcdEjectTimeoutNow(port, slot, FORCED_MCD_EJECTION_TIMEOUT); } } } diff --git a/pcsx2/Sio.h b/pcsx2/Sio.h index fba2f7ad44..1ddb89ec41 100644 --- a/pcsx2/Sio.h +++ b/pcsx2/Sio.h @@ -67,4 +67,4 @@ extern void sioWrite8(u8 value); extern void sioWriteCtrl16(u16 value); extern void sioInterrupt(); extern void InitializeSIO(u8 value); - +extern void SetForceMcdEjectTimeoutNow(); diff --git a/pcsx2/gui/ApplyState.h b/pcsx2/gui/ApplyState.h index 60cf326d8d..2589497694 100644 --- a/pcsx2/gui/ApplyState.h +++ b/pcsx2/gui/ApplyState.h @@ -184,6 +184,10 @@ public: // If no exceptions are thrown, then the operation is assumed a success. :) virtual void Apply()=0; + //Enable the apply button manually if required (in case the auto-trigger doesn't kick in, e.g. when clicking a button) + void SomethingChanged(); + + void Init(); // Mandatory override: As a rule for proper interface design, all deriving classes need diff --git a/pcsx2/gui/Dialogs/ConfigurationDialog.h b/pcsx2/gui/Dialogs/ConfigurationDialog.h index 7038f003d3..566341ee9d 100644 --- a/pcsx2/gui/Dialogs/ConfigurationDialog.h +++ b/pcsx2/gui/Dialogs/ConfigurationDialog.h @@ -209,7 +209,6 @@ namespace Dialogs class CreateMemoryCardDialog : public wxDialogWithHelpers { protected: - uint m_slot; wxDirName m_mcdpath; wxString m_mcdfile; wxTextCtrl* m_text_filenameInput; @@ -223,12 +222,14 @@ namespace Dialogs public: virtual ~CreateMemoryCardDialog() throw() {} - //CreateMemoryCardDialog( wxWindow* parent, uint port, uint slot, const wxString& filepath=wxEmptyString ); - CreateMemoryCardDialog( wxWindow* parent, uint slot, const wxDirName& mcdpath, const wxString& suggested_mcdfileName); + CreateMemoryCardDialog( wxWindow* parent, const wxDirName& mcdpath, const wxString& suggested_mcdfileName); + //duplicate of MemoryCardFile::Create. Don't know why the existing method isn't used. - avih + static bool CreateIt( const wxString& mcdFile, uint sizeInMB ); wxString result_createdMcdFilename; //wxDirName GetPathToMcds() const; + protected: void CreateControls(); void OnOk_Click( wxCommandEvent& evt ); diff --git a/pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp b/pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp index d43f88125f..f496953de7 100644 --- a/pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp +++ b/pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp @@ -36,15 +36,14 @@ wxFilePickerCtrl* CreateMemoryCardFilePicker( wxWindow* parent, uint portidx, ui } */ -Dialogs::CreateMemoryCardDialog::CreateMemoryCardDialog( wxWindow* parent, uint slot, const wxDirName& mcdpath, const wxString& suggested_mcdfileName) +Dialogs::CreateMemoryCardDialog::CreateMemoryCardDialog( wxWindow* parent, const wxDirName& mcdpath, const wxString& suggested_mcdfileName) : wxDialogWithHelpers( parent, _("Create a new memory card file") ) - , m_mcdpath( mcdpath.IsOk() ? mcdpath : (wxDirName)g_Conf->Mcd[slot].Filename.GetPath() ) + , m_mcdpath( mcdpath ) , m_mcdfile( suggested_mcdfileName )//suggested_and_result_mcdfileName.IsEmpty() ? g_Conf->Mcd[slot].Filename.GetFullName() { SetMinWidth( 472 ); //m_filepicker = NULL; - m_slot = slot; CreateControls(); @@ -94,7 +93,8 @@ Dialogs::CreateMemoryCardDialog::CreateMemoryCardDialog( wxWindow* parent, uint *this += s_padding | StdExpand(); - Connect( wxID_OK, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CreateMemoryCardDialog::OnOk_Click ) ); + Connect( wxID_OK, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CreateMemoryCardDialog::OnOk_Click ) ); + Connect( m_text_filenameInput->GetId(), wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( CreateMemoryCardDialog::OnOk_Click ) ); m_text_filenameInput->SetFocus(); m_text_filenameInput->SelectAll(); @@ -108,7 +108,7 @@ wxDirName Dialogs::CreateMemoryCardDialog::GetPathToMcds() const // When this GUI is moved into the FileMemoryCard plugin (where it eventually belongs), // this function will be removed and the MemoryCardFile::Create() function will be used // instead. -static bool CreateIt( const wxString& mcdFile, uint sizeInMB ) +bool Dialogs::CreateMemoryCardDialog::CreateIt( const wxString& mcdFile, uint sizeInMB ) { //int enc[16] = {0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0,0,0,0}; @@ -183,7 +183,7 @@ void Dialogs::CreateMemoryCardDialog::CreateControls() ) ); - m_text_filenameInput = new wxTextCtrl( this, wxID_ANY); + m_text_filenameInput = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER); // Initial value of the checkbox is saved between calls to the dialog box. If the user checks // the option, it remains checked for future dialog. If the user unchecks it, ditto. diff --git a/pcsx2/gui/Dialogs/McdConfigDialog.cpp b/pcsx2/gui/Dialogs/McdConfigDialog.cpp index 02f5b67c0e..d305f510c0 100644 --- a/pcsx2/gui/Dialogs/McdConfigDialog.cpp +++ b/pcsx2/gui/Dialogs/McdConfigDialog.cpp @@ -98,19 +98,31 @@ Dialogs::McdConfigDialog::McdConfigDialog( wxWindow* parent ) m_panel_mcdlist = new MemoryCardListPanel_Simple( this ); m_needs_suspending = false; - // [TODO] : Plan here is to add an advanced tab which gives the user the ability - // to configure the names of each memory card slot. - wxString title=_("Drag card files in the list to swap or copy between ports."); - title+=_("\n\nNote: 'Rename' and 'Delete' require to apply pending changes first."); - title+=_("\nAlso, 'Create', 'Rename' and 'Delete' will NOT be reverted when clicking 'Cancel'."); - *this += Heading(title) | StdExpand(); - *this += StdPadding; + wxFlexGridSizer* s_flex=new wxFlexGridSizer(3,1, 0, 0); + s_flex->AddGrowableCol(0); + s_flex->AddGrowableRow(1); + + //set own sizer to s_flex (3-rows-1-col table with growable width and growable middle-row-height) + // instead of the default vertical sizer which cannot expand vertically. + // (vertical sizers can expand horizontally and consume the minimum vertical height possible) + SetSizer(s_flex); - *this += m_panel_mcdlist | StdExpand(); - //*this += StdPadding; - //*this += new wxStaticLine( this ) | StdExpand(); - *this += StdPadding; - *this += new McdConfigPanel_Toggles( this ) | StdExpand(); + wxBoxSizer* s_top = new wxBoxSizer(wxVERTICAL); + + wxString title=_("Drag card files in the list to swap or copy between ports."); + title+=_("\nNote: Rename/Copy/Create/Delete will NOT be reverted with 'Cancel'."); + + *s_top += Heading(title) | StdExpand(); + *s_top += StdPadding; + + *this += s_top | StdExpand(); + *this+= m_panel_mcdlist | StdExpand(); + + wxBoxSizer* s_bottom = new wxBoxSizer(wxVERTICAL); + *s_bottom += StdPadding; + *s_bottom += new McdConfigPanel_Toggles( this ) | StdExpand(); + + *this+= s_bottom | StdExpand(); for( uint i=0; i<2; ++i ) { @@ -118,7 +130,12 @@ Dialogs::McdConfigDialog::McdConfigDialog( wxWindow* parent ) Connect( check->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(McdConfigDialog::OnMultitapClicked) ); } - AddOkCancel(); + AddOkCancel(s_bottom); + + //make this dialog fit to current elements (else can be shrinked too much) + // [There seem to be a bug in wxWidgets which prevents Fit() to succeed by itself, + // So using the "bigger" method: SetSizerAndFit, with existing sizer (set earlier to s_flex) - avih] + SetSizerAndFit(GetSizer()); } void Dialogs::McdConfigDialog::OnMultitapClicked( wxCommandEvent& evt ) diff --git a/pcsx2/gui/Panels/BaseApplicableConfigPanel.cpp b/pcsx2/gui/Panels/BaseApplicableConfigPanel.cpp index b4a917a4a1..bf844f936e 100644 --- a/pcsx2/gui/Panels/BaseApplicableConfigPanel.cpp +++ b/pcsx2/gui/Panels/BaseApplicableConfigPanel.cpp @@ -198,6 +198,13 @@ void BaseApplicableConfigPanel::OnSettingsApplied( wxCommandEvent& evt ) void BaseApplicableConfigPanel::AppStatusEvent_OnSettingsApplied() {} +void BaseApplicableConfigPanel::SomethingChanged() +{ + wxCommandEvent change(pxEvt_SomethingChanged); + AddPendingEvent(change); +} + + BaseApplicableConfigPanel_SpecificConfig::BaseApplicableConfigPanel_SpecificConfig(wxWindow* parent, wxOrientation orient) : BaseApplicableConfigPanel( parent, orient ) { @@ -208,3 +215,4 @@ BaseApplicableConfigPanel_SpecificConfig::BaseApplicableConfigPanel_SpecificConf { } + diff --git a/pcsx2/gui/Panels/MemoryCardListPanel.cpp b/pcsx2/gui/Panels/MemoryCardListPanel.cpp index 90b9138c4a..91a2fe46e6 100644 --- a/pcsx2/gui/Panels/MemoryCardListPanel.cpp +++ b/pcsx2/gui/Panels/MemoryCardListPanel.cpp @@ -23,6 +23,7 @@ #include "Dialogs/ConfigurationDialog.h" #include "Utilities/IniInterface.h" +#include "../../Sio.h" #include #include @@ -169,6 +170,11 @@ void Panels::BaseMcdListPanel::CreateLayout() { //if( m_listview ) m_listview->SetMinSize( wxSize( 480, 140 ) ); + wxFlexGridSizer* s_flex=new wxFlexGridSizer(3,1, 0, 0); + s_flex->AddGrowableCol(0); + s_flex->AddGrowableRow(1); + SetSizer(s_flex); + wxBoxSizer& s_buttons(*new wxBoxSizer( wxHORIZONTAL )); s_leftside_buttons = new wxBoxSizer( wxHORIZONTAL ); s_rightside_buttons = new wxBoxSizer( wxHORIZONTAL ); @@ -178,7 +184,11 @@ void Panels::BaseMcdListPanel::CreateLayout() s_buttons += s_rightside_buttons | pxAlignRight; if( m_FolderPicker ) *this += m_FolderPicker | pxExpand; + else *this += StdPadding;//we need the 'else' because we need these items to land into the proper rows of s_flex. + if( m_listview ) *this += m_listview | pxExpand; + else *this += StdPadding; + *this += s_buttons | pxExpand; *s_leftside_buttons += m_btn_Refresh; @@ -446,52 +456,11 @@ public: Msgbox::Alert(success, _("Success")); dest.IsPresent=true; dest.IsEnabled = true;//src.IsEnabled; + m_listview->GetMcdProvider().PublicApply(); } else if( wxDragMove == def ) - { - /* - - // Move always performs a swap :) - - const bool srcExists( srcfile.FileExists() ); - const bool destExists( destfile.FileExists() ); - - if( destExists && srcExists) - { - wxFileName tempname; - tempname.AssignTempFileName( basepath.ToString() ); - - // Neat trick to handle errors. - result = result && wxRenameFile( srcfile.GetFullPath(), tempname.GetFullPath(), true ); - result = result && wxRenameFile( destfile.GetFullPath(), srcfile.GetFullPath(), false ); - result = result && wxRenameFile( tempname.GetFullPath(), destfile.GetFullPath(), true ); - } - else if( destExists ) - { - result = wxRenameFile( destfile.GetFullPath(), srcfile.GetFullPath() ); - } - else if( srcExists ) - { - result = wxRenameFile( srcfile.GetFullPath(), destfile.GetFullPath() ); - } - - // Swap isEnabled state since both files got exchanged - bool temp = dest.IsEnabled; - dest.IsEnabled = src.IsEnabled; - src.IsEnabled = temp; - - if( !result ) - { - // TODO : Popup an error to the user. - - Console.Error( "(FileMcd) memory card files swap failed." ); - Console.Indent().WriteLn( L"Src : " + srcfile.GetFullPath() ); - Console.Indent().WriteLn( L"Dest: " + destfile.GetFullPath() ); - } - */ - - // avih: old implementation above was swapping file contents (by actually switching the file names of 2 files) - // New implementation just swaps the assigned file names at the slots. + {// move/swap files in ports + // Just swaps the assigned file names at the slots. //Note: each slot has 2 important properties: IsPresent (with Filename) and IsEnabled. // For the sake of usability, when draggind src to dest, if src IsPresent, automatically enable dest. @@ -561,24 +530,25 @@ Panels::MemoryCardListPanel_Simple::MemoryCardListPanel_Simple( wxWindow* parent *s_leftside_buttons += m_button_Rename; *s_leftside_buttons += 2; *s_leftside_buttons += m_button_Create; + SetSizerAndFit(GetSizer()); parent->SetWindowStyle(parent->GetWindowStyle() | wxRESIZE_BORDER); Connect( m_listview->GetId(), wxEVT_COMMAND_LIST_BEGIN_DRAG, wxListEventHandler(MemoryCardListPanel_Simple::OnListDrag)); Connect( m_listview->GetId(), wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler(MemoryCardListPanel_Simple::OnListSelectionChanged)); + Connect( m_listview->GetId(), wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler(MemoryCardListPanel_Simple::OnItemActivated));//enter or double click - //Deselected is not working for some reason (e.g. when clicking an empty row at the table) - avih + //Deselected is not working for some reason (e.g. when clicking an empty row at the table?) - avih Connect( m_listview->GetId(), wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEventHandler(MemoryCardListPanel_Simple::OnListSelectionChanged)); Connect( m_listview->GetId(), wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, wxListEventHandler(MemoryCardListPanel_Simple::OnOpenItemContextMenu) ); Connect( m_button_Mount->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MemoryCardListPanel_Simple::OnMountCard)); - Connect( m_button_Create->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MemoryCardListPanel_Simple::OnCreateCard)); + Connect( m_button_Create->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MemoryCardListPanel_Simple::OnCreateOrDeleteCard)); Connect( m_button_Rename->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MemoryCardListPanel_Simple::OnRenameFile)); // Popup Menu Connections! - - Connect( McdMenuId_Create, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MemoryCardListPanel_Simple::OnCreateCard) ); + Connect( McdMenuId_Create, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MemoryCardListPanel_Simple::OnCreateOrDeleteCard) ); Connect( McdMenuId_Mount, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MemoryCardListPanel_Simple::OnMountCard) ); Connect( McdMenuId_Rename, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MemoryCardListPanel_Simple::OnRenameFile) ); Connect( McdMenuId_RefreshList, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MemoryCardListPanel_Simple::OnRefreshSelections) ); @@ -640,6 +610,9 @@ void Panels::MemoryCardListPanel_Simple::Apply() else g_Conf->Mcd[slot].Filename = L""; } + + SetForceMcdEjectTimeoutNow(); + } void Panels::MemoryCardListPanel_Simple::AppStatusEvent_OnSettingsApplied() @@ -648,7 +621,27 @@ void Panels::MemoryCardListPanel_Simple::AppStatusEvent_OnSettingsApplied() { m_Cards[slot].IsEnabled = g_Conf->Mcd[slot].Enabled; m_Cards[slot].Filename = g_Conf->Mcd[slot].Filename; + + //automatically create the enabled but non-existing file such that it can be managed (else will get created anyway on boot) + wxString targetFile = (GetMcdPath() + m_Cards[slot].Filename.GetFullName()).GetFullPath(); + if ( m_Cards[slot].IsEnabled && !wxFileExists( targetFile ) ) + { + wxString errMsg; + if (isValidNewFilename(m_Cards[slot].Filename.GetFullName(), GetMcdPath(), errMsg, 5)) + { + if ( !Dialogs::CreateMemoryCardDialog::CreateIt(targetFile, 8) ) + Console.Error( L"Automatic createion of MCD '%s' failed. Hope for the best...", targetFile.c_str() ); + else + Console.WriteLn( L"memcard created: '%s'.", targetFile.c_str() ); + } + else + { + Console.Error( L"memcard was enabled but had an invalid file name. Aborting automatic creation. Hope for the best..." ); + } + } + } + DoRefresh(); _parent::AppStatusEvent_OnSettingsApplied(); } @@ -690,80 +683,141 @@ void Panels::MemoryCardListPanel_Simple::DoRefresh() UpdateUI(); } -void Panels::MemoryCardListPanel_Simple::OnCreateCard(wxCommandEvent& evt) +void Panels::MemoryCardListPanel_Simple::UiCreateNewCard( McdSlotItem& card ) { + if( card.IsPresent ){ + Console.WriteLn("Error: Aborted: create mcd invoked but but a file is already associated."); + return; + } + ScopedCoreThreadClose closed_core; + Dialogs::CreateMemoryCardDialog dialog( this, m_FolderPicker->GetPath(), L"my memory card" ); + wxWindowID result = dialog.ShowModal(); + + if (result != wxID_CANCEL) + { + card.IsEnabled = true; + card.Filename = dialog.result_createdMcdFilename; + card.IsPresent = true; + Console.WriteLn(L"setting new card to slot %u: '%s'", card.Slot, card.Filename.GetFullName().c_str()); + } + else + card.IsEnabled=false; + + Apply(); + RefreshSelections(); + closed_core.AllowResume(); +} + + +void Panels::MemoryCardListPanel_Simple::UiDeleteCard( McdSlotItem& card ) +{ + if( !card.IsPresent ){ + Console.WriteLn("Error: Aborted: delete mcd invoked but but a file is not associated."); + return; + } + + ScopedCoreThreadClose closed_core; + + bool result = true; + if( card.IsFormatted ) + { + wxString content; + content.Printf( + pxE( "!Notice:Mcd:Delete", + L"You are about to delete the formatted memory card file '%s' [=slot %u]. " + L"All data on this card will be lost! Are you absolutely and quite positively sure?" + ), card.Filename.GetFullName().c_str() + , card.Slot + ); + + result = Msgbox::YesNo( content, _("Delete memory card file?") ); + } + + if( result ) + { + wxFileName fullpath( m_FolderPicker->GetPath() + card.Filename.GetFullName());//g_Conf->Mcd[GetSlotIndexForViewIndex( selectedViewIndex )].Filename.GetFullName() ); + + card.IsEnabled=false; + Apply(); + wxRemoveFile( fullpath.GetFullPath() ); + } + + RefreshSelections(); + closed_core.AllowResume(); +} + +void Panels::MemoryCardListPanel_Simple::UiRenameCard( McdSlotItem& card ) +{ + if( !card.IsPresent ){ + Console.WriteLn("Error: Aborted: Rename mcd invoked but no file is associated."); + return; + } + + const wxDirName basepath( m_listview->GetMcdProvider().GetMcdPath() ); + wxString newFilename; + while (1){ + wxString title; + title.Printf(_("Select a new name for the memory card file '%s'\n( '.ps2' will be added automatically)"), + card.Filename.GetFullName().c_str() + ); + newFilename = wxGetTextFromUser(title, _("Rename memory card file")); + if( newFilename==L"" ) + return; + + newFilename += L".ps2"; + + //check that the name is valid for a new file + wxString errMsg; + if( !isValidNewFilename( newFilename, basepath, errMsg, 5 ) ) + { + wxString message; + message.Printf(_("Error (%s)"), errMsg.c_str()); + Msgbox::Alert( message, _("Rename memory card file") ); + continue; + } + + break; + } + + ScopedCoreThreadClose closed_core; + + bool origEnabled=card.IsEnabled; + card.IsEnabled=false; + Apply(); + if( !wxRenameFile( (basepath + card.Filename).GetFullPath(), (basepath + wxFileName(newFilename)).GetFullPath(), false ) ) + { + card.IsEnabled=origEnabled; + Apply(); + Msgbox::Alert( _("Error: Rename could not be completed.\n"), _("Rename memory card file") ); + + closed_core.AllowResume(); + return; + } + + card.Filename = newFilename; + card.IsEnabled=origEnabled; + Apply(); + + RefreshSelections(); + closed_core.AllowResume(); +} + +void Panels::MemoryCardListPanel_Simple::OnCreateOrDeleteCard(wxCommandEvent& evt) +{ const int selectedViewIndex = m_listview->GetFirstSelected(); if( wxNOT_FOUND == selectedViewIndex ) return; McdSlotItem& card( GetCardForViewIndex(selectedViewIndex) ); if( card.IsPresent ) - {// called for "delete memory card" - - if ( 0<=card.Slot && card.Slot<=7 && card.Filename != g_Conf->Mcd[card.Slot].Filename) - { - Msgbox::Alert( _("Error: Please apply pending changes before proceeding."), _("Delete memory card file") ); - return; - } - - if ( 0<=card.Slot && card.Slot<=7 && g_Conf->Mcd[card.Slot].Enabled ) - { - Msgbox::Alert( _("Error: Memory card file currently in use.\n\n1. Disable this port (if not already disabled).\n2. Click 'Apply'.\n3. Proceed with Delete."), _("Delete memory card file") ); - return; - } - - bool result = true; - if( card.IsFormatted ) - { - wxString content; - content.Printf( - pxE( "!Notice:Mcd:Delete", - L"You are about to delete the formatted memory card file '%s' [=slot %u]. " - L"All data on this card will be lost! Are you absolutely and quite positively sure?" - ), card.Filename.GetFullName().c_str() - , card.Slot - ); - - result = Msgbox::YesNo( content, _("Delete memory card file?") ); - } - - if( result ) - { - wxFileName fullpath( m_FolderPicker->GetPath() + card.Filename.GetFullName());//g_Conf->Mcd[GetSlotIndexForViewIndex( selectedViewIndex )].Filename.GetFullName() ); - wxRemoveFile( fullpath.GetFullPath() ); - } - } + UiDeleteCard( card ); else - {// actually create a file - Dialogs::CreateMemoryCardDialog dialog( this, GetSlotIndexForViewIndex( selectedViewIndex ), m_FolderPicker->GetPath(), L"my memory card" ); - wxWindowID result = dialog.ShowModal(); - //card.IsEnabled = (result != wxID_CANCEL); - if (result != wxID_CANCEL) - { - card.IsEnabled = true; - card.Filename = dialog.result_createdMcdFilename; - card.IsPresent = true; - Console.WriteLn(L"setting new card to slot %u: '%s'", card.Slot, card.Filename.GetFullName().c_str()); - } - else - { - card.IsEnabled=false; - } - } - wxCommandEvent change(pxEvt_SomethingChanged); - this->AddPendingEvent(change);//enable the apply button (the auto-trigger doesn't get triggered here...) - - RefreshSelections(); - closed_core.AllowResume(); + UiCreateNewCard( card ); } -/*void Panels::MemoryCardListPanel_Simple::OnSwapPorts(wxCommandEvent& evt) -{ - -}*/ - +//enable/disapbe port void Panels::MemoryCardListPanel_Simple::OnMountCard(wxCommandEvent& evt) { evt.Skip(); @@ -796,69 +850,29 @@ void Panels::MemoryCardListPanel_Simple::OnRelocateCard(wxCommandEvent& evt) } */ +// enter/double-click +void Panels::MemoryCardListPanel_Simple::OnItemActivated(wxListEvent& evt) +{ + const int viewIndex = m_listview->GetFirstSelected(); + if( wxNOT_FOUND == viewIndex ) return; + McdSlotItem& card( GetCardForViewIndex(viewIndex) ); + + if ( card.IsPresent ) + UiRenameCard( card ); + else + UiCreateNewCard( card );// IsPresent==false can only happen for an internal slot (vs filename on the HD), so a card can be created. +} + void Panels::MemoryCardListPanel_Simple::OnRenameFile(wxCommandEvent& evt) { - //evt.Skip();//what is it used for? - avih - const wxDirName basepath( m_listview->GetMcdProvider().GetMcdPath() ); - const int viewIndex = m_listview->GetFirstSelected(); - if( wxNOT_FOUND == viewIndex ) - return; - + if( wxNOT_FOUND == viewIndex ) return; McdSlotItem& card( GetCardForViewIndex(viewIndex) ); - if( !card.IsPresent ){ - Console.WriteLn("Internal Error: rename mcd invoked but no file is associated. Aborting."); - return; - } - if ( 0<=card.Slot && card.Slot<=7 && card.Filename != g_Conf->Mcd[card.Slot].Filename) - { - Msgbox::Alert( _("Error: Please apply pending changes before proceeding."), _("Rename memory card file") ); - return; - } - - if ( 0<=card.Slot && card.Slot<=7 && g_Conf->Mcd[card.Slot].Enabled) - { - Msgbox::Alert( _("Error: Memory card file currently in use.\n\n1. Disable this port (if not already disabled).\n2. Click 'Apply'.\n3. Proceed with rename.\n4. Don't forget to re-enable this port."), _("Rename memory card file") ); - return; - } - - wxString newFilename; - while (1){ - newFilename = wxGetTextFromUser(_("Select a new name for the memory card file\n( '.ps2' will be added automatically)"), _("Rename memory card file")); - if( newFilename==L"" ) - { - Msgbox::Alert( _("Rename canceled"), _("Rename memory card file") ); - return; - } - newFilename += L".ps2"; - - //check that the name is valid for a new file - wxString errMsg; - if( !isValidNewFilename( newFilename, basepath, errMsg, 5 ) ) - { - wxString message; - message.Printf(_("Error (%s)"), errMsg.c_str()); - Msgbox::Alert( message, _("Rename memory card file") ); - continue; - } - - break; - } - - if( !wxRenameFile( (basepath + card.Filename).GetFullPath(), (basepath + wxFileName(newFilename)).GetFullPath(), false ) ) - { - Msgbox::Alert( _("Error: Rename could not be completed.\n"), _("Rename memory card file") ); - return; - } - - card.Filename = newFilename; - this->DoRefresh(); - - wxCommandEvent change(pxEvt_SomethingChanged); - this->AddPendingEvent(change);//enable the apply button (the auto-trigger doesn't get triggered here...) + UiRenameCard( card ); } + void Panels::MemoryCardListPanel_Simple::OnListDrag(wxListEvent& evt) { int selectionViewIndex = m_listview->GetFirstSelected(); diff --git a/pcsx2/gui/Panels/MemoryCardListView.cpp b/pcsx2/gui/Panels/MemoryCardListView.cpp index 8e3b783403..0f534db4d9 100644 --- a/pcsx2/gui/Panels/MemoryCardListView.cpp +++ b/pcsx2/gui/Panels/MemoryCardListView.cpp @@ -194,7 +194,7 @@ wxListItemAttr* MemoryCardListView_Simple::OnGetItemAttr(long item) const m_ItemAttr = wxListItemAttr(); // Wipe it clean! - if( !it.IsPresent || !it.IsEnabled) + if( it.IsPresent && !it.IsEnabled) m_ItemAttr.SetTextColour( *wxLIGHT_GREY ); /* if( m_TargetedItem == item ) diff --git a/pcsx2/gui/Panels/MemoryCardPanels.h b/pcsx2/gui/Panels/MemoryCardPanels.h index f326c2b715..6c061e005d 100644 --- a/pcsx2/gui/Panels/MemoryCardPanels.h +++ b/pcsx2/gui/Panels/MemoryCardPanels.h @@ -78,6 +78,7 @@ public: virtual McdSlotItem& GetCardForViewIndex( int idx )=0; virtual int GetSlotIndexForViewIndex( int listViewIndex )=0; virtual wxDirName GetMcdPath() const=0; + virtual void PublicApply() =0; }; // -------------------------------------------------------------------------------------- @@ -211,9 +212,10 @@ namespace Panels virtual McdSlotItem& GetCardForViewIndex( int idx ); virtual int GetSlotIndexForViewIndex( int viewIndex ); + virtual void PublicApply(){ Apply(); }; protected: - void OnCreateCard(wxCommandEvent& evt); + void OnCreateOrDeleteCard(wxCommandEvent& evt); void OnMountCard(wxCommandEvent& evt); // void OnRelocateCard(wxCommandEvent& evt); void OnRenameFile(wxCommandEvent& evt); @@ -221,6 +223,7 @@ namespace Panels void OnListDrag(wxListEvent& evt); void OnListSelectionChanged(wxListEvent& evt); void OnOpenItemContextMenu(wxListEvent& evt); + void OnItemActivated(wxListEvent& evt); virtual bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames); @@ -228,6 +231,10 @@ namespace Panels virtual void AppStatusEvent_OnSettingsApplied(); virtual void DoRefresh(); virtual bool ValidateEnumerationStatus(); + + virtual void UiRenameCard( McdSlotItem& card ); + virtual void UiCreateNewCard( McdSlotItem& card ); + virtual void UiDeleteCard( McdSlotItem& card ); }; // --------------------------------------------------------------------------------------