1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxGenericFileDialog 
   4 // Author:      Robert Roebling 
   8 // Copyright:   (c) Robert Roebling 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  13 #pragma implementation "filedlgg.h" 
  16 // For compilers that support precompilation, includes "wx.h". 
  17 #include "wx/wxprec.h" 
  25 // NOTE : it probably also supports MAC, untested 
  26 #if !defined(__UNIX__) && !defined(__DOS__) && !defined(__WIN32__) && !defined(__OS2__) 
  27 #error wxGenericFileDialog currently only supports Unix, win32 and DOS 
  30 #include "wx/checkbox.h" 
  31 #include "wx/textctrl.h" 
  32 #include "wx/choice.h" 
  33 #include "wx/checkbox.h" 
  34 #include "wx/stattext.h" 
  38 #include "wx/msgdlg.h" 
  40 #include "wx/bmpbuttn.h" 
  41 #include "wx/tokenzr.h" 
  42 #include "wx/config.h" 
  43 #include "wx/imaglist.h" 
  45 #include "wx/artprov.h" 
  46 #include "wx/file.h"        // for wxS_IXXX constants only 
  47 #include "wx/filedlg.h"     // wxOPEN, wxSAVE... 
  48 #include "wx/generic/filedlgg.h" 
  49 #include "wx/generic/dirctrlg.h" // for wxFileIconsTable 
  52     #include "wx/tooltip.h" 
  55 #include <sys/types.h> 
  67     #include "wx/msw/wrapwin.h" 
  68     #include "wx/msw/mslu.h" 
  76 #if defined(__UNIX__) || defined(__DOS__) 
  80 // ---------------------------------------------------------------------------- 
  82 // ---------------------------------------------------------------------------- 
  85 int wxCALLBACK 
wxFileDataNameCompare( long data1
, long data2
, long data
) 
  87      wxFileData 
*fd1 
= (wxFileData
*)data1
; 
  88      wxFileData 
*fd2 
= (wxFileData
*)data2
; 
  89      if (fd1
->GetFileName() == wxT("..")) return -data
; 
  90      if (fd2
->GetFileName() == wxT("..")) return data
; 
  91      if (fd1
->IsDir() && !fd2
->IsDir()) return -data
; 
  92      if (fd2
->IsDir() && !fd1
->IsDir()) return data
; 
  93      return data
*wxStrcmp( fd1
->GetFileName(), fd2
->GetFileName() ); 
  97 int wxCALLBACK 
wxFileDataSizeCompare( long data1
, long data2
, long data
) 
  99      wxFileData 
*fd1 
= (wxFileData
*)data1
; 
 100      wxFileData 
*fd2 
= (wxFileData
*)data2
; 
 101      if (fd1
->GetFileName() == wxT("..")) return -data
; 
 102      if (fd2
->GetFileName() == wxT("..")) return data
; 
 103      if (fd1
->IsDir() && !fd2
->IsDir()) return -data
; 
 104      if (fd2
->IsDir() && !fd1
->IsDir()) return data
; 
 105      if (fd1
->IsLink() && !fd2
->IsLink()) return -data
; 
 106      if (fd2
->IsLink() && !fd1
->IsLink()) return data
; 
 107      return data
*(fd1
->GetSize() - fd2
->GetSize()); 
 111 int wxCALLBACK 
wxFileDataTypeCompare( long data1
, long data2
, long data
) 
 113      wxFileData 
*fd1 
= (wxFileData
*)data1
; 
 114      wxFileData 
*fd2 
= (wxFileData
*)data2
; 
 115      if (fd1
->GetFileName() == wxT("..")) return -data
; 
 116      if (fd2
->GetFileName() == wxT("..")) return data
; 
 117      if (fd1
->IsDir() && !fd2
->IsDir()) return -data
; 
 118      if (fd2
->IsDir() && !fd1
->IsDir()) return data
; 
 119      if (fd1
->IsLink() && !fd2
->IsLink()) return -data
; 
 120      if (fd2
->IsLink() && !fd1
->IsLink()) return data
; 
 121      return data
*wxStrcmp( fd1
->GetFileType(), fd2
->GetFileType() ); 
 125 int wxCALLBACK 
wxFileDataTimeCompare( long data1
, long data2
, long data
) 
 127      wxFileData 
*fd1 
= (wxFileData
*)data1
; 
 128      wxFileData 
*fd2 
= (wxFileData
*)data2
; 
 129      if (fd1
->GetFileName() == wxT("..")) return -data
; 
 130      if (fd2
->GetFileName() == wxT("..")) return data
; 
 131      if (fd1
->IsDir() && !fd2
->IsDir()) return -data
; 
 132      if (fd2
->IsDir() && !fd1
->IsDir()) return data
; 
 134      return fd1
->GetDateTime().IsLaterThan(fd2
->GetDateTime()) ? int(data
) : -int(data
); 
 137 #if defined(__UNIX__) && !defined(__OS2__) 
 138 #define IsTopMostDir(dir)   (dir == wxT("/")) 
 141 #if defined(__DOS__) || defined(__WINDOWS__) || defined (__OS2__) 
 142 #define IsTopMostDir(dir)   (dir.IsEmpty()) 
 145 #if defined(__DOS__) || defined(__WINDOWS__) || defined(__OS2__) 
 146 // defined in src/generic/dirctrlg.cpp 
 147 extern bool wxIsDriveAvailable(const wxString
& dirName
); 
 150 // defined in src/generic/dirctrlg.cpp 
 151 extern size_t wxGetAvailableDrives(wxArrayString 
&paths
, wxArrayString 
&names
, wxArrayInt 
&icon_ids
); 
 153 //----------------------------------------------------------------------------- 
 155 //----------------------------------------------------------------------------- 
 157 wxFileData::wxFileData( const wxFileData
& fileData 
) 
 159     m_fileName 
= fileData
.GetFileName(); 
 160     m_filePath 
= fileData
.GetFilePath(); 
 161     m_size 
= fileData
.GetSize(); 
 162     m_dateTime 
= fileData
.GetDateTime(); 
 163     m_permissions 
= fileData
.GetPermissions(); 
 164     m_type 
= fileData
.GetType(); 
 165     m_image 
