Memory cards manager: allow custom file names (create/rename/copy), still without assigning arbitrary MCD files at the folder. TODO: 1. allow assigning arbitrary files at the folder. 2. GUI cleanups (text alignment on some messages, MCD list vertical stretch..) 3. code cleanups (remove all commented/unused code).

This is a relatively big change of the MCD manager, so I'd appreciate feedback (functionality, translations, bugs, etc).

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4423 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
avihal@gmail.com 2011-03-12 22:58:28 +00:00
parent 0f2e588ba2
commit 2471c483bc
9 changed files with 423 additions and 128 deletions

View File

@ -129,6 +129,7 @@ bool isoFile::Detect( bool readType )
m_blockofs = 0; m_blockofs = 0;
m_type = ISOTYPE_AUDIO; m_type = ISOTYPE_AUDIO;
//BUG: This also detects a memory-card-file as a valid Audio-CD ISO... -avih
return true; return true;
} }

View File

@ -212,8 +212,9 @@ namespace Dialogs
uint m_slot; uint m_slot;
wxDirName m_mcdpath; wxDirName m_mcdpath;
wxString m_mcdfile; wxString m_mcdfile;
wxTextCtrl* m_text_filenameInput;
wxFilePickerCtrl* m_filepicker; //wxFilePickerCtrl* m_filepicker;
pxRadioPanel* m_radio_CardSize; pxRadioPanel* m_radio_CardSize;
#ifdef __WXMSW__ #ifdef __WXMSW__
@ -223,9 +224,10 @@ namespace Dialogs
public: public:
virtual ~CreateMemoryCardDialog() throw() {} virtual ~CreateMemoryCardDialog() throw() {}
//CreateMemoryCardDialog( wxWindow* parent, uint port, uint slot, const wxString& filepath=wxEmptyString ); //CreateMemoryCardDialog( wxWindow* parent, uint port, uint slot, const wxString& filepath=wxEmptyString );
CreateMemoryCardDialog( wxWindow* parent, uint slot, const wxDirName& mcdpath, const wxString& mcdfile=wxEmptyString ); CreateMemoryCardDialog( wxWindow* parent, uint slot, const wxDirName& mcdpath, const wxString& suggested_mcdfileName);
wxDirName GetPathToMcds() const; wxString result_createdMcdFilename;
//wxDirName GetPathToMcds() const;
protected: protected:
void CreateControls(); void CreateControls();

View File

@ -18,14 +18,13 @@
#include "System.h" #include "System.h"
#include "MemoryCardFile.h" #include "MemoryCardFile.h"
//#include <wx/filepicker.h>
#include <wx/filepicker.h>
#include <wx/ffile.h> #include <wx/ffile.h>
using namespace pxSizerFlags; using namespace pxSizerFlags;
extern wxString GetMsg_McdNtfsCompress(); extern wxString GetMsg_McdNtfsCompress();
/*
wxFilePickerCtrl* CreateMemoryCardFilePicker( wxWindow* parent, uint portidx, uint slotidx, const wxString& filename=wxEmptyString ) wxFilePickerCtrl* CreateMemoryCardFilePicker( wxWindow* parent, uint portidx, uint slotidx, const wxString& filename=wxEmptyString )
{ {
return new wxFilePickerCtrl( parent, wxID_ANY, filename, return new wxFilePickerCtrl( parent, wxID_ANY, filename,
@ -36,14 +35,15 @@ wxFilePickerCtrl* CreateMemoryCardFilePicker( wxWindow* parent, uint portidx, ui
); );
} }
*/
Dialogs::CreateMemoryCardDialog::CreateMemoryCardDialog( wxWindow* parent, uint slot, const wxDirName& mcdpath, const wxString& mcdfile ) Dialogs::CreateMemoryCardDialog::CreateMemoryCardDialog( wxWindow* parent, uint slot, const wxDirName& mcdpath, const wxString& suggested_mcdfileName)
: wxDialogWithHelpers( parent, _("Create new memory card") ) : wxDialogWithHelpers( parent, _("Create a new memory card file") )
, m_mcdpath( mcdpath.IsOk() ? mcdpath : (wxDirName)g_Conf->Mcd[slot].Filename.GetPath() ) , m_mcdpath( mcdpath.IsOk() ? mcdpath : (wxDirName)g_Conf->Mcd[slot].Filename.GetPath() )
, m_mcdfile( mcdfile.IsEmpty() ? g_Conf->Mcd[slot].Filename.GetFullName() : mcdfile ) , m_mcdfile( suggested_mcdfileName )//suggested_and_result_mcdfileName.IsEmpty() ? g_Conf->Mcd[slot].Filename.GetFullName()
{ {
SetMinWidth( 472 ); SetMinWidth( 472 );
m_filepicker = NULL; //m_filepicker = NULL;
m_slot = slot; m_slot = slot;
CreateControls(); CreateControls();
@ -65,12 +65,22 @@ Dialogs::CreateMemoryCardDialog::CreateMemoryCardDialog( wxWindow* parent, uint
//s_padding += Heading(_("Select the size for your new memory card.")); //s_padding += Heading(_("Select the size for your new memory card."));
if( m_filepicker ) // if( m_filepicker )
s_padding += m_filepicker | StdExpand(); // s_padding += m_filepicker | StdExpand();
else // else
{ {
s_padding += Heading( _( "New card will be saved to:" ) ) | StdExpand(); s_padding += Heading( _( "New memory card file:" ) ) | StdExpand();
s_padding += Heading( (m_mcdpath + m_mcdfile).GetFullPath() ).Unwrapped() | StdExpand(); s_padding += Heading( wxString(_("At folder: ")) + (m_mcdpath + m_mcdfile).GetPath() ).Unwrapped() | StdExpand();
wxBoxSizer& s_filename( *new wxBoxSizer(wxHORIZONTAL) );
s_filename += Heading( _("Select file name: ")).SetMinWidth(150);
m_text_filenameInput->SetMinSize(wxSize(150,20));
m_text_filenameInput->SetValue ((m_mcdpath + m_mcdfile).GetName());
s_filename += m_text_filenameInput;
s_filename += Heading( L".ps2" );
s_padding += s_filename | wxALIGN_LEFT;
} }
s_padding += m_radio_CardSize | StdExpand(); s_padding += m_radio_CardSize | StdExpand();
@ -85,13 +95,16 @@ Dialogs::CreateMemoryCardDialog::CreateMemoryCardDialog( wxWindow* parent, uint
*this += s_padding | StdExpand(); *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 ) );
}
m_text_filenameInput->SetFocus();
m_text_filenameInput->SelectAll();
}
/*
wxDirName Dialogs::CreateMemoryCardDialog::GetPathToMcds() const wxDirName Dialogs::CreateMemoryCardDialog::GetPathToMcds() const
{ {
return m_filepicker ? (wxDirName)m_filepicker->GetPath() : m_mcdpath; return m_filepicker ? (wxDirName)m_filepicker->GetPath() : m_mcdpath;
} }
*/
// When this GUI is moved into the FileMemoryCard plugin (where it eventually belongs), // 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 // this function will be removed and the MemoryCardFile::Create() function will be used
// instead. // instead.
@ -102,7 +115,7 @@ static bool CreateIt( const wxString& mcdFile, uint sizeInMB )
u8 m_effeffs[528*16]; u8 m_effeffs[528*16];
memset8<0xff>( m_effeffs ); memset8<0xff>( m_effeffs );
Console.WriteLn( L"(FileMcd) Creating new %uMB memory card: " + mcdFile, sizeInMB ); Console.WriteLn( L"(FileMcd) Creating new %uMB memory card file: '%s'", sizeInMB, mcdFile.c_str() );
wxFFile fp( mcdFile, L"wb" ); wxFFile fp( mcdFile, L"wb" );
if( !fp.IsOpened() ) return false; if( !fp.IsOpened() ) return false;
@ -114,6 +127,7 @@ static bool CreateIt( const wxString& mcdFile, uint sizeInMB )
if( fp.Write( m_effeffs, sizeof(m_effeffs) ) == 0 ) if( fp.Write( m_effeffs, sizeof(m_effeffs) ) == 0 )
return false; return false;
} }
return true; return true;
} }
@ -125,18 +139,34 @@ void Dialogs::CreateMemoryCardDialog::OnOk_Click( wxCommandEvent& evt )
#ifdef __WXMSW__ #ifdef __WXMSW__
g_Conf->McdCompressNTFS = m_check_CompressNTFS->GetValue(); g_Conf->McdCompressNTFS = m_check_CompressNTFS->GetValue();
#endif #endif
result_createdMcdFilename=L"_INVALID_FILE_NAME_";
wxString composedName = m_text_filenameInput->GetValue().Trim() + L".ps2";
wxString errMsg;
if( !isValidNewFilename(composedName, m_mcdpath, errMsg, 5) )
{
wxString message;
message.Printf(_("Error (%s)"), errMsg.c_str());
Msgbox::Alert( message, _("Create memory card file") );
m_text_filenameInput->SetFocus();
m_text_filenameInput->SelectAll();
return;
}
wxString fullPath=(m_mcdpath + composedName).GetFullPath();
if( !CreateIt( if( !CreateIt(
m_filepicker ? m_filepicker->GetPath() : (m_mcdpath + m_mcdfile).GetFullPath(), fullPath,
m_radio_CardSize ? m_radio_CardSize->SelectedItem().SomeInt : 8 m_radio_CardSize ? m_radio_CardSize->SelectedItem().SomeInt : 8
) ) ) )
{ {
Msgbox::Alert( Msgbox::Alert(
_("Error: The memory card could not be created."), _("Error: The memory card file could not be created."),
_("memory card creation error") _("Create memory card file")
); );
return; return;
} }
result_createdMcdFilename = composedName;
EndModal( wxID_OK ); EndModal( wxID_OK );
} }
@ -153,6 +183,8 @@ void Dialogs::CreateMemoryCardDialog::CreateControls()
) )
); );
m_text_filenameInput = new wxTextCtrl( this, wxID_ANY);
// Initial value of the checkbox is saved between calls to the dialog box. If the user checks // 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. // the option, it remains checked for future dialog. If the user unchecks it, ditto.
m_check_CompressNTFS->SetValue( g_Conf->McdCompressNTFS ); m_check_CompressNTFS->SetValue( g_Conf->McdCompressNTFS );