= GetImageId(); 
 168 wxFileData::wxFileData( const wxString 
&filePath
, const wxString 
&fileName
, fileType type
, int image_id 
) 
 170     m_fileName 
= fileName
; 
 171     m_filePath 
= filePath
; 
 178 void wxFileData::ReadData() 
 186 #if defined(__DOS__) || defined(__WINDOWS__) || defined(__OS2__) 
 187     // c:\.. is a drive don't stat it 
 188     if ((m_fileName 
== wxT("..")) && (m_filePath
.length() <= 5)) 
 194 #endif // __DOS__ || __WINDOWS__ 
 198 #if defined(__UNIX__) && (!defined( __OS2__ ) && !defined(__VMS)) 
 199     lstat( m_filePath
.fn_str(), &buff 
); 
 200     m_type 
|= S_ISLNK( buff
.st_mode 
) != 0 ? is_link 
: 0; 
 202     wxStat( m_filePath
, &buff 
); 
 205     m_type 
|= (buff
.st_mode 
& S_IFDIR
) != 0 ? is_dir 
: 0; 
 206     m_type 
|= (buff
.st_mode 
& wxS_IXUSR
) != 0 ? is_exe 
: 0; 
 208     // try to get a better icon 
 209     if (m_image 
== wxFileIconsTable::file
) 
 212             m_image 
= wxFileIconsTable::executable
; 
 213         else if (m_fileName
.Find(wxT('.'), TRUE
) != wxNOT_FOUND
) 
 214             m_image 
= wxTheFileIconsTable
->GetIconID(m_fileName
.AfterLast(wxT('.'))); 
 217     m_size 
= buff
.st_size
; 
 219     m_dateTime 
= buff
.st_mtime
; 
 221 #if defined(__UNIX__) 
 222     m_permissions
.Printf(_T("%c%c%c%c%c%c%c%c%c"), 
 223                          buff
.st_mode 
& wxS_IRUSR 
? _T('r') : _T('-'), 
 224                          buff
.st_mode 
& wxS_IWUSR 
? _T('w') : _T('-'), 
 225                          buff
.st_mode 
& wxS_IXUSR 
? _T('x') : _T('-'), 
 226                          buff
.st_mode 
& wxS_IRGRP 
? _T('r') : _T('-'), 
 227                          buff
.st_mode 
& wxS_IWGRP 
? _T('w') : _T('-'), 
 228                          buff
.st_mode 
& wxS_IXGRP 
? _T('x') : _T('-'), 
 229                          buff
.st_mode 
& wxS_IROTH 
? _T('r') : _T('-'), 
 230                          buff
.st_mode 
& wxS_IWOTH 
? _T('w') : _T('-'), 
 231                          buff
.st_mode 
& wxS_IXOTH 
? _T('x') : _T('-')); 
 232 #elif defined(__WIN32__) 
 233     DWORD attribs 
= GetFileAttributes(m_filePath
); 
 234     if (attribs 
!= (DWORD
)-1) 
 236         m_permissions
.Printf(_T("%c%c%c%c"), 
 237                              attribs 
& FILE_ATTRIBUTE_ARCHIVE  
? _T('A') : _T(' '), 
 238                              attribs 
& FILE_ATTRIBUTE_READONLY 
? _T('R') : _T(' '), 
 239                              attribs 
& FILE_ATTRIBUTE_HIDDEN   
? _T('H') : _T(' '), 
 240                              attribs 
& FILE_ATTRIBUTE_SYSTEM   
? _T('S') : _T(' ')); 
 245 wxString 
wxFileData::GetFileType() const 
 253    else if (m_fileName
.Find(wxT('.'), TRUE
) != wxNOT_FOUND
) 
 254         return m_fileName
.AfterLast(wxT('.')); 
 256     return wxEmptyString
; 
 259 wxString 
wxFileData::GetModificationTime() const 
 261     // want time as 01:02 so they line up nicely, no %r in WIN32 
 262     return m_dateTime
.FormatDate() + wxT(" ") + m_dateTime
.Format(wxT("%I:%M:%S %p")); 
 265 wxString 
wxFileData::GetHint() const 
 267     wxString s 
= m_filePath
; 
 277         s 
+= wxString::Format( _("%ld bytes"), m_size 
); 
 283         s 
<< GetModificationTime() 
 291 wxString 
wxFileData::GetEntry( fileListFieldType num 
) const 
 301             if (!IsDir() && !IsLink() && !IsDrive()) 
 302                 s
.Printf(_T("%ld"), m_size
); 
 311                 s 
= GetModificationTime(); 
 314 #if defined(__UNIX__) || defined(__WIN32__) 
 318 #endif // defined(__UNIX__) || defined(__WIN32__) 
 321             wxFAIL_MSG( _T("unexpected field in wxFileData::GetEntry()") ); 
 327 void wxFileData::SetNewName( const wxString 
&filePath
, const wxString 
&fileName 
) 
 329     m_fileName 
= fileName
; 
 330     m_filePath 
= filePath
; 
 333 void wxFileData::MakeItem( wxListItem 
&item 
) 
 335     item
.m_text 
= m_fileName
; 
 336     item
.ClearAttributes(); 
 338         item
.SetTextColour(*wxRED
); 
 340         item
.SetTextColour(*wxBLUE
); 
 342     item
.m_image 
= m_image
; 
 346         wxColour dg 
= wxTheColourDatabase
->Find( _T("MEDIUM GREY") ); 
 348             item
.SetTextColour(dg
); 
 350     item
.m_data 
= (long)this; 
 353 //----------------------------------------------------------------------------- 
 355 //----------------------------------------------------------------------------- 
 357 IMPLEMENT_DYNAMIC_CLASS(wxFileCtrl
,wxListCtrl
) 
 359 BEGIN_EVENT_TABLE(wxFileCtrl
,wxListCtrl
) 
 360     EVT_LIST_DELETE_ITEM(-1, wxFileCtrl::OnListDeleteItem
) 
 361     EVT_LIST_END_LABEL_EDIT(-1, wxFileCtrl::OnListEndLabelEdit
) 
 362     EVT_LIST_COL_CLICK(-1, wxFileCtrl::OnListColClick
) 
 366 wxFileCtrl::wxFileCtrl() 
 368     m_showHidden 
= FALSE
; 
 370     m_sort_field 