View File

@ -48,7 +48,7 @@ Panels::McdConfigPanel_Toggles::McdConfigPanel_Toggles(wxWindow *parent)
for( uint i=0; i<2; ++i ) for( uint i=0; i<2; ++i )
{ {
m_check_Multitap[i] = new pxCheckBox( this, pxsFmt(_("Enable Multitap on Port %u"), i+1) ); m_check_Multitap[i] = new pxCheckBox( this, pxsFmt(_("Use Multitap on Port %u"), i+1) );
m_check_Multitap[i]->SetClientData( (void*)i ); m_check_Multitap[i]->SetClientData( (void*)i );
m_check_Multitap[i]->SetName(pxsFmt( L"CheckBox::Multitap%u", i )); m_check_Multitap[i]->SetName(pxsFmt( L"CheckBox::Multitap%u", i ));
} }
@ -100,8 +100,10 @@ Dialogs::McdConfigDialog::McdConfigDialog( wxWindow* parent )
// [TODO] : Plan here is to add an advanced tab which gives the user the ability // [TODO] : Plan here is to add an advanced tab which gives the user the ability
// to configure the names of each memory card slot. // to configure the names of each memory card slot.
wxString title=_("Drag card files in the list to swap or copy between ports.");
*this += Heading(_("Drag items over other items in the list to swap or copy memory cards.")) | StdExpand(); 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; *this += StdPadding;
*this += m_panel_mcdlist | StdExpand(); *this += m_panel_mcdlist | StdExpand();

View File

@ -15,6 +15,7 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "Utilities/SafeArray.inl" #include "Utilities/SafeArray.inl"
#include <wx/file.h>
#include "MemoryCardFile.h" #include "MemoryCardFile.h"
@ -75,9 +76,9 @@ protected:
wxString GetDisabledMessage( uint slot ) const wxString GetDisabledMessage( uint slot ) const
{ {
return pxE( "!Notice:Mcd:HasBeenDisabled", wxsFormat( return pxE( "!Notice:Mcd:HasBeenDisabled", wxsFormat(
L"The memory card in slot %d has been automatically disabled. You can correct the problem\n" L"The PS2-slot %d has been automatically disabled. You can correct the problem\n"
L"and re-enable the memory card at any time using Config:Memory cards from the main menu.", L"and re-enable it at any time using Config:Memory cards from the main menu.",
slot slot//TODO: translate internal slot index to human-readable slot description
) ); ) );
} }
}; };
@ -272,7 +273,7 @@ s32 FileMemoryCard::Read( uint slot, u8 *dest, u32 adr, int size )
wxFFile& mcfp( m_file[slot] ); wxFFile& mcfp( m_file[slot] );
if( !mcfp.IsOpened() ) if( !mcfp.IsOpened() )
{ {
DevCon.Error( "(FileMcd) Ignoring attempted read from disabled card." ); DevCon.Error( "(FileMcd) Ignoring attempted read from disabled slot." );
memset(dest, 0, size); memset(dest, 0, size);
return 1; return 1;
} }
@ -286,7 +287,7 @@ s32 FileMemoryCard::Save( uint slot, const u8 *src, u32 adr, int size )
if( !mcfp.IsOpened() ) if( !mcfp.IsOpened() )
{ {
DevCon.Error( "(FileMcd) Ignoring attempted save/write to disabled card." ); DevCon.Error( "(FileMcd) Ignoring attempted save/write to disabled slot." );
return 1; return 1;
} }
@ -311,7 +312,7 @@ s32 FileMemoryCard::EraseBlock( uint slot, u32 adr )
if( !mcfp.IsOpened() ) if( !mcfp.IsOpened() )
{ {
DevCon.Error( "MemoryCard: Ignoring erase for disabled card." ); DevCon.Error( "MemoryCard: Ignoring erase for disabled slot." );
return 1; return 1;
} }
@ -509,3 +510,42 @@ struct superblock
u8 card_type; // 0x150 u8 card_type; // 0x150
u8 card_flags; // 0x151 u8 card_flags; // 0x151
}; };
//Tests if a string is a valid name for a new file within a specified directory.
//returns true if:
// - the file name has a minimum length of minNumCharacters chars (default is 5 chars: at least 1 char + '.' + 3-chars extension)
// and - the file name is within the basepath directory (doesn't contain .. , / , \ , etc)
// and - file name doesn't already exist
// and - can be created on current system (it is actually created and deleted for this test).
bool isValidNewFilename( wxString filenameStringToTest, wxDirName atBasePath, wxString& out_errorMessage, uint minNumCharacters)
{
if ( filenameStringToTest.Length()<1 || filenameStringToTest.Length()<minNumCharacters )
{
out_errorMessage = _("File name empty or too short");
return false;
}
if( (atBasePath + wxFileName(filenameStringToTest)).GetFullPath() != (atBasePath + wxFileName(filenameStringToTest).GetFullName()).GetFullPath() ){
out_errorMessage = _("File name outside of required directory");
return false;
}
if ( wxFileExists( (atBasePath + wxFileName(filenameStringToTest)).GetFullPath() ))
{
out_errorMessage = _("File name already exists");
return false;
}
wxFile fp;
if( !fp.Create( (atBasePath + wxFileName(filenameStringToTest)).GetFullPath() ))
{
out_errorMessage = _("The Operating-System prevents this file from being created");
return false;
}
fp.Close();
wxRemoveFile( (atBasePath + wxFileName(filenameStringToTest)).GetFullPath() );
out_errorMessage = L"[OK - New file name is valid]"; //shouldn't be displayed on success, hence not translatable.
return true;
}

View File

@ -25,5 +25,6 @@
extern uint FileMcd_GetMtapPort(uint slot); extern uint FileMcd_GetMtapPort(uint slot);
extern uint FileMcd_GetMtapSlot(uint slot); extern uint FileMcd_GetMtapSlot(uint slot);
extern bool FileMcd_IsMultitapSlot( uint slot ); extern bool FileMcd_IsMultitapSlot( uint slot );
extern wxFileName FileMcd_GetSimpleName(uint slot); //extern wxFileName FileMcd_GetSimpleName(uint slot);
extern wxString FileMcd_GetDefaultName(uint slot); extern wxString FileMcd_GetDefaultName(uint slot);
extern bool isValidNewFilename( wxString filenameStringToTest, wxDirName atBasePath, wxString& out_errorMessage, uint minNumCharacters=5 );

View File