= wxFileData::FileList_Name
; 
 373 wxFileCtrl::wxFileCtrl(wxWindow 
*win
, 
 375                        const wxString
& wild
, 
 380                        const wxValidator 
&validator
, 
 381                        const wxString 
&name
) 
 382           : wxListCtrl(win
, id
, pos
, size
, style
, validator
, name
), 
 385     wxImageList 
*imageList 
= wxTheFileIconsTable
->GetSmallImageList(); 
 387     SetImageList( imageList
, wxIMAGE_LIST_SMALL 
); 
 389     m_showHidden 
= showHidden
; 
 392     m_sort_field 
= wxFileData::FileList_Name
; 
 394     m_dirName 
= wxT("*"); 
 396     if (style 
& wxLC_REPORT
) 
 397         ChangeToReportMode(); 
 400 void wxFileCtrl::ChangeToListMode() 
 403     SetSingleStyle( wxLC_LIST 
); 
 407 void wxFileCtrl::ChangeToReportMode() 
 410     SetSingleStyle( wxLC_REPORT 
); 
 412     // do this since WIN32 does mm/dd/yy UNIX does mm/dd/yyyy 
 413     // don't hardcode since mm/dd is dd/mm elsewhere 
 415     wxDateTime 
dt(22, wxDateTime::Dec
, 2002, 22, 22, 22); 
 416     wxString txt 
= dt
.FormatDate() + wxT("22") + dt
.Format(wxT("%I:%M:%S %p")); 
 417     GetTextExtent(txt
, &w
, &h
); 
 419     InsertColumn( 0, _("Name"), wxLIST_FORMAT_LEFT
, w 
); 
 420     InsertColumn( 1, _("Size"), wxLIST_FORMAT_LEFT
, w
/2 ); 
 421     InsertColumn( 2, _("Type"), wxLIST_FORMAT_LEFT
, w
/2 ); 
 422     InsertColumn( 3, _("Modified"), wxLIST_FORMAT_LEFT
, w 
); 
 423 #if defined(__UNIX__) 
 424     GetTextExtent(wxT("Permissions 2"), &w
, &h
); 
 425     InsertColumn( 4, _("Permissions"), wxLIST_FORMAT_LEFT
, w 
); 
 426 #elif defined(__WIN32__) 
 427     GetTextExtent(wxT("Attributes 2"), &w
, &h
); 
 428     InsertColumn( 4, _("Attributes"), wxLIST_FORMAT_LEFT
, w 
); 
 434 void wxFileCtrl::ChangeToSmallIconMode() 
 437     SetSingleStyle( wxLC_SMALL_ICON 
); 
 441 void wxFileCtrl::ShowHidden( bool show 
) 
 447 long wxFileCtrl::Add( wxFileData 
*fd
, wxListItem 
&item 
) 
 450     item
.m_mask 
= wxLIST_MASK_TEXT 
+ wxLIST_MASK_DATA 
+ wxLIST_MASK_IMAGE
; 
 451     fd
->MakeItem( item 
); 
 452     long my_style 
= GetWindowStyleFlag(); 
 453     if (my_style 
& wxLC_REPORT
) 
 455         ret 
= InsertItem( item 
); 
 456         for (int i 
= 1; i 
< wxFileData::FileList_Max
; i
++) 
 457             SetItem( item
.m_itemId
, i
, fd
->GetEntry((wxFileData::fileListFieldType
)i
) ); 
 459     else if ((my_style 
& wxLC_LIST
) || (my_style 
& wxLC_SMALL_ICON
)) 
 461         ret 
= InsertItem( item 
); 
 466 void wxFileCtrl::UpdateItem(const wxListItem 
&item
) 
 468     wxFileData 
*fd 
= (wxFileData
*)GetItemData(item
); 
 469     wxCHECK_RET(fd
, wxT("invalid filedata")); 
 473     SetItemText(item
, fd
->GetFileName()); 
 474     SetItemImage(item
, fd
->GetImageId(), fd
->GetImageId()); 
 476     if (GetWindowStyleFlag() & wxLC_REPORT
) 
 478         for (int i 
= 1; i 
< wxFileData::FileList_Max
; i
++) 
 479             SetItem( item
.m_itemId
, i
, fd
->GetEntry((wxFileData::fileListFieldType
)i
) ); 
 483 void wxFileCtrl::UpdateFiles() 
 485     // don't do anything before ShowModal() call which sets m_dirName 
 486     if ( m_dirName 
== wxT("*") ) 
 489     wxBusyCursor bcur
; // this may take a while... 
 498 #if defined(__WINDOWS__) || defined(__DOS__) || defined(__WXMAC__) || defined(__OS2__) 
 499     if ( IsTopMostDir(m_dirName
) ) 
 501         wxArrayString names
, paths
; 
 503         size_t n
, count 
= wxGetAvailableDrives(paths
, names
, icons
); 
 505         for (n
=0; n
<count
; n
++) 
 507             wxFileData 
*fd 
= new wxFileData(paths
[n
], names
[n
], wxFileData::is_drive
, icons
[n
]); 
 513 #endif // defined(__DOS__) || defined(__WINDOWS__) 
 516         if ( !IsTopMostDir(m_dirName
) ) 
 518             wxString 
p(wxPathOnly(m_dirName
)); 
 519 #if defined(__UNIX__) && !defined(__OS2__) 
 520             if (p
.IsEmpty()) p 
= wxT("/"); 
 522             wxFileData 
*fd 
= new wxFileData(p
, wxT(".."), wxFileData::is_dir
, wxFileIconsTable::folder
); 
 527         wxString 
dirname(m_dirName
); 
 528 #if defined(__DOS__) || defined(__WINDOWS__) || defined(__OS2__) 
 529         if (dirname
.length() == 2 && dirname
[1u] == wxT(':')) 
 530             dirname 
<< wxT('\\'); 
 531 #endif // defined(__DOS__) || defined(__WINDOWS__) || defined(__OS2__) 
 534         if ( dir
.IsOpened() ) 
 536             wxString 
dirPrefix(dirname
); 
 537             if (dirPrefix
.Last() != wxFILE_SEP_PATH
) 
 538                 dirPrefix 
+= wxFILE_SEP_PATH
; 
 540             int hiddenFlag 