@ -43,7 +43,8 @@ static bool IsMcdFormatted( wxFFile& fhand )
return memcmp( formatted_string, dest, fmtstrlen ) == 0; return memcmp( formatted_string, dest, fmtstrlen ) == 0;
} }
bool EnumerateMemoryCard( McdSlotItem& dest, const wxFileName& filename ) //sets IsPresent if the file is valid, and derived properties (filename, formatted, size, etc)
bool EnumerateMemoryCard( McdSlotItem& dest, const wxFileName& filename, const wxDirName basePath )
{ {
dest.IsFormatted = false; dest.IsFormatted = false;
dest.IsPresent = false; dest.IsPresent = false;
@ -62,6 +63,9 @@ bool EnumerateMemoryCard( McdSlotItem& dest, const wxFileName& filename )
dest.IsPresent = true; dest.IsPresent = true;
dest.Filename = filename; dest.Filename = filename;
if( filename.GetFullPath() == (basePath+filename.GetFullName()).GetFullPath() )
dest.Filename = filename.GetFullName();
dest.SizeInMB = (uint)(mcdFile.Length() / (1024 * 528 * 2)); dest.SizeInMB = (uint)(mcdFile.Length() / (1024 * 528 * 2));
dest.IsFormatted = IsMcdFormatted( mcdFile ); dest.IsFormatted = IsMcdFormatted( mcdFile );
filename.GetTimes( NULL, &dest.DateModified, &dest.DateCreated ); filename.GetTimes( NULL, &dest.DateModified, &dest.DateCreated );
@ -230,7 +234,7 @@ public:
uint GetViewIndex() const uint GetViewIndex() const
{ {
pxAssumeDev( m_viewIndex >= 0, "memory card Index is uninitialized (invalid drag&drop object state)" ); pxAssumeDev( m_viewIndex >= 0, "memory card view-Index is uninitialized (invalid drag&drop object state)" );
return (uint)m_viewIndex; return (uint)m_viewIndex;
} }
@ -349,15 +353,13 @@ public:
m_listview->GetMcdProvider().RefreshMcds(); m_listview->GetMcdProvider().RefreshMcds();
return result; return result;
} }
virtual wxDragResult OnDropMcd( McdSlotItem& src, McdSlotItem& dest, wxDragResult def ) virtual wxDragResult OnDropMcd( McdSlotItem& src, McdSlotItem& dest, wxDragResult def )
{ {
if( src.Slot == dest.Slot ) return wxDragNone; if( src.Slot == dest.Slot ) return wxDragNone;
if( !pxAssert( (src.Slot >= 0) && (dest.Slot >= 0) ) ) return wxDragNone; if( !pxAssert( (src.Slot >= 0) && (dest.Slot >= 0) ) ) return wxDragNone;
const wxDirName basepath( m_listview->GetMcdProvider().GetMcdPath() ); const wxDirName basepath( m_listview->GetMcdProvider().GetMcdPath() );
wxFileName srcfile( basepath + g_Conf->Mcd[src.Slot].Filename );
wxFileName destfile( basepath + g_Conf->Mcd[dest.Slot].Filename );
bool result = true; bool result = true;
@ -365,19 +367,56 @@ public:
{ {
// user is force invoking copy mode, which means we need to check the destination // user is force invoking copy mode, which means we need to check the destination
// and prompt if it looks valuable (formatted). // and prompt if it looks valuable (formatted).
if( !src.IsPresent )
{
Msgbox::Alert(_("Failed. Can only copy an existing card file."), _("Copy memory card file"));
return wxDragNone;
}
if ( !dest.IsPresent )
{
while (1){
wxString newFilename=L"";
newFilename = wxGetTextFromUser(_("Select a name for the new memory card file copy\n( '.ps2' will be added automatically)"), _("Copy memory card file"));
if( newFilename==L"" )
{
Msgbox::Alert( _("Copy canceled"), _("Copy memory card file") );
return wxDragNone;
}
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, _("Copy memory card file") );
continue;
}
dest.Filename = newFilename;
break;
}
}
wxFileName srcfile( basepath + src.Filename);//g_Conf->Mcd[src.Slot].Filename );
wxFileName destfile( basepath + dest.Filename);//g_Conf->Mcd[dest.Slot].Filename );
if( dest.IsPresent && dest.IsFormatted ) if( dest.IsPresent && dest.IsFormatted )
{ {
wxString content; wxString content;
content.Printf( content.Printf(
pxE( "!Notice:Mcd:Overwrite", pxE( "!Notice:Mcd:Overwrite",
L"This will copy the entire contents of the memory card file '%s' (=slot %u) to the memory card file '%s' (=slot %u). " L"This will copy the entire contents of memory card file '%s' [=slot %u] to the memory card file '%s' [=slot %u]. "
L"All previous data on the memory card file '%s' will be lost. Are you sure?" ), L"All previous data on memory card file '%s' will be lost. Are you sure?" ),
src.Filename.GetFullName().c_str(), src.Slot, src.Filename.GetFullName().c_str(), src.Slot,
dest.Filename.GetFullName().c_str(), dest.Slot, dest.Filename.GetFullName().c_str(), dest.Slot,
dest.Filename.GetFullName().c_str(), dest.Slot dest.Filename.GetFullName().c_str(), dest.Slot
); );
result = Msgbox::YesNo( content, _("Overwrite memory card?") ); result = Msgbox::YesNo( content, _("Overwrite memory card file?") );
if (!result) if (!result)
return wxDragNone; return wxDragNone;
@ -388,7 +427,7 @@ public:
{ {
wxString heading; wxString heading;
heading.Printf( pxE( "!Notice:Mcd:Copy Failed", heading.Printf( pxE( "!Notice:Mcd:Copy Failed",
L"Error! Could not copy the memory card into file '%s' (=slot %u). The destination file is in use." ),//xxx L"Error! Copy failed. Destination memory card file '%s' [=slot %u] is in use." ),
dest.Filename.GetFullName().c_str(), dest.Slot dest.Filename.GetFullName().c_str(), dest.Slot
); );
@ -399,10 +438,19 @@ public:
} }
// Destination memcard isEnabled state is the same now as the source's // Destination memcard isEnabled state is the same now as the source's
dest.IsEnabled = src.IsEnabled; wxString success;
success.Printf(_("Memory card file '%s' copied to '%s'.\n\nBoth card files are now identical."),
src.Filename.GetFullName().c_str(),
dest.Filename.GetFullName().c_str()
);
Msgbox::Alert(success, _("Success"));
dest.IsPresent=true;
dest.IsEnabled = true;//src.IsEnabled;
} }
else if( wxDragMove == def ) else if( wxDragMove == def )
{ {
/*
// Move always performs a swap :) // Move always performs a swap :)
const bool srcExists( srcfile.FileExists() ); const bool srcExists( srcfile.FileExists() );
@ -436,10 +484,32 @@ public:
{ {
// TODO : Popup an error to the user. // TODO : Popup an error to the user.
Console.Error( "(FileMcd) memory card swap failed." ); Console.Error( "(FileMcd) memory card files swap failed." );
Console.Indent().WriteLn( L"Src : " + srcfile.GetFullPath() ); Console.Indent().WriteLn( L"Src : " + srcfile.GetFullPath() );
Console.Indent().WriteLn( L"Dest: " + destfile.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.
//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.
// However, src slot keeps its old IsEnabled regardless of what happened.
if (src.IsPresent || dest.IsPresent)
{
//swap file names (along with IsPresent)
wxFileName tmpFilename = dest.Filename;
bool tmpPresent = dest.IsPresent;
dest.Filename = src.Filename;
dest.IsPresent = src.IsPresent;
if( src.IsPresent )
dest.IsEnabled = true;
src.Filename = tmpFilename;
src.IsPresent = tmpPresent;
}
} }
return def; return def;
@ -450,13 +520,20 @@ enum McdMenuId
{ {
McdMenuId_Create = 0x888, McdMenuId_Create = 0x888,
McdMenuId_Mount, McdMenuId_Mount,
McdMenuId_Relocate, McdMenuId_Rename,
McdMenuId_RefreshList McdMenuId_RefreshList
}; };
// ===================================================================================================== // =====================================================================================================
// MemoryCardListPanel_Simple (implementations) // MemoryCardListPanel_Simple (implementations)
// ===================================================================================================== // =====================================================================================================
/* some code from cotton to enumerate files at a folder:
[21:07] <cotton> ScopedPtr<wxArrayString> memcardList(new wxArrayString());
[21:07] <cotton> wxDir::GetAllFiles(m_FolderPicker->GetPath().ToString(), memcardList, L"*.ps2*", wxDIR_FILES);
[21:07] <cotton> for(uint i = 0; i < memcardList->size(); i++) {
[21:07] <cotton> DevCon.WriteLn(L"hey - " + memcardList[0][i]);
[21:07] <cotton> }
*/
Panels::MemoryCardListPanel_Simple::MemoryCardListPanel_Simple( wxWindow* parent ) Panels::MemoryCardListPanel_Simple::MemoryCardListPanel_Simple( wxWindow* parent )
: _parent( parent ) : _parent( parent )
{ {
@ -467,8 +544,9 @@ Panels::MemoryCardListPanel_Simple::MemoryCardListPanel_Simple( wxWindow* parent
m_listview->SetMinSize(wxSize(m_listview->GetMinWidth(), m_listview->GetCharHeight() * 13)); m_listview->SetMinSize(wxSize(m_listview->GetMinWidth(), m_listview->GetCharHeight() * 13));
m_listview->SetDropTarget( new McdDropTarget(m_listview) ); m_listview->SetDropTarget( new McdDropTarget(m_listview) );
m_button_Create = new wxButton(this, wxID_ANY, _("Create")); m_button_Create = new wxButton(this, wxID_ANY, _("Create card file"));
m_button_Mount = new wxButton(this, wxID_ANY, _("Mount")); m_button_Mount = new wxButton(this, wxID_ANY, _("Enable port"));
m_button_Rename = new wxButton(this, wxID_ANY, _("Rename card file"));
// ------------------------------------ // ------------------------------------
// Sizer / Layout Section // Sizer / Layout Section
@ -476,28 +554,33 @@ Panels::MemoryCardListPanel_Simple::MemoryCardListPanel_Simple( wxWindow* parent
CreateLayout(); CreateLayout();
*s_leftside_buttons += m_button_Create; *s_leftside_buttons += 20;
*s_leftside_buttons += 2;
*s_leftside_buttons += m_button_Mount; *s_leftside_buttons += m_button_Mount;
//*s_leftside_buttons += 2; *s_leftside_buttons += 20;
*s_leftside_buttons += m_button_Rename;
*s_leftside_buttons += 2;
*s_leftside_buttons += m_button_Create;
parent->SetWindowStyle(parent->GetWindowStyle() | wxRESIZE_BORDER); 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_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_SELECTED, wxListEventHandler(MemoryCardListPanel_Simple::OnListSelectionChanged));
//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_DESELECTED, wxListEventHandler(MemoryCardListPanel_Simple::OnListSelectionChanged));
Connect( m_listview->GetId(), wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, wxListEventHandler(MemoryCardListPanel_Simple::OnOpenItemContextMenu) ); 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_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::OnCreateCard));
Connect( m_button_Rename->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MemoryCardListPanel_Simple::OnRenameFile));
// Popup Menu Connections! // Popup Menu Connections!
Connect( McdMenuId_Create, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MemoryCardListPanel_Simple::OnCreateCard) ); Connect( McdMenuId_Create, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MemoryCardListPanel_Simple::OnCreateCard) );
Connect( McdMenuId_Mount, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MemoryCardListPanel_Simple::OnMountCard) ); Connect( McdMenuId_Mount, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MemoryCardListPanel_Simple::OnMountCard) );
Connect( McdMenuId_Relocate, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MemoryCardListPanel_Simple::OnRelocateCard) ); Connect( McdMenuId_Rename, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MemoryCardListPanel_Simple::OnRenameFile) );
Connect( McdMenuId_RefreshList, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MemoryCardListPanel_Simple::OnRefreshSelections) ); Connect( McdMenuId_RefreshList, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MemoryCardListPanel_Simple::OnRefreshSelections) );
} }
@ -511,25 +594,34 @@ void Panels::MemoryCardListPanel_Simple::UpdateUI()
{ {
m_button_Create->Disable(); m_button_Create->Disable();
m_button_Mount->Disable(); m_button_Mount->Disable();
m_button_Rename->Disable();
return; return;
} }
const McdSlotItem& item( GetCardForViewIndex(sel) ); const McdSlotItem& card( GetCardForViewIndex(sel) );
m_button_Rename->Enable( card.IsPresent );
wxString renameTip = _("Rename this memory card file.");
renameTip += wxString(L"\n") + _("Note: Port needs to be disabled first, and the change then needs to be applied." );
pxSetToolTip( m_button_Rename, renameTip );
m_button_Create->Enable(); m_button_Create->Enable();
m_button_Create->SetLabel( item.IsPresent ? _("Delete") : _("Create") ); m_button_Create->SetLabel( card.IsPresent ? _("Delete card file") : _("Create card file") );
wxString deleteTip = _("Permanently delete this memory card file from disk (all contents are lost)");
deleteTip += wxString(L"\n") + _("Note: Port needs to be disabled first, and the change then needs to be applied." );
pxSetToolTip( m_button_Create, pxSetToolTip( m_button_Create,
item.IsPresent card.IsPresent
? _("Deletes the existing memory card from disk (all contents are lost)." ) ? deleteTip
: _("Creates a new memory card in the empty slot." ) : _("Create a new memory card file and assign it to the selected PS2-Port." )
); );
m_button_Mount->Enable( item.IsPresent ); m_button_Mount->Enable( card.IsPresent );
m_button_Mount->SetLabel( item.IsEnabled ? _("Disable") : _("Enable") ); m_button_Mount->SetLabel( card.IsEnabled ? _("Disable Port") : _("Enable Port") );
pxSetToolTip( m_button_Mount, pxSetToolTip( m_button_Mount,
item.IsEnabled card.IsEnabled
? _("Disables the selected memory card, so that it will not be seen by games or BIOS.") ? _("Disable the selected PS2-Port (this memory card will be invisible to games/BIOS).")
: _("Mounts the selected memory card, so that games can see it again.") : _("Enable the selected PS2-Port (games/BIOS will see this memory card).")
); );
} }
@ -544,6 +636,10 @@ void Panels::MemoryCardListPanel_Simple::Apply()
for( uint slot=0; slot<8; ++slot ) for( uint slot=0; slot<8; ++slot )
{ {
g_Conf->Mcd[slot].Enabled = m_Cards[slot].IsEnabled && m_Cards[slot].IsPresent; g_Conf->Mcd[slot].Enabled = m_Cards[slot].IsEnabled && m_Cards[slot].IsPresent;
if (m_Cards[slot].IsPresent)
g_Conf->Mcd[slot].Filename = m_Cards[slot].Filename;
else
g_Conf->Mcd[slot].Filename = L"";
} }
} }
@ -552,11 +648,15 @@ void Panels::MemoryCardListPanel_Simple::AppStatusEvent_OnSettingsApplied()
for( uint slot=0; slot<8; ++slot ) for( uint slot=0; slot<8; ++slot )
{ {
m_Cards[slot].IsEnabled = g_Conf->Mcd[slot].Enabled; m_Cards[slot].IsEnabled = g_Conf->Mcd[slot].Enabled;
m_Cards[slot].Filename = g_Conf->Mcd[slot].Filename;
} }
_parent::AppStatusEvent_OnSettingsApplied(); _parent::AppStatusEvent_OnSettingsApplied();
} }
//BUG: the next function is never reached because, for some reason, IsoDropTarget::OnDropFiles is called instead.
// Interestingly, IsoDropTarget::OnDropFiles actually "detects" a memory card file as a valid Audio-CD ISO... - avih
bool Panels::MemoryCardListPanel_Simple::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames) bool Panels::MemoryCardListPanel_Simple::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames)
{ {
if( filenames.GetCount() == 1 && wxFileName(filenames[0]).IsDir() ) if( filenames.GetCount() == 1 && wxFileName(filenames[0]).IsDir() )
@ -577,10 +677,13 @@ void Panels::MemoryCardListPanel_Simple::DoRefresh()
{ {
for( uint slot=0; slot<8; ++slot ) for( uint slot=0; slot<8; ++slot )
{ {
if( FileMcd_IsMultitapSlot(slot) && !m_MultitapEnabled[FileMcd_GetMtapPort(slot)] ) continue; if( FileMcd_IsMultitapSlot(slot) && !m_MultitapEnabled[FileMcd_GetMtapPort(slot)] )
continue;
//wxFileName fullpath( m_FolderPicker->GetPath() + g_Conf->Mcd[slot].Filename.GetFullName() );
wxFileName fullpath = m_FolderPicker->GetPath() + m_Cards[slot].Filename.GetFullName();
wxFileName fullpath( m_FolderPicker->GetPath() + g_Conf->Mcd[slot].Filename.GetFullName() ); EnumerateMemoryCard( m_Cards[slot], fullpath, m_FolderPicker->GetPath());
EnumerateMemoryCard( m_Cards[slot], fullpath );
m_Cards[slot].Slot = slot; m_Cards[slot].Slot = slot;
} }
@ -598,34 +701,61 @@ void Panels::MemoryCardListPanel_Simple::OnCreateCard(wxCommandEvent& evt)
McdSlotItem& card( GetCardForViewIndex(selectedViewIndex) ); McdSlotItem& card( GetCardForViewIndex(selectedViewIndex) );
if( card.IsPresent ) 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; bool result = true;
if( card.IsFormatted ) if( card.IsFormatted )
{ {
wxString content; wxString content;
content.Printf( content.Printf(
pxE( "!Notice:Mcd:Delete", pxE( "!Notice:Mcd:Delete",
L"You are about to delete the formatted memory card file '%s' (=slot %u). " 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?" L"All data on this card will be lost! Are you absolutely and quite positively sure?"
), card.Filename.GetFullName().c_str() ), card.Filename.GetFullName().c_str()
, card.Slot , card.Slot
); );
result = Msgbox::YesNo( content, _("Delete memory card?") ); result = Msgbox::YesNo( content, _("Delete memory card file?") );
} }
if( result ) if( result )
{ {
wxFileName fullpath( m_FolderPicker->GetPath() + g_Conf->Mcd[GetSlotIndexForViewIndex( selectedViewIndex )].Filename.GetFullName() ); wxFileName fullpath( m_FolderPicker->GetPath() + card.Filename.GetFullName());//g_Conf->Mcd[GetSlotIndexForViewIndex( selectedViewIndex )].Filename.GetFullName() );
wxRemoveFile( fullpath.GetFullPath() ); wxRemoveFile( fullpath.GetFullPath() );
} }
} }
else else
{ {// actually create a file
wxWindowID result = Dialogs::CreateMemoryCardDialog( this, GetSlotIndexForViewIndex( selectedViewIndex ), m_FolderPicker->GetPath() ).ShowModal(); Dialogs::CreateMemoryCardDialog dialog( this, GetSlotIndexForViewIndex( selectedViewIndex ), m_FolderPicker->GetPath(), L"my memory card" );
card.IsEnabled = (result != wxID_CANCEL); 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;
}
} }
this->AddPendingEvent(wxCommandEvent(pxEvt_SomethingChanged));//enable the apply button (the auto-trigger doesn't get triggered here...)
RefreshSelections(); RefreshSelections();
closed_core.AllowResume(); closed_core.AllowResume();
} }
@ -648,7 +778,8 @@ void Panels::MemoryCardListPanel_Simple::OnMountCard(wxCommandEvent& evt)
m_listview->RefreshItem(selectedViewIndex); m_listview->RefreshItem(selectedViewIndex);
UpdateUI(); UpdateUI();
} }
/*
//text dialog: can be used for rename: wxGetTextFromUser - avih
void Panels::MemoryCardListPanel_Simple::OnRelocateCard(wxCommandEvent& evt) void Panels::MemoryCardListPanel_Simple::OnRelocateCard(wxCommandEvent& evt)
{ {
evt.Skip(); evt.Skip();
@ -664,6 +795,69 @@ void Panels::MemoryCardListPanel_Simple::OnRelocateCard(wxCommandEvent& evt)
m_listview->RefreshItem(slot); m_listview->RefreshItem(slot);
UpdateUI(); UpdateUI();
} }
*/
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;
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();
this->AddPendingEvent(wxCommandEvent(pxEvt_SomethingChanged));//enable the apply button (the auto-trigger doesn't get triggered here...)
}
void Panels::MemoryCardListPanel_Simple::OnListDrag(wxListEvent& evt) void Panels::MemoryCardListPanel_Simple::OnListDrag(wxListEvent& evt)
{ {
@ -692,9 +886,12 @@ void Panels::MemoryCardListPanel_Simple::OnOpenItemContextMenu(wxListEvent& evt)
{ {
const McdSlotItem& card( GetCardForViewIndex(idx) ); const McdSlotItem& card( GetCardForViewIndex(idx) );
junk->Append( McdMenuId_Create, card.IsPresent ? _("Delete") : _("Create new...") ); if (card.IsPresent){
junk->Append( McdMenuId_Mount, card.IsEnabled ? _("Disable") : _("Enable") ); junk->Append( McdMenuId_Mount, card.IsEnabled ? _("Disable Port") : _("Enable Port") );
junk->Append( McdMenuId_Relocate, _("Relocate file...") ); junk->Append( McdMenuId_Rename, _("Rename card file...") );
}
junk->Append( McdMenuId_Create, card.IsPresent ? _("Delete card file") : _("Create a new card file...") );
junk->AppendSeparator(); junk->AppendSeparator();
} }
@ -732,8 +929,10 @@ int Panels::MemoryCardListPanel_Simple::GetSlotIndexForViewIndex( int listViewIn
{ {
int targetSlot=-1; int targetSlot=-1;
//this list-view arrangement is mostly kept aligned with the slots indexes, and only takes care /*
//this list-view arrangement is mostly kept aligned with the internal slots indexes, and only takes care
// of the case where MT1 is disabled (hence the MT2 slots 2,3,4 "move backwards" 3 places on the view-index) // of the case where MT1 is disabled (hence the MT2 slots 2,3,4 "move backwards" 3 places on the view-index)
// However, this arrangement it's not very intuitive to use...
if (!m_MultitapEnabled[0] && listViewIndex>=2) if (!m_MultitapEnabled[0] && listViewIndex>=2)
{ {
//we got an MT2 slot. //we got an MT2 slot.
@ -744,31 +943,30 @@ int Panels::MemoryCardListPanel_Simple::GetSlotIndexForViewIndex( int listViewIn
{ {
targetSlot=listViewIndex;//identical view-index and card slot. targetSlot=listViewIndex;//identical view-index and card slot.
} }
*/
//This arrangement of list-view is as follows:
/* //alternative arrangement of list-view: //mcd1(=MT1 port 1)
//mcd1(=MT1 slot 1) //[MT1 port 2,3,4 if MT1 is enabled]
//[MT1 slots 2,3,4 if MT1 is enabled]
//mcd2(=MT2 slot 1) //mcd2(=MT2 slot 1)
//[MT2 slots 2,3,4 if MT2 is enabled] //[MT2 port 2,3,4 if MT2 is enabled]
if (m_MultitapEnabled[0]){ if (m_MultitapEnabled[0]){
//MT1 enabled: //MT1 enabled:
if (1<=listViewIndex && idx<=3){//MT1 slots 2/3/4 move one place backwards if (1<=listViewIndex && listViewIndex<=3){//MT1 ports 2/3/4 move one place backwards
targetSlot=listViewIndex+1; targetSlot=listViewIndex+1;
}else if (listViewIndex==4){//mcd2 (=MT2 slot 1) moves 3 places forward }else if (listViewIndex==4){//mcd2 (=MT2 port 1) moves 3 places forward
targetSlot=1; targetSlot=1;
} else {//mcd1 keeps it's pos as first, MT2 slots keep their pos at the end of the list. } else {//mcd1 keeps it's pos as first, MT2 ports keep their pos at the end of the list.
targetSlot=listViewIndex; targetSlot=listViewIndex;
} }
} else { } else {
//MT1 disabled: mcd1 and mcd2 stay put, MT2 slots 2,3,4 come next (move backwards 3 places) //MT1 disabled: mcd1 and mcd2 stay put, MT2 ports 2,3,4 come next (move backwards 3 places)
if (2<=listViewIndex && listViewIndex<=4) if (2<=listViewIndex && listViewIndex<=4)
targetSlot=listViewIndex+3; targetSlot=listViewIndex+3;
else else
targetSlot=listViewIndex; targetSlot=listViewIndex;
} }
*/
assert(targetSlot>=0); assert(targetSlot>=0);
return targetSlot; return targetSlot;

View File

@ -73,11 +73,11 @@ enum McdColumnType_Simple
{ {
McdColS_PortSlot, // port and slot of the card McdColS_PortSlot, // port and slot of the card
McdColS_Status, // either Enabled/Disabled, or Missing (no card). McdColS_Status, // either Enabled/Disabled, or Missing (no card).
McdColS_Filename,
McdColS_Size, McdColS_Size,
McdColS_Formatted, McdColS_Formatted,
McdColS_DateModified, McdColS_DateModified,
McdColS_DateCreated, McdColS_DateCreated,
McdColS_Filename,
McdColS_Count McdColS_Count
}; };
@ -102,13 +102,13 @@ const ListViewColumnInfo& MemoryCardListView_Simple::GetDefaultColumnInfo( uint
{ {
static const ListViewColumnInfo columns[] = static const ListViewColumnInfo columns[] =
{ {
{ _("PS2 Location") , 140 , wxLIST_FORMAT_CENTER }, { _("PS2 Port") , 140 , wxLIST_FORMAT_LEFT },
{ _("Status") , 96 , wxLIST_FORMAT_CENTER }, { _("Port status") , 96 , wxLIST_FORMAT_LEFT },
{ _("Size") , 72 , wxLIST_FORMAT_LEFT }, { _("File name") , 256 , wxLIST_FORMAT_LEFT },
{ _("Formatted") , 96 , wxLIST_FORMAT_CENTER }, { _("File size") , 72 , wxLIST_FORMAT_LEFT },
{ _("Modified") , 120 , wxLIST_FORMAT_LEFT }, { _("Formatted") , 96 , wxLIST_FORMAT_LEFT },
{ _("Created") , 120 , wxLIST_FORMAT_LEFT }, { _("Last Modified"), 120 , wxLIST_FORMAT_LEFT },
{ _("Filename") , 256 , wxLIST_FORMAT_LEFT }, { _("Created on") , 120 , wxLIST_FORMAT_LEFT },
}; };
pxAssumeDev( idx < ArraySize(columns), "ListView column index is out of bounds." ); pxAssumeDev( idx < ArraySize(columns), "ListView column index is out of bounds." );
@ -128,29 +128,38 @@ wxString MemoryCardListView_Simple::OnGetItemText(long item, long column) const
{ {
if( !m_CardProvider ) return _parent::OnGetItemText(item, column); if( !m_CardProvider ) return _parent::OnGetItemText(item, column);
const McdSlotItem& it( m_CardProvider->GetCardForViewIndex(item) ); const McdSlotItem& it( m_CardProvider->GetCardForViewIndex(item) );
wxString prefix=L" ";
switch( column ) switch( column )
{ {
// case McdColS_PortSlot: return pxsFmt( L"%u", item+1);
case McdColS_PortSlot: case McdColS_PortSlot:
if (!it.IsMultitapSlot()) if (!it.IsMultitapSlot())
return pxsFmt(L"Port-%u or Multitap-%u-Port-1", it.GetMtapPort()+1, it.GetMtapPort()+1); return pxsFmt(wxString(L" ") + _("Port-%u / Multitap-%u--Port-1"), it.GetMtapPort()+1, it.GetMtapPort()+1);
return pxsFmt(L" Multitap-%u-Port-%u", it.GetMtapPort()+1, it.GetMtapSlot()+1); return pxsFmt(wxString(L" ") + _("Multitap-%u--Port-%u"), it.GetMtapPort()+1, it.GetMtapSlot()+1);
case McdColS_Status: return it.IsPresent ? ( it.IsEnabled ? _("Enabled") : _("Disabled")) : _("Missing"); case McdColS_Status:
case McdColS_Size: return it.IsPresent ? pxsFmt( L"%u MB", it.SizeInMB ) : (wxString)_("N/A"); {
case McdColS_Formatted: return it.IsFormatted ? _("Yes") : _("No"); wxString res = prefix + (it.IsEnabled ? _("Enabled") : _("Disabled"));
case McdColS_DateModified: return it.IsPresent ? it.DateModified.FormatDate() : (wxString)_("N/A"); if( !it.IsPresent )
case McdColS_DateCreated: return it.IsPresent ? it.DateCreated.FormatDate() : (wxString)_("N/A"); res = prefix + _("Empty");
return prefix + res;
}
case McdColS_Size: return prefix + ( !it.IsPresent ? L"" : pxsFmt( L"%u MB", it.SizeInMB ) );
case McdColS_Formatted: return prefix + ( !it.IsPresent ? L"" : ( it.IsFormatted ? _("Yes") : _("No")) );
case McdColS_DateModified: return prefix + ( !it.IsPresent ? L"" : it.DateModified.FormatDate() );
case McdColS_DateCreated: return prefix + ( !it.IsPresent ? L"" : it.DateCreated.FormatDate() );
case McdColS_Filename: case McdColS_Filename:
{ {
if (!it.IsPresent) return L"";
wxDirName filepath( it.Filename.GetPath() ); wxDirName filepath( it.Filename.GetPath() );
if (filepath.SameAs(g_Conf->Folders.MemoryCards)) if (filepath.SameAs(g_Conf->Folders.MemoryCards))
return it.Filename.GetFullName(); return prefix + it.Filename.GetFullName();
else else
return it.Filename.GetFullPath(); return prefix + it.Filename.GetFullPath();
} }
} }
@ -185,11 +194,11 @@ wxListItemAttr* MemoryCardListView_Simple::OnGetItemAttr(long item) const
m_ItemAttr = wxListItemAttr(); // Wipe it clean! m_ItemAttr = wxListItemAttr(); // Wipe it clean!
if( !it.IsPresent ) if( !it.IsPresent || !it.IsEnabled)
m_ItemAttr.SetTextColour( *wxLIGHT_GREY ); m_ItemAttr.SetTextColour( *wxLIGHT_GREY );
/*
if( m_TargetedItem == item ) if( m_TargetedItem == item )
m_ItemAttr.SetBackgroundColour( wxColour(L"Wheat") ); m_ItemAttr.SetBackgroundColour( wxColour(L"Wheat") );
*/
return &m_ItemAttr; return &m_ItemAttr;
} }

View File

@ -29,36 +29,43 @@ struct ListViewColumnInfo
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// McdListItem / IMcdList // McdListItem / IMcdList
//
// These are the items at the list-view.
// Each item holds:
// - An internal slot association (or -1 if it isn't associated with an internal slot)
// - Properties of the internal slot (when associated with one)
// - Properties of the file associated with this list item (when associated with one)
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
struct McdSlotItem struct McdSlotItem
{ {
bool IsPresent; int Slot; //0-7: internal slot. -1: unrelated to an internal slot (the rest of the files at the folder).
bool IsEnabled; bool IsPresent; //Whether or not a file is associated with this item (true/false when 0<=Slot<=7. Always true when Slot==-1)
//Only meaningful when IsPresent==true (a file exists for this item):
wxFileName Filename; // full pathname
bool IsFormatted; bool IsFormatted;
uint SizeInMB; // size, in megabytes! uint SizeInMB; // size, in megabytes!
wxDateTime DateCreated; wxDateTime DateCreated;
wxDateTime DateModified; wxDateTime DateModified;
int Slot; //Only meaningful when 0<=Slot<=7 (associated with an internal slot):
// Properties of an internal slot, and translation from internal slot index to ps2 physical port (0-based-indexes).
wxFileName Filename; // full pathname (optional) bool IsEnabled; //This slot is enabled/disabled
McdSlotItem()
{
//Port = -1;
Slot = -1;
IsPresent = false;
IsEnabled = false;
}
bool IsMultitapSlot() const; bool IsMultitapSlot() const;
uint GetMtapPort() const; uint GetMtapPort() const;
uint GetMtapSlot() const; uint GetMtapSlot() const;
bool operator==( const McdSlotItem& right ) const; bool operator==( const McdSlotItem& right ) const;
bool operator!=( const McdSlotItem& right ) const; bool operator!=( const McdSlotItem& right ) const;
McdSlotItem()
{
Slot = -1;
IsPresent = false;
IsEnabled = false;
}
}; };
typedef std::vector<McdSlotItem> McdList; typedef std::vector<McdSlotItem> McdList;
@ -84,7 +91,7 @@ protected:
IMcdList* m_CardProvider; IMcdList* m_CardProvider;
// specifies the target of a drag&drop operation // specifies the target of a drag&drop operation
int m_TargetedItem; int m_TargetedItem;
public: public:
virtual ~BaseMcdListView() throw() { } virtual ~BaseMcdListView() throw() { }
@ -183,7 +190,9 @@ namespace Panels
typedef BaseMcdListPanel _parent; typedef BaseMcdListPanel _parent;
protected: protected:
McdSlotItem m_Cards[8]; McdSlotItem m_Cards[8];
wxButton* m_button_Rename;
// Doubles as Create and Delete buttons // Doubles as Create and Delete buttons
wxButton* m_button_Create; wxButton* m_button_Create;
@ -206,7 +215,8 @@ namespace Panels
protected: protected:
void OnCreateCard(wxCommandEvent& evt); void OnCreateCard(wxCommandEvent& evt);
void OnMountCard(wxCommandEvent& evt); void OnMountCard(wxCommandEvent& evt);
void OnRelocateCard(wxCommandEvent& evt); // void OnRelocateCard(wxCommandEvent& evt);
void OnRenameFile(wxCommandEvent& evt);
void OnListDrag(wxListEvent& evt); void OnListDrag(wxListEvent& evt);
void OnListSelectionChanged(wxListEvent& evt); void OnListSelectionChanged(wxListEvent& evt);