= m_showHidden 
? wxDIR_HIDDEN 
: 0; 
 545             // Get the directories first (not matched against wildcards): 
 546             cont 
= dir
.GetFirst(&f
, wxEmptyString
, wxDIR_DIRS 
| hiddenFlag
); 
 549                 wxFileData 
*fd 
= new wxFileData(dirPrefix 
+ f
, f
, wxFileData::is_dir
, wxFileIconsTable::folder
); 
 552                 cont 
= dir
.GetNext(&f
); 
 555             // Tokenize the wildcard string, so we can handle more than 1 
 556             // search pattern in a wildcard. 
 557             wxStringTokenizer 
tokenWild(m_wild
, wxT(";")); 
 558             while ( tokenWild
.HasMoreTokens() ) 
 560                 cont 
= dir
.GetFirst(&f
, tokenWild
.GetNextToken(), 
 561                                         wxDIR_FILES 
| hiddenFlag
); 
 564                     wxFileData 
*fd 
= new wxFileData(dirPrefix 
+ f
, f
, wxFileData::is_file
, wxFileIconsTable::file
); 
 567                     cont 
= dir
.GetNext(&f
); 
 573     SortItems(m_sort_field
, m_sort_foward
); 
 576 void wxFileCtrl::SetWild( const wxString 
&wild 
) 
 578     if (wild
.Find(wxT('|')) != wxNOT_FOUND
) 
 585 void wxFileCtrl::MakeDir() 
 587     wxString 
new_name( _("NewName") ); 
 588     wxString 
path( m_dirName 
); 
 589     path 
+= wxFILE_SEP_PATH
; 
 591     if (wxFileExists(path
)) 
 593         // try NewName0, NewName1 etc. 
 596             new_name 
= _("NewName"); 
 598             num
.Printf( wxT("%d"), i 
); 
 602             path 
+= wxFILE_SEP_PATH
; 
 605         } while (wxFileExists(path
)); 
 611         wxMessageDialog 
dialog(this, _("Operation not permitted."), _("Error"), wxOK 
| wxICON_ERROR 
); 
 616     wxFileData 
*fd 
= new wxFileData( path
, new_name
, wxFileData::is_dir
, wxFileIconsTable::folder 
); 
 620     long id 
= Add( fd
, item 
); 
 624         SortItems(m_sort_field
, m_sort_foward
); 
 625         id 
= FindItem( 0, (long)fd 
); 
 631 void wxFileCtrl::GoToParentDir() 
 633     if (!IsTopMostDir(m_dirName
)) 
 635         size_t len 
= m_dirName
.Len(); 
 636         if (wxEndsWithPathSeparator(m_dirName
)) 
 637             m_dirName
.Remove( len
-1, 1 ); 
 638         wxString 
fname( wxFileNameFromPath(m_dirName
) ); 
 639         m_dirName 
= wxPathOnly( m_dirName 
); 
 640 #if defined(__DOS__) || defined(__WINDOWS__) || defined(__OS2__) 
 641         if (!m_dirName
.IsEmpty()) 
 643             if (m_dirName
.Last() == wxT('.')) 
 646 #elif defined(__UNIX__) 
 647         if (m_dirName
.IsEmpty()) 
 648             m_dirName 
= wxT("/"); 
 651         long id 
= FindItem( 0, fname 
); 
 654             SetItemState( id
, wxLIST_STATE_SELECTED
, wxLIST_STATE_SELECTED 
); 
 660 void wxFileCtrl::GoToHomeDir() 
 662     wxString s 
= wxGetUserHome( wxString() ); 
 666 void wxFileCtrl::GoToDir( const wxString 
&dir 
) 
 668     if (!wxDirExists(dir
)) return; 
 672     SetItemState( 0, wxLIST_STATE_SELECTED
, wxLIST_STATE_SELECTED 
); 
 676 void wxFileCtrl::FreeItemData(const wxListItem
& item
) 
 678     wxFileData 
*fd 
= (wxFileData
*)item
.m_data
; 
 682 void wxFileCtrl::OnListDeleteItem( wxListEvent 
&event 
) 
 684     FreeItemData(event
.m_item
); 
 687 void wxFileCtrl::FreeAllItemsData() 
 690     item
.m_mask 
= wxLIST_MASK_DATA
; 
 692     item
.m_itemId 
= GetNextItem( -1, wxLIST_NEXT_ALL 
); 
 693     while ( item
.m_itemId 
!= -1 ) 
 697         item
.m_itemId 
= GetNextItem( item
.m_itemId
, wxLIST_NEXT_ALL 
); 
 701 void wxFileCtrl::OnListEndLabelEdit( wxListEvent 
&event 
) 
 703     wxFileData 
*fd 
= (wxFileData
*)event
.m_item
.m_data
; 
 706     if ((event
.GetLabel().IsEmpty()) || 
 707         (event
.GetLabel() == _(".")) || 
 708         (event
.GetLabel() == _("..")) || 
 709         (event
.GetLabel().First( wxFILE_SEP_PATH 
) != wxNOT_FOUND
)) 
 711         wxMessageDialog 
dialog(this, _("Illegal directory name."), _("Error"), wxOK 
| wxICON_ERROR 
); 
 717     wxString 
new_name( wxPathOnly( fd
->GetFilePath() ) ); 
 718     new_name 
+= wxFILE_SEP_PATH
; 
 719     new_name 
+= event
.GetLabel(); 
 723     if (wxFileExists(new_name
)) 
 725         wxMessageDialog 
dialog(this, _("File name exists already."), _("Error"), wxOK 
| wxICON_ERROR 
); 
 730     if (wxRenameFile(fd
->GetFilePath(),new_name
)) 
 732         fd
->SetNewName( new_name
, event
.GetLabel() ); 
 733         SetItemState( event
.GetItem(), wxLIST_STATE_SELECTED
, wxLIST_STATE_SELECTED 
); 
 734         UpdateItem( event
.GetItem() ); 
 735         EnsureVisible( event
.GetItem() ); 
 739         wxMessageDialog 
dialog(this, _("Operation not permitted."), _("Error"), wxOK 
| wxICON_ERROR 
); 
 745 void wxFileCtrl::OnListColClick( wxListEvent 
&event 
) 
 747     int col 
= event
.GetColumn(); 
 751         case wxFileData::FileList_Name 
: 
 752         case wxFileData::FileList_Size 
: 
 753         case wxFileData::FileList_Type 
: 
 754         case wxFileData::FileList_Time 
: break; 
 758     if ((wxFileData::fileListFieldType
)col 
== m_sort_field
) 
 759         m_sort_foward 
= !m_sort_foward
; 
 761         m_sort_field 
= (wxFileData::fileListFieldType
)col
; 
 763     SortItems(m_sort_field
, m_sort_foward
); 
 766 void wxFileCtrl::SortItems(wxFileData::fileListFieldType field
, bool foward
) 
 768     m_sort_field 
= field
; 
 769     m_sort_foward 
= foward
; 
 770     long sort_dir 
= foward 
? 1 : -1; 
 772     switch (m_sort_field
) 
 774         case wxFileData::FileList_Name 
: 
 776             wxListCtrl::SortItems((wxListCtrlCompare
)wxFileDataNameCompare
, sort_dir
); 
 779         case wxFileData::FileList_Size 
: 
 781              wxListCtrl::SortItems((wxListCtrlCompare
)wxFileDataSizeCompare
, sort_dir
); 
 784         case wxFileData::FileList_Type 
: 
 786              wxListCtrl::SortItems((wxListCtrlCompare
)wxFileDataTypeCompare
, sort_dir
); 
 789         case wxFileData::FileList_Time 
: 
 791              wxListCtrl::SortItems((wxListCtrlCompare
)wxFileDataTimeCompare
, sort_dir
); 
 798 wxFileCtrl::~wxFileCtrl() 
 803 //----------------------------------------------------------------------------- 
 804 // wxGenericFileDialog 
 805 //----------------------------------------------------------------------------- 
 807 #define  ID_LIST_MODE     (wxID_FILEDLGG    ) 
 808 #define  ID_REPORT_MODE   (wxID_FILEDLGG + 1) 
 809 #define  ID_UP_DIR        (wxID_FILEDLGG + 5) 
 810 #define  ID_PARENT_DIR    (wxID_FILEDLGG + 6) 
 811 #define  ID_NEW_DIR       (wxID_FILEDLGG + 7) 
 812 #define  ID_CHOICE        (wxID_FILEDLGG + 8) 
 813 #define  ID_TEXT          (wxID_FILEDLGG + 9) 
 814 #define  ID_LIST_CTRL     (wxID_FILEDLGG + 10) 
 815 #define  ID_ACTIVATED     (wxID_FILEDLGG + 11) 
 816 #define  ID_CHECK         (wxID_FILEDLGG + 12) 
 818 IMPLEMENT_DYNAMIC_CLASS(wxGenericFileDialog
, wxFileDialogBase
) 
 820 BEGIN_EVENT_TABLE(wxGenericFileDialog
,wxDialog
) 
 821         EVT_BUTTON(ID_LIST_MODE
, wxGenericFileDialog::OnList
) 
 822         EVT_BUTTON(ID_REPORT_MODE
, wxGenericFileDialog::OnReport
) 
 823         EVT_BUTTON(ID_UP_DIR
, wxGenericFileDialog::OnUp
) 
 824         EVT_BUTTON(ID_PARENT_DIR
, wxGenericFileDialog::OnHome
) 
 825         EVT_BUTTON(ID_NEW_DIR
, wxGenericFileDialog::OnNew
) 
 826         EVT_BUTTON(wxID_OK
, wxGenericFileDialog::OnListOk
) 
 827         EVT_LIST_ITEM_SELECTED(ID_LIST_CTRL
, wxGenericFileDialog::OnSelected
) 
 828         EVT_LIST_ITEM_ACTIVATED(ID_LIST_CTRL
, wxGenericFileDialog::OnActivated
) 
 829         EVT_CHOICE(ID_CHOICE
,wxGenericFileDialog::OnChoiceFilter
) 
 830         EVT_TEXT_ENTER(ID_TEXT
,wxGenericFileDialog::OnTextEnter
) 
 831         EVT_TEXT(ID_TEXT
,wxGenericFileDialog::OnTextChange
) 
 832         EVT_CHECKBOX(ID_CHECK
,wxGenericFileDialog::OnCheck
) 
 835 long wxGenericFileDialog::ms_lastViewStyle 
= wxLC_LIST
; 
 836 bool wxGenericFileDialog::ms_lastShowHidden 
= FALSE
; 
 838 wxGenericFileDialog::wxGenericFileDialog(wxWindow 
*parent
, 
 839                            const wxString
& message
, 
 840                            const wxString
& defaultDir
, 
 841                            const wxString
& defaultFile
, 
 842                            const wxString
& wildCard
, 
 845                     :wxFileDialogBase(parent
, message
, defaultDir
, defaultFile
, wildCard
, style
, pos
) 
 847     wxDialog::Create( parent
, -1, message
, pos
, wxDefaultSize
, 
 848                       wxDEFAULT_DIALOG_STYLE 
| wxRESIZE_BORDER 
); 
 850     if (wxConfig::Get(FALSE
)) 
 852         wxConfig::Get()->Read(wxT("/wxWindows/wxFileDialog/ViewStyle"), 
 854         wxConfig::Get()->Read(wxT("/wxWindows/wxFileDialog/ShowHidden"), 
 858     if (m_dialogStyle 
== 0) 
 859         m_dialogStyle 
= wxOPEN
; 
 860     if ((m_dialogStyle 
& wxMULTIPLE 
) && !(m_dialogStyle 
& wxOPEN
)) 
 861         m_dialogStyle 
|= wxOPEN
; 
 863     if ((m_dir
.empty()) || (m_dir 
== wxT("."))) 
 868     size_t len 
= m_dir
.Len(); 
 869     if ((len 
> 1) && (wxEndsWithPathSeparator(m_dir
))) 
 870         m_dir
.Remove( len
-1, 1 ); 
 873     m_path 
+= wxFILE_SEP_PATH
; 
 874     m_path 
+= defaultFile
; 
 875     m_filterExtension 
= wxEmptyString
; 
 877     // interpret wildcards 
 878     wxArrayString wildDescriptions
, wildFilters
; 
 879     if ( !ParseWildcard(m_wildCard
, wildDescriptions
, wildFilters
) ) 
 881         wxFAIL_MSG( wxT("Wrong file type description") ); 
 886     bool is_pda 
= (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA
); 
 888     wxBoxSizer 
*mainsizer 
= new wxBoxSizer( wxVERTICAL 
); 
 890     wxBoxSizer 
*buttonsizer 
= new wxBoxSizer( wxHORIZONTAL 
); 
 894     but 
= new wxBitmapButton(this, ID_LIST_MODE
, 
 895                              wxArtProvider::GetBitmap(wxART_LIST_VIEW
, wxART_CMN_DIALOG
)); 
 897     but
->SetToolTip( _("View files as a list view") ); 
 899     buttonsizer
->Add( but
, 0, wxALL
, 5 ); 
 901     but 
= new wxBitmapButton(this, ID_REPORT_MODE
, 
 902                              wxArtProvider::GetBitmap(wxART_REPORT_VIEW
, wxART_CMN_DIALOG
)); 
 904     but
->SetToolTip( _("View files as a detailed view") ); 
 906     buttonsizer
->Add( but
, 0, wxALL
, 5 ); 
 908     buttonsizer
->Add( 30, 5, 1 ); 
 910     m_upDirButton 
= new wxBitmapButton(this, ID_UP_DIR
, 
 911                            wxArtProvider::GetBitmap(wxART_GO_DIR_UP
, wxART_CMN_DIALOG
)); 
 913     m_upDirButton
->SetToolTip( _("Go to parent directory") ); 
 915     buttonsizer
->Add( m_upDirButton
, 0, wxALL
, 5 ); 
 917 #ifndef __DOS__ // VS: Home directory is meaningless in MS-DOS... 
 918     but 
= new wxBitmapButton(this, ID_PARENT_DIR
, 
 919                              wxArtProvider::GetBitmap(wxART_GO_HOME
, wxART_CMN_DIALOG
)); 
 921     but
->SetToolTip( _("Go to home directory") ); 
 923     buttonsizer
->Add( but
, 0, wxALL
, 5); 
 925     buttonsizer
->Add( 20, 20 ); 
 928     m_newDirButton 
= new wxBitmapButton(this, ID_NEW_DIR
, 
 929                            wxArtProvider::GetBitmap(wxART_NEW_DIR
, wxART_CMN_DIALOG
)); 
 931     m_newDirButton
->SetToolTip( _("Create new directory") ); 
 933     buttonsizer
->Add( m_newDirButton
, 0, wxALL
, 5 ); 
 936         mainsizer
->Add( buttonsizer
, 0, wxALL 
| wxEXPAND
, 0 ); 
 938         mainsizer
->Add( buttonsizer
, 0, wxALL 
| wxEXPAND
, 5 ); 
 940     wxBoxSizer 
*staticsizer 
= new wxBoxSizer( wxHORIZONTAL 
); 
 942         staticsizer
->Add( new wxStaticText( this, -1, _("Current directory:") ), 0, wxRIGHT
, 10 ); 
 943     m_static 
= new wxStaticText( this, -1, m_dir 
); 
 944     staticsizer
->Add( m_static
, 1 ); 
 945     mainsizer
->Add( staticsizer
, 0, wxEXPAND 
| wxLEFT
|wxRIGHT
|wxBOTTOM
, 10 ); 
 947     long style2 
= ms_lastViewStyle 
| wxSUNKEN_BORDER
; 
 948     if ( !(m_dialogStyle 
& wxMULTIPLE
) ) 
 949         style2 
|= wxLC_SINGLE_SEL
; 
 951     m_list 
= new wxFileCtrl( this, ID_LIST_CTRL
, 
 952                              wildFilters
[0], ms_lastShowHidden
, 
 953                              wxDefaultPosition
, wxSize(540,200), 
 958         // PDAs have a different screen layout 
 959         mainsizer
->Add( m_list
, 1, wxEXPAND 
| wxLEFT
|wxRIGHT
, 5 ); 
 961         wxBoxSizer 
*choicesizer 
= new wxBoxSizer( wxHORIZONTAL 
); 
 962         m_choice 
= new wxChoice( this, ID_CHOICE 
); 
 963         choicesizer
->Add( m_choice
, 1, wxCENTER
|wxALL
, 5 ); 
 964         mainsizer
->Add( choicesizer
, 0, wxEXPAND 
); 
 966         wxBoxSizer 
*textsizer 
= new wxBoxSizer( wxHORIZONTAL 
); 
 967         m_text 
= new wxTextCtrl( this, ID_TEXT
, m_fileName
, wxDefaultPosition
, wxDefaultSize
, wxPROCESS_ENTER 
); 
 968         textsizer
->Add( m_text
, 1, wxCENTER 
| wxALL
, 5 ); 
 969         mainsizer
->Add( textsizer
, 0, wxEXPAND 
); 
 971         m_check 
= new wxCheckBox( this, ID_CHECK
, _("Show hidden files") ); 
 972         m_check
->SetValue( ms_lastShowHidden 
); 
 973         textsizer
->Add( m_check
, 0, wxCENTER
|wxALL
, 5 ); 
 975         buttonsizer 
= new wxBoxSizer( wxHORIZONTAL 
); 
 976         buttonsizer
->Add( new wxButton( this, wxID_OK
, _("OK") ), 0, wxCENTER 
| wxALL
, 5 ); 
 977         buttonsizer
->Add( new wxButton( this, wxID_CANCEL
, _("Cancel") ), 0, wxCENTER 
| wxALL
, 5 ); 
 978         mainsizer
->Add( buttonsizer
, 0, wxALIGN_RIGHT 
); 
 982         mainsizer
->Add( m_list
, 1, wxEXPAND 
| wxLEFT
|wxRIGHT
, 10 ); 
 984         wxBoxSizer 
*textsizer 
= new wxBoxSizer( wxHORIZONTAL 
); 
 985         m_text 
= new wxTextCtrl( this, ID_TEXT
, m_fileName
, wxDefaultPosition
, wxDefaultSize
, wxPROCESS_ENTER 
); 
 986         textsizer
->Add( m_text
, 1, wxCENTER 
| wxLEFT
|wxRIGHT
|wxTOP
, 10 ); 
 987         textsizer
->Add( new wxButton( this, wxID_OK
, _("OK") ), 0, wxCENTER 
| wxLEFT
|wxRIGHT
|wxTOP
, 10 ); 
 988         mainsizer
->Add( textsizer
, 0, wxEXPAND 
); 
 990         wxBoxSizer 
*choicesizer 
= new wxBoxSizer( wxHORIZONTAL 
); 
 991         m_choice 
= new wxChoice( this, ID_CHOICE 
); 
 992         choicesizer
->Add( m_choice
, 1, wxCENTER
|wxALL
, 10 ); 
 993         m_check 
= new wxCheckBox( this, ID_CHECK
, _("Show hidden files") ); 
 994         m_check
->SetValue( ms_lastShowHidden 
); 
 995         choicesizer
->Add( m_check
, 0, wxCENTER
|wxALL
, 10 ); 
 996         choicesizer
->Add( new wxButton( this, wxID_CANCEL
, _("Cancel") ), 0, wxCENTER 
| wxALL
, 10 ); 
 997         mainsizer
->Add( choicesizer
, 0, wxEXPAND 
); 
1000     for (size_t n
=0; n
<wildFilters
.GetCount(); n
++) 
1002         m_choice
->Append( wildDescriptions
[n
], (void*) new wxString( wildFilters
[n
] ) ); 
1004     SetFilterIndex( 0 ); 
1006     SetAutoLayout( TRUE 
); 
1007     SetSizer( mainsizer 
); 
1009     mainsizer
->Fit( this ); 
1010     mainsizer
->SetSizeHints( this ); 
1017 wxGenericFileDialog::~wxGenericFileDialog() 
1019     if (wxConfig::Get(FALSE
)) 
1021         wxConfig::Get()->Write(wxT("/wxWindows/wxFileDialog/ViewStyle"), 
1023         wxConfig::Get()->Write(wxT("/wxWindows/wxFileDialog/ShowHidden"), 
1027     const int count 
= m_choice
->GetCount(); 
1028     for ( int i 
= 0; i 
< count
; i
++ ) 
1030         delete (wxString 
*)m_choice
->GetClientData(i
); 
1034 int wxGenericFileDialog::ShowModal() 
1036     m_list
->GoToDir(m_dir
); 
1038     m_text
->SetValue(m_fileName
); 
1040     return wxDialog::ShowModal(); 
1043 void wxGenericFileDialog::DoSetFilterIndex(int filterindex
) 
1045     wxString 
*str 
= (wxString
*) m_choice
->GetClientData( filterindex 
); 
1046     m_list
->SetWild( *str 
); 
1047     m_filterIndex 
= filterindex
; 
1048     if ( str
->Left(2) == wxT("*.") ) 
1050         m_filterExtension 
= str
->Mid(1); 
1051         if (m_filterExtension 
== _T(".*")) 
1052             m_filterExtension
.clear(); 
1056         m_filterExtension
.clear(); 
1060 void wxGenericFileDialog::SetFilterIndex( int filterindex 
) 
1062     m_choice
->SetSelection( filterindex 
); 
1064     DoSetFilterIndex(filterindex
); 
1067 void wxGenericFileDialog::OnChoiceFilter( wxCommandEvent 
&event 
) 
1069     DoSetFilterIndex((int)event
.GetInt()); 
1072 void wxGenericFileDialog::OnCheck( wxCommandEvent 
&event 
) 
1074     m_list
->ShowHidden( (ms_lastShowHidden 
= event
.GetInt() != 0) ); 
1077 void wxGenericFileDialog::OnActivated( wxListEvent 
&event 
) 
1079     HandleAction( event
.m_item
.m_text 
); 
1082 void wxGenericFileDialog::OnTextEnter( wxCommandEvent 
&WXUNUSED(event
) ) 
1084     wxCommandEvent 
cevent(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_OK
); 
1085     cevent
.SetEventObject( this ); 
1086     GetEventHandler()->ProcessEvent( cevent 
); 
1089 static bool ignoreChanges 
= FALSE
; 
1091 void wxGenericFileDialog::OnTextChange( wxCommandEvent 
&WXUNUSED(event
) ) 
1095         // Clear selections.  Otherwise when the user types in a value they may 
1096         // not get the file whose name they typed. 
1097         if (m_list
->GetSelectedItemCount() > 0) 
1099             long item 
= m_list
->GetNextItem(-1, wxLIST_NEXT_ALL
, 
1100                 wxLIST_STATE_SELECTED
); 
1101             while ( item 
!= -1 ) 
1103                 m_list
->SetItemState(item
,0, wxLIST_STATE_SELECTED
); 
1104                 item 
= m_list
->GetNextItem(item
, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
); 
1110 void wxGenericFileDialog::OnSelected( wxListEvent 
&event 
) 
1112     wxString 
filename( event
.m_item
.m_text 
); 
1113     if (filename 
== wxT("..")) return; 
1115     wxString dir 
= m_list
->GetDir(); 
1116     if (!IsTopMostDir(dir
)) 
1117         dir 
+= wxFILE_SEP_PATH
; 
1119     if (wxDirExists(dir
)) return; 
1121     ignoreChanges 
= TRUE
; 
1122     m_text
->SetValue( filename 
); 
1123     ignoreChanges 
= FALSE
; 
1126 void wxGenericFileDialog::HandleAction( const wxString 
&fn 
) 
1128     wxString 
filename( fn 
); 
1129     wxString dir 
= m_list
->GetDir(); 
1130     if (filename
.IsEmpty()) return; 
1131     if (filename 
== wxT(".")) return; 
1133     // "some/place/" means they want to chdir not try to load "place" 
1134     bool want_dir 
= filename
.Last() == wxFILE_SEP_PATH
; 
1136         filename 
= filename
.RemoveLast(); 
1138     if (filename 
== wxT("..")) 
1140         m_list
->GoToParentDir(); 
1147     if (filename 
== wxT("~")) 
1149         m_list
->GoToHomeDir(); 
1155     if (filename
.BeforeFirst(wxT('/')) == wxT("~")) 
1157         filename 
= wxGetUserHome() + filename
.Remove(0, 1); 
1161     if ((filename
.Find(wxT('*')) != wxNOT_FOUND
) || 
1162         (filename
.Find(wxT('?')) != wxNOT_FOUND
)) 
1164         if (filename
.Find(wxFILE_SEP_PATH
) != wxNOT_FOUND
) 
1166             wxMessageBox(_("Illegal file specification."), _("Error"), wxOK 
| wxICON_ERROR 
); 
1169         m_list
->SetWild( filename 
); 
1173     if (!IsTopMostDir(dir
)) 
1174         dir 
+= wxFILE_SEP_PATH
; 
1175     if (!wxIsAbsolutePath(filename
)) 
1181     if (wxDirExists(filename
)) 
1183         m_list
->GoToDir( filename 
); 
1188     // they really wanted a dir, but it doesn't exist 
1191         wxMessageBox(_("Directory doesn't exist."), _("Error"), 
1192                      wxOK 
| wxICON_ERROR 
); 
1196     // append the default extension to the filename if it doesn't have any 
1198     // VZ: the logic of testing for !wxFileExists() only for the open file 
1199     //     dialog is not entirely clear to me, why don't we allow saving to a 
1200     //     file without extension as well? 
1201     if ( !(m_dialogStyle 
& wxOPEN
) || !wxFileExists(filename
) ) 
1203         filename 
= AppendExtension(filename
, m_filterExtension
); 
1206     // check that the file [doesn't] exist if necessary 
1207     if ( (m_dialogStyle 
& wxSAVE
) && 
1208             (m_dialogStyle 
& wxOVERWRITE_PROMPT
) && 
1209                 wxFileExists( filename 
) ) 
1212         msg
.Printf( _("File '%s' already exists, do you really want to overwrite it?"), filename
.c_str() ); 
1214         if (wxMessageBox(msg
, _("Confirm"), wxYES_NO
) != wxYES
) 
1217     else if ( (m_dialogStyle 
& wxOPEN
) && 
1218                 (m_dialogStyle 
& wxFILE_MUST_EXIST
) && 
1219                     !wxFileExists(filename
) ) 
1221         wxMessageBox(_("Please choose an existing file."), _("Error"), 
1222                      wxOK 
| wxICON_ERROR 
); 
1225     SetPath( filename 
); 
1227     // change to the directory where the user went if asked 
1228     if ( m_dialogStyle 
& wxCHANGE_DIR 
) 
1231         wxSplitPath(filename
, &cwd
, NULL
, NULL
); 
1233         if ( cwd 
!= wxGetCwd() ) 
1235             wxSetWorkingDirectory(cwd
); 
1239     wxCommandEvent event
; 
1240     wxDialog::OnOK(event
); 
1243 void wxGenericFileDialog::OnListOk( wxCommandEvent 
&WXUNUSED(event
) ) 
1245     HandleAction( m_text
->GetValue() ); 
1248 void wxGenericFileDialog::OnList( wxCommandEvent 
&WXUNUSED(event
) ) 
1250     m_list
->ChangeToListMode(); 
1251     ms_lastViewStyle 
= wxLC_LIST
; 
1255 void wxGenericFileDialog::OnReport( wxCommandEvent 
&WXUNUSED(event
) ) 
1257     m_list
->ChangeToReportMode(); 
1258     ms_lastViewStyle 
= wxLC_REPORT
; 
1262 void wxGenericFileDialog::OnUp( wxCommandEvent 
&WXUNUSED(event
) ) 
1264     m_list
->GoToParentDir(); 
1269 void wxGenericFileDialog::OnHome( wxCommandEvent 
&WXUNUSED(event
) ) 
1271     m_list
->GoToHomeDir(); 
1276 void wxGenericFileDialog::OnNew( wxCommandEvent 
&WXUNUSED(event
) ) 
1281 void wxGenericFileDialog::SetPath( const wxString
& path 
) 
1283     // not only set the full path but also update filename and dir 
1285     if ( !path
.empty() ) 
1288         wxSplitPath(path
, &m_dir
, &m_fileName
, &ext
); 
1291             m_fileName 
+= wxT("."); 
1297 void wxGenericFileDialog::GetPaths( wxArrayString
& paths 
) const 
1300     if (m_list
->GetSelectedItemCount() == 0) 
1302         paths
.Add( GetPath() ); 
1306     paths
.Alloc( m_list
->GetSelectedItemCount() ); 
1308     wxString dir 
= m_list
->GetDir(); 
1310     if (dir 
!= wxT("/")) 
1312         dir 
+= wxFILE_SEP_PATH
; 
1315     item
.m_mask 
= wxLIST_MASK_TEXT
; 
1317     item
.m_itemId 
= m_list
->GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED 
); 
1318     while ( item
.m_itemId 
!= -1 ) 
1320         m_list
->GetItem( item 
); 
1321         paths
.Add( dir 
+ item
.m_text 
); 
1322         item
.m_itemId 
= m_list
->GetNextItem( item
.m_itemId
, 
1323             wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED 
); 
1327 void wxGenericFileDialog::GetFilenames(wxArrayString
& files
) const 
1330     if (m_list
->GetSelectedItemCount() == 0) 
1332         files
.Add( GetFilename() ); 
1335     files
.Alloc( m_list
->GetSelectedItemCount() ); 
1338     item
.m_mask 
= wxLIST_MASK_TEXT
; 
1340     item
.m_itemId 
= m_list
->GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED 
); 
1341     while ( item
.m_itemId 
!= -1 ) 
1343         m_list
->GetItem( item 
); 
1344         files
.Add( item
.m_text 
); 
1345         item
.m_itemId 
= m_list
->GetNextItem( item
.m_itemId
, 
1346             wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED 
); 
1350 void wxGenericFileDialog::UpdateControls() 
1352     wxString dir 
= m_list
->GetDir(); 
1353     m_static
->SetLabel(dir
); 
1355     bool enable 
= !IsTopMostDir(dir
); 
1356     m_upDirButton
->Enable(enable
); 
1358 #if defined(__DOS__) || defined(__WINDOWS__) || defined(__OS2__) 
1359     m_newDirButton
->Enable(enable
); 
1360 #endif // defined(__DOS__) || defined(__WINDOWS__) || defined(__OS2__) 
1363 #ifdef USE_GENERIC_FILEDIALOG 
1365 IMPLEMENT_DYNAMIC_CLASS(wxFileDialog
, wxGenericFileDialog
); 
1367 #endif // USE_GENERIC_FILEDIALOG 
1369 #endif // wxUSE_FILEDLG