1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxFileDialog
4 // Author: Robert Roebling
8 // Copyright: (c) Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "filedlgg.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
25 #if !defined(__UNIX__) && !defined(__DOS__)
26 #error wxFileDialog currently only supports Unix and DOS
29 #include "wx/checkbox.h"
30 #include "wx/textctrl.h"
31 #include "wx/choice.h"
32 #include "wx/checkbox.h"
33 #include "wx/stattext.h"
34 #include "wx/filedlg.h"
38 #include "wx/listctrl.h"
39 #include "wx/msgdlg.h"
41 #include "wx/bmpbuttn.h"
42 #include "wx/tokenzr.h"
43 #include "wx/mimetype.h"
45 #include "wx/module.h"
46 #include "wx/config.h"
47 #include "wx/imaglist.h"
49 #include "wx/artprov.h"
52 #include "wx/tooltip.h"
55 #include <sys/types.h>
73 //-----------------------------------------------------------------------------
75 //-----------------------------------------------------------------------------
77 class wxFileData
: public wxObject
81 wxFileData( const wxString
&name
, const wxString
&fname
);
82 wxString
GetName() const;
83 wxString
GetFullName() const;
84 wxString
GetHint() const;
85 wxString
GetEntry( int num
);
90 void MakeItem( wxListItem
&item
);
91 void SetNewName( const wxString
&name
, const wxString
&fname
);
102 wxString m_permissions
;
107 DECLARE_DYNAMIC_CLASS(wxFileData
);
110 //-----------------------------------------------------------------------------
112 //-----------------------------------------------------------------------------
114 class wxFileCtrl
: public wxListCtrl
118 wxFileCtrl( wxWindow
*win
,
120 const wxString
&dirName
,
121 const wxString
&wild
,
122 const wxPoint
&pos
= wxDefaultPosition
,
123 const wxSize
&size
= wxDefaultSize
,
124 long style
= wxLC_LIST
,
125 const wxValidator
&validator
= wxDefaultValidator
,
126 const wxString
&name
= wxT("filelist") );
127 void ChangeToListMode();
128 void ChangeToReportMode();
129 void ChangeToIconMode();
130 void ShowHidden( bool show
= TRUE
);
131 long Add( wxFileData
*fd
, wxListItem
&item
);
133 virtual void StatusbarText( wxChar
*WXUNUSED(text
) ) {};
135 void GoToParentDir();
137 void GoToDir( const wxString
&dir
);
138 void SetWild( const wxString
&wild
);
139 void GetDir( wxString
&dir
);
140 void OnListDeleteItem( wxListEvent
&event
);
141 void OnListDeleteAllItems( wxListEvent
&event
);
142 void OnListEndLabelEdit( wxListEvent
&event
);
144 // Associate commonly used UI controls with wxFileCtrl so that they can be
145 // disabled when they cannot be used (e.g. can't go to parent directory
146 // if wxFileCtrl already is in the root dir):
147 void SetGoToParentControl(wxWindow
*ctrl
) { m_goToParentControl
= ctrl
; }
148 void SetNewDirControl(wxWindow
*ctrl
) { m_newDirControl
= ctrl
; }
155 wxWindow
*m_goToParentControl
;
156 wxWindow
*m_newDirControl
;
158 DECLARE_DYNAMIC_CLASS(wxFileCtrl
);
159 DECLARE_EVENT_TABLE()
162 // ----------------------------------------------------------------------------
163 // private classes - icons list management
164 // ----------------------------------------------------------------------------
166 class wxFileIconEntry
: public wxObject
169 wxFileIconEntry(int i
) { id
= i
; }
175 class wxFileIconsTable
180 int GetIconID(const wxString
& extension
, const wxString
& mime
= wxEmptyString
);
181 wxImageList
*GetImageList() { return &m_ImageList
; }
184 wxImageList m_ImageList
;
185 wxHashTable m_HashTable
;
188 static wxFileIconsTable
*g_IconsTable
= NULL
;
192 #define FI_EXECUTABLE 2
194 wxFileIconsTable::wxFileIconsTable() :
196 m_HashTable(wxKEY_STRING
)
198 m_HashTable
.DeleteContents(TRUE
);
200 m_ImageList
.Add(wxArtProvider::GetBitmap(wxART_FOLDER
, wxART_CMN_DIALOG
));
202 m_ImageList
.Add(wxArtProvider::GetBitmap(wxART_NORMAL_FILE
, wxART_CMN_DIALOG
));
204 if (GetIconID(wxEmptyString
, _T("application/x-executable")) == FI_UNKNOWN
)
206 m_ImageList
.Add(wxArtProvider::GetBitmap(wxART_EXECUTABLE_FILE
, wxART_CMN_DIALOG
));
207 m_HashTable
.Delete(_T("exe"));
208 m_HashTable
.Put(_T("exe"), new wxFileIconEntry(FI_EXECUTABLE
));
210 /* else put into list by GetIconID
211 (KDE defines application/x-executable for *.exe and has nice icon)
218 // VS: we don't need this function w/o wxMimeTypesManager because we'll only have
219 // one icon and we won't resize it
221 static wxBitmap
CreateAntialiasedBitmap(const wxImage
& img
)
223 wxImage
small(16, 16);
224 unsigned char *p1
, *p2
, *ps
;
225 unsigned char mr
= img
.GetMaskRed(),
226 mg
= img
.GetMaskGreen(),
227 mb
= img
.GetMaskBlue();
230 unsigned sr
, sg
, sb
, smask
;
232 p1
= img
.GetData(), p2
= img
.GetData() + 3 * 32, ps
= small
.GetData();
233 small
.SetMaskColour(mr
, mr
, mr
);
235 for (y
= 0; y
< 16; y
++)
237 for (x
= 0; x
< 16; x
++)
239 sr
= sg
= sb
= smask
= 0;
240 if (p1
[0] != mr
|| p1
[1] != mg
|| p1
[2] != mb
)
241 sr
+= p1
[0], sg
+= p1
[1], sb
+= p1
[2];
244 if (p1
[0] != mr
|| p1
[1] != mg
|| p1
[2] != mb
)
245 sr
+= p1
[0], sg
+= p1
[1], sb
+= p1
[2];
248 if (p2
[0] != mr
|| p2
[1] != mg
|| p2
[2] != mb
)
249 sr
+= p2
[0], sg
+= p2
[1], sb
+= p2
[2];
252 if (p2
[0] != mr
|| p2
[1] != mg
|| p2
[2] != mb
)
253 sr
+= p2
[0], sg
+= p2
[1], sb
+= p2
[2];
258 ps
[0] = ps
[1] = ps
[2] = mr
;
260 ps
[0] = sr
>> 2, ps
[1] = sg
>> 2, ps
[2] = sb
>> 2;
263 p1
+= 32 * 3, p2
+= 32 * 3;
266 return wxBitmap(small
);
269 // finds empty borders and return non-empty area of image:
270 static wxImage
CutEmptyBorders(const wxImage
& img
)
272 unsigned char mr
= img
.GetMaskRed(),
273 mg
= img
.GetMaskGreen(),
274 mb
= img
.GetMaskBlue();
275 unsigned char *dt
= img
.GetData(), *dttmp
;
276 unsigned w
= img
.GetWidth(), h
= img
.GetHeight();
278 unsigned top
, bottom
, left
, right
, i
;
281 #define MK_DTTMP(x,y) dttmp = dt + ((x + y * w) * 3)
282 #define NOEMPTY_PIX(empt) if (dttmp[0] != mr || dttmp[1] != mg || dttmp[2] != mb) {empt = FALSE; break;}
284 for (empt
= TRUE
, top
= 0; empt
&& top
< h
; top
++)
287 for (i
= 0; i
< w
; i
++, dttmp
+=3)
290 for (empt
= TRUE
, bottom
= h
-1; empt
&& bottom
> top
; bottom
--)
293 for (i
= 0; i
< w
; i
++, dttmp
+=3)
296 for (empt
= TRUE
, left
= 0; empt
&& left
< w
; left
++)
299 for (i
= 0; i
< h
; i
++, dttmp
+=3*w
)
302 for (empt
= TRUE
, right
= w
-1; empt
&& right
> left
; right
--)
305 for (i
= 0; i
< h
; i
++, dttmp
+=3*w
)
308 top
--, left
--, bottom
++, right
++;
310 return img
.GetSubImage(wxRect(left
, top
, right
- left
+ 1, bottom
- top
+ 1));
312 #endif // wxUSE_MIMETYPE
316 int wxFileIconsTable::GetIconID(const wxString
& extension
, const wxString
& mime
)
319 if (!extension
.IsEmpty())
321 wxFileIconEntry
*entry
= (wxFileIconEntry
*) m_HashTable
.Get(extension
);
322 if (entry
) return (entry
-> id
);
325 wxFileType
*ft
= (mime
.IsEmpty()) ?
326 wxTheMimeTypesManager
-> GetFileTypeFromExtension(extension
) :
327 wxTheMimeTypesManager
-> GetFileTypeFromMimeType(mime
);
329 if (ft
== NULL
|| (!ft
-> GetIcon(&ic
)) || (!ic
.Ok()))
331 int newid
= FI_UNKNOWN
;
332 m_HashTable
.Put(extension
, new wxFileIconEntry(newid
));
335 wxImage img
= ic
.ConvertToImage();
338 int id
= m_ImageList
.GetImageCount();
339 if (img
.GetWidth() == 16 && img
.GetHeight() == 16)
340 m_ImageList
.Add(wxBitmap(img
));
343 if (img
.GetWidth() != 32 || img
.GetHeight() != 32)
344 m_ImageList
.Add(CreateAntialiasedBitmap(CutEmptyBorders(img
).Rescale(32, 32)));
346 m_ImageList
.Add(CreateAntialiasedBitmap(img
));
348 m_HashTable
.Put(extension
, new wxFileIconEntry(id
));
351 #else // !wxUSE_MIMETYPE
353 if (extension
== wxT("exe"))
354 return FI_EXECUTABLE
;
357 #endif // wxUSE_MIMETYPE/!wxUSE_MIMETYPE
362 // ----------------------------------------------------------------------------
364 // ----------------------------------------------------------------------------
367 int ListCompare( long data1
, long data2
, long WXUNUSED(data
) )
369 wxFileData
*fd1
= (wxFileData
*)data1
;
370 wxFileData
*fd2
= (wxFileData
*)data2
;
371 if (fd1
->GetName() == wxT("..")) return -1;
372 if (fd2
->GetName() == wxT("..")) return 1;
373 if (fd1
->IsDir() && !fd2
->IsDir()) return -1;
374 if (fd2
->IsDir() && !fd1
->IsDir()) return 1;
375 return wxStrcmp( fd1
->GetName(), fd2
->GetName() );
379 #define IsTopMostDir(dir) (dir == wxT("/"))
382 #if defined(__DOS__) || defined(__WINDOWS__)
383 #define IsTopMostDir(dir) (dir.IsEmpty())
386 #if defined(__DOS__) || defined(__WINDOWS__)
387 extern bool wxIsDriveAvailable(const wxString
& dirName
);
390 //-----------------------------------------------------------------------------
392 //-----------------------------------------------------------------------------
394 IMPLEMENT_DYNAMIC_CLASS(wxFileData
,wxObject
);
396 wxFileData::wxFileData( const wxString
&name
, const wxString
&fname
)
401 #if defined(__DOS__) || defined(__WINDOWS__)
402 // VS: In case the file is root directory of a volume (e.g. "C:"),
403 // we don't want it stat()ed, since the drive may not be in:
404 if (name
.length() == 2 && name
[1u] == wxT(':'))
407 m_isExe
= m_isLink
= FALSE
;
414 wxStat( m_fileName
.fn_str(), &buff
);
416 #if defined(__UNIX__) && (!defined( __EMX__ ) && !defined(__VMS))
418 lstat( m_fileName
.fn_str(), &lbuff
);
419 m_isLink
= S_ISLNK( lbuff
.st_mode
);
420 struct tm
*t
= localtime( &lbuff
.st_mtime
);
423 struct tm
*t
= localtime( &buff
.st_mtime
);
426 // struct passwd *user = getpwuid( buff.st_uid );
427 // struct group *grp = getgrgid( buff.st_gid );
429 m_isDir
= S_ISDIR( buff
.st_mode
);
430 m_isExe
= ((buff
.st_mode
& S_IXUSR
) == S_IXUSR
);
432 m_size
= buff
.st_size
;
435 m_minute
= t
->tm_min
;
436 m_month
= t
->tm_mon
+1;
441 m_permissions
.sprintf( wxT("%c%c%c"),
442 ((( buff
.st_mode
& S_IRUSR
) == S_IRUSR
) ? wxT('r') : wxT('-')),
443 ((( buff
.st_mode
& S_IWUSR
) == S_IWUSR
) ? wxT('w') : wxT('-')),
444 ((( buff
.st_mode
& S_IXUSR
) == S_IXUSR
) ? wxT('x') : wxT('-')) );
447 wxString
wxFileData::GetName() const
452 wxString
wxFileData::GetFullName() const
457 wxString
wxFileData::GetHint() const
459 wxString s
= m_fileName
;
461 if (m_isDir
) s
+= _("<DIR> ");
462 else if (m_isLink
) s
+= _("<LINK> ");
465 s
+= LongToString( m_size
);
468 s
+= IntToString( m_day
);
470 s
+= IntToString( m_month
);
472 s
+= IntToString( m_year
);
474 s
+= IntToString( m_hour
);
476 s
+= IntToString( m_minute
);
482 wxString
wxFileData::GetEntry( int num
)
494 if (m_isDir
) s
= _("<DIR>");
495 else if (m_isLink
) s
= _("<LINK>");
496 else s
= LongToString( m_size
);
501 if (m_day
< 10) s
= wxT("0"); else s
= wxT("");
502 s
+= IntToString( m_day
);
504 if (m_month
< 10) s
+= wxT("0");
505 s
+= IntToString( m_month
);
507 s
+= IntToString( m_year
);
512 if (m_hour
< 10) s
= wxT("0"); else s
= wxT("");
513 s
+= IntToString( m_hour
);
515 if (m_minute
< 10) s
+= wxT("0");
516 s
+= IntToString( m_minute
);
529 bool wxFileData::IsDir()
534 bool wxFileData::IsExe()
539 bool wxFileData::IsLink()
544 long wxFileData::GetSize()
549 void wxFileData::SetNewName( const wxString
&name
, const wxString
&fname
)
555 void wxFileData::MakeItem( wxListItem
&item
)
557 item
.m_text
= m_name
;
558 item
.ClearAttributes();
559 if (IsExe()) item
.SetTextColour(*wxRED
);
560 if (IsDir()) item
.SetTextColour(*wxBLUE
);
563 item
.m_image
= FI_FOLDER
;
565 item
.m_image
= FI_EXECUTABLE
;
566 else if (m_name
.Find(wxT('.')) != wxNOT_FOUND
)
567 item
.m_image
= g_IconsTable
->GetIconID(m_name
.AfterLast(wxT('.')));
569 item
.m_image
= FI_UNKNOWN
;
573 wxColour
*dg
= wxTheColourDatabase
->FindColour( "MEDIUM GREY" );
574 item
.SetTextColour(*dg
);
576 item
.m_data
= (long)this;
579 //-----------------------------------------------------------------------------
581 //-----------------------------------------------------------------------------
583 IMPLEMENT_DYNAMIC_CLASS(wxFileCtrl
,wxListCtrl
);
585 BEGIN_EVENT_TABLE(wxFileCtrl
,wxListCtrl
)
586 EVT_LIST_DELETE_ITEM(-1, wxFileCtrl::OnListDeleteItem
)
587 EVT_LIST_DELETE_ALL_ITEMS(-1, wxFileCtrl::OnListDeleteAllItems
)
588 EVT_LIST_END_LABEL_EDIT(-1, wxFileCtrl::OnListEndLabelEdit
)
592 wxFileCtrl::wxFileCtrl()
594 #if defined(__UNIX__)
595 m_dirName
= wxT("/");
596 #elif defined(__DOS__)
599 m_showHidden
= FALSE
;
602 wxFileCtrl::wxFileCtrl(wxWindow
*win
, wxWindowID id
,
603 const wxString
&dirName
, const wxString
&wild
,
604 const wxPoint
&pos
, const wxSize
&size
,
605 long style
, const wxValidator
&validator
,
606 const wxString
&name
)
607 : wxListCtrl(win
, id
, pos
, size
, style
, validator
, name
)
610 g_IconsTable
= new wxFileIconsTable
;
611 wxImageList
*imageList
= g_IconsTable
->GetImageList();
613 SetImageList( imageList
, wxIMAGE_LIST_SMALL
);
615 m_goToParentControl
= m_newDirControl
= NULL
;
619 m_showHidden
= FALSE
;
623 void wxFileCtrl::ChangeToListMode()
625 SetSingleStyle( wxLC_LIST
);
629 void wxFileCtrl::ChangeToReportMode()
631 SetSingleStyle( wxLC_REPORT
);
635 void wxFileCtrl::ChangeToIconMode()
637 SetSingleStyle( wxLC_ICON
);
641 void wxFileCtrl::ShowHidden( bool show
)
647 long wxFileCtrl::Add( wxFileData
*fd
, wxListItem
&item
)
650 item
.m_mask
= wxLIST_MASK_TEXT
+ wxLIST_MASK_DATA
+ wxLIST_MASK_IMAGE
;
651 fd
->MakeItem( item
);
652 long my_style
= GetWindowStyleFlag();
653 if (my_style
& wxLC_REPORT
)
656 const int noEntries
= 5;
658 const int noEntries
= 4;
660 ret
= InsertItem( item
);
661 for (int i
= 1; i
< noEntries
; i
++)
662 SetItem( item
.m_itemId
, i
, fd
->GetEntry( i
) );
664 else if (my_style
& wxLC_LIST
)
666 ret
= InsertItem( item
);
671 void wxFileCtrl::UpdateFiles()
673 wxBusyCursor bcur
; // this may take a while...
675 long my_style
= GetWindowStyleFlag();
676 int name_col_width
= 0;
677 if (my_style
& wxLC_REPORT
)
679 if (GetColumnCount() > 0)
680 name_col_width
= GetColumnWidth( 0 );
684 if (my_style
& wxLC_REPORT
)
686 if (name_col_width
< 140) name_col_width
= 140;
687 InsertColumn( 0, _("Name"), wxLIST_FORMAT_LEFT
, name_col_width
);
688 InsertColumn( 1, _("Size"), wxLIST_FORMAT_LEFT
, 60 );
689 InsertColumn( 2, _("Date"), wxLIST_FORMAT_LEFT
, 65 );
690 InsertColumn( 3, _("Time"), wxLIST_FORMAT_LEFT
, 50 );
692 InsertColumn( 4, _("Permissions"), wxLIST_FORMAT_LEFT
, 120 );
695 wxFileData
*fd
= (wxFileData
*) NULL
;
700 #if defined(__DOS__) || defined(__WINDOWS__)
701 if ( IsTopMostDir(m_dirName
) )
703 // Pseudo-directory with all available drives listed...
704 for (int drive
= 1; drive
<= 26; drive
++)
707 path
.Printf(wxT("%c:\\"), (char)(drive
+ 'A' - 1));
708 if ( wxIsDriveAvailable(path
) )
711 fd
= new wxFileData(path
, path
);
721 if ( !IsTopMostDir(m_dirName
) )
723 wxString
p(wxPathOnly(m_dirName
));
725 if (p
.IsEmpty()) p
= wxT("/");
727 fd
= new wxFileData( wxT(".."), p
);
732 wxString
dirname(m_dirName
);
733 #if defined(__DOS__) || defined(__WINDOWS__)
734 if (dirname
.length() == 2 && dirname
[1u] == wxT(':'))
735 dirname
<< wxT('\\');
739 if ( dir
.IsOpened() )
741 wxString
dirPrefix(dirname
+ wxFILE_SEP_PATH
);
742 int hiddenFlag
= m_showHidden
? wxDIR_HIDDEN
: 0;
747 // Get the directories first (not matched against wildcards):
748 cont
= dir
.GetFirst(&f
, wxEmptyString
, wxDIR_DIRS
| hiddenFlag
);
751 fd
= new wxFileData(f
, dirPrefix
+ f
);
754 cont
= dir
.GetNext(&f
);
757 // Tokenize the wildcard string, so we can handle more than 1
758 // search pattern in a wildcard.
759 wxStringTokenizer
tokenWild(m_wild
, wxT(";"));
760 while ( tokenWild
.HasMoreTokens() )
762 cont
= dir
.GetFirst(&f
, tokenWild
.GetNextToken(),
763 wxDIR_FILES
| hiddenFlag
);
766 fd
= new wxFileData(f
, dirPrefix
+ f
);
769 cont
= dir
.GetNext(&f
);
775 SortItems(ListCompare
, 0);
777 if ( my_style
& wxLC_REPORT
)
779 SetColumnWidth(1, wxLIST_AUTOSIZE
);
780 SetColumnWidth(2, wxLIST_AUTOSIZE
);
781 SetColumnWidth(3, wxLIST_AUTOSIZE
);
784 // Finally, enable/disable context-dependent controls:
785 if ( m_goToParentControl
)
786 m_goToParentControl
->Enable(!IsTopMostDir(m_dirName
));
787 #if defined(__DOS__) || defined(__WINDOWS__)
788 if ( m_newDirControl
)
789 m_newDirControl
->Enable(!IsTopMostDir(m_dirName
));
793 void wxFileCtrl::SetWild( const wxString
&wild
)
799 void wxFileCtrl::MakeDir()
801 wxString
new_name( _("NewName") );
802 wxString
path( m_dirName
);
803 path
+= wxFILE_SEP_PATH
;
805 if (wxFileExists(path
))
807 // try NewName0, NewName1 etc.
810 new_name
= _("NewName");
812 num
.Printf( wxT("%d"), i
);
816 path
+= wxFILE_SEP_PATH
;
819 } while (wxFileExists(path
));
825 wxMessageDialog
dialog(this, _("Operation not permitted."), _("Error"), wxOK
| wxICON_ERROR
);
830 wxFileData
*fd
= new wxFileData( new_name
, path
);
834 long id
= Add( fd
, item
);
838 SortItems( ListCompare
, 0 );
839 id
= FindItem( 0, (long)fd
);
845 void wxFileCtrl::GoToParentDir()
847 if (!IsTopMostDir(m_dirName
))
849 size_t len
= m_dirName
.Len();
850 if (m_dirName
[len
-1] == wxFILE_SEP_PATH
)
851 m_dirName
.Remove( len
-1, 1 );
852 wxString
fname( wxFileNameFromPath(m_dirName
) );
853 m_dirName
= wxPathOnly( m_dirName
);
855 if (m_dirName
.IsEmpty())
856 m_dirName
= wxT("/");
859 long id
= FindItem( 0, fname
);
862 SetItemState( id
, wxLIST_STATE_SELECTED
, wxLIST_STATE_SELECTED
);
868 void wxFileCtrl::GoToHomeDir()
870 wxString s
= wxGetUserHome( wxString() );
874 void wxFileCtrl::GoToDir( const wxString
&dir
)
878 SetItemState( 0, wxLIST_STATE_SELECTED
, wxLIST_STATE_SELECTED
);
882 void wxFileCtrl::GetDir( wxString
&dir
)
887 void wxFileCtrl::OnListDeleteItem( wxListEvent
&event
)
889 wxFileData
*fd
= (wxFileData
*)event
.m_item
.m_data
;
893 void wxFileCtrl::OnListDeleteAllItems( wxListEvent
&WXUNUSED(event
) )
896 item
.m_mask
= wxLIST_MASK_DATA
;
898 item
.m_itemId
= GetNextItem( -1, wxLIST_NEXT_ALL
);
899 while ( item
.m_itemId
!= -1 )
902 wxFileData
*fd
= (wxFileData
*)item
.m_data
;
906 item
.m_itemId
= GetNextItem( item
.m_itemId
, wxLIST_NEXT_ALL
);
910 void wxFileCtrl::OnListEndLabelEdit( wxListEvent
&event
)
912 wxFileData
*fd
= (wxFileData
*)event
.m_item
.m_data
;
915 if ((event
.GetLabel().IsEmpty()) ||
916 (event
.GetLabel() == _(".")) ||
917 (event
.GetLabel() == _("..")) ||
918 (event
.GetLabel().First( wxFILE_SEP_PATH
) != wxNOT_FOUND
))
920 wxMessageDialog
dialog(this, _("Illegal directory name."), _("Error"), wxOK
| wxICON_ERROR
);
926 wxString
new_name( wxPathOnly( fd
->GetFullName() ) );
927 new_name
+= wxFILE_SEP_PATH
;
928 new_name
+= event
.GetLabel();
932 if (wxFileExists(new_name
))
934 wxMessageDialog
dialog(this, _("File name exists already."), _("Error"), wxOK
| wxICON_ERROR
);
939 if (wxRenameFile(fd
->GetFullName(),new_name
))
941 fd
->SetNewName( new_name
, event
.GetLabel() );
942 SetItemState( event
.GetItem(), wxLIST_STATE_SELECTED
, wxLIST_STATE_SELECTED
);
943 EnsureVisible( event
.GetItem() );
947 wxMessageDialog
dialog(this, _("Operation not permitted."), _("Error"), wxOK
| wxICON_ERROR
);
953 //-----------------------------------------------------------------------------
955 //-----------------------------------------------------------------------------
957 #define ID_LIST_MODE (wxID_FILEDLGG )
958 #define ID_REPORT_MODE (wxID_FILEDLGG + 1)
959 #define ID_UP_DIR (wxID_FILEDLGG + 5)
960 #define ID_PARENT_DIR (wxID_FILEDLGG + 6)
961 #define ID_NEW_DIR (wxID_FILEDLGG + 7)
962 #define ID_CHOICE (wxID_FILEDLGG + 8)
963 #define ID_TEXT (wxID_FILEDLGG + 9)
964 #define ID_LIST_CTRL (wxID_FILEDLGG + 10)
965 #define ID_ACTIVATED (wxID_FILEDLGG + 11)
966 #define ID_CHECK (wxID_FILEDLGG + 12)
968 IMPLEMENT_DYNAMIC_CLASS(wxFileDialog
,wxDialog
)
970 BEGIN_EVENT_TABLE(wxFileDialog
,wxDialog
)
971 EVT_BUTTON(ID_LIST_MODE
, wxFileDialog::OnList
)
972 EVT_BUTTON(ID_REPORT_MODE
, wxFileDialog::OnReport
)
973 EVT_BUTTON(ID_UP_DIR
, wxFileDialog::OnUp
)
974 EVT_BUTTON(ID_PARENT_DIR
, wxFileDialog::OnHome
)
975 EVT_BUTTON(ID_NEW_DIR
, wxFileDialog::OnNew
)
976 EVT_BUTTON(wxID_OK
, wxFileDialog::OnListOk
)
977 EVT_LIST_ITEM_SELECTED(ID_LIST_CTRL
, wxFileDialog::OnSelected
)
978 EVT_LIST_ITEM_ACTIVATED(ID_LIST_CTRL
, wxFileDialog::OnActivated
)
979 EVT_CHOICE(ID_CHOICE
,wxFileDialog::OnChoice
)
980 EVT_TEXT_ENTER(ID_TEXT
,wxFileDialog::OnTextEnter
)
981 EVT_CHECKBOX(ID_CHECK
,wxFileDialog::OnCheck
)
984 long wxFileDialog::s_lastViewStyle
= wxLC_LIST
;
985 bool wxFileDialog::s_lastShowHidden
= FALSE
;
987 wxFileDialog::wxFileDialog(wxWindow
*parent
,
988 const wxString
& message
,
989 const wxString
& defaultDir
,
990 const wxString
& defaultFile
,
991 const wxString
& wildCard
,
993 const wxPoint
& pos
) :
994 wxDialog( parent
, -1, message
, pos
, wxDefaultSize
, wxDEFAULT_DIALOG_STYLE
| wxRESIZE_BORDER
)
998 if (wxConfig::Get(FALSE
))
1000 wxConfig::Get()->Read(wxT("/wxWindows/wxFileDialog/ViewStyle"),
1002 wxConfig::Get()->Read(wxT("/wxWindows/wxFileDialog/ShowHidden"),
1006 m_message
= message
;
1007 m_dialogStyle
= style
;
1009 if (m_dialogStyle
== 0) m_dialogStyle
= wxOPEN
;
1010 if ((m_dialogStyle
& wxMULTIPLE
) && !(m_dialogStyle
& wxOPEN
))
1011 m_dialogStyle
|= wxOPEN
;
1014 if ((m_dir
.empty()) || (m_dir
== wxT(".")))
1019 size_t len
= m_dir
.Len();
1020 if ((len
> 1) && (m_dir
[len
-1] == wxFILE_SEP_PATH
))
1021 m_dir
.Remove( len
-1, 1 );
1024 m_path
+= wxFILE_SEP_PATH
;
1025 m_path
+= defaultFile
;
1026 m_fileName
= defaultFile
;
1027 m_wildCard
= wildCard
;
1029 m_filterExtension
= wxEmptyString
;
1031 // interpret wildcards
1033 if (m_wildCard
.IsEmpty())
1034 m_wildCard
= _("All files (*)|*");
1036 wxStringTokenizer
tokens( m_wildCard
, wxT("|") );
1038 wxString firstWildText
;
1039 if (tokens
.CountTokens() == 1)
1041 firstWildText
= tokens
.GetNextToken();
1042 firstWild
= firstWildText
;
1046 wxASSERT_MSG( tokens
.CountTokens() % 2 == 0, wxT("Wrong file type descripition") );
1047 firstWildText
= tokens
.GetNextToken();
1048 firstWild
= tokens
.GetNextToken();
1050 if ( firstWild
.Left( 2 ) == wxT("*.") )
1051 m_filterExtension
= firstWild
.Mid( 1 );
1052 if ( m_filterExtension
== ".*" ) m_filterExtension
= wxEmptyString
;
1056 wxBoxSizer
*mainsizer
= new wxBoxSizer( wxVERTICAL
);
1058 wxBoxSizer
*buttonsizer
= new wxBoxSizer( wxHORIZONTAL
);
1060 wxBitmapButton
*but
;
1062 but
= new wxBitmapButton(this, ID_LIST_MODE
,
1063 wxArtProvider::GetBitmap(wxART_LIST_VIEW
, wxART_CMN_DIALOG
));
1065 but
->SetToolTip( _("View files as a list view") );
1067 buttonsizer
->Add( but
, 0, wxALL
, 5 );
1069 but
= new wxBitmapButton(this, ID_REPORT_MODE
,
1070 wxArtProvider::GetBitmap(wxART_REPORT_VIEW
, wxART_CMN_DIALOG
));
1072 but
->SetToolTip( _("View files as a detailed view") );
1074 buttonsizer
->Add( but
, 0, wxALL
, 5 );
1076 buttonsizer
->Add( 30, 5, 1 );
1078 wxWindow
*butDirUp
=
1079 new wxBitmapButton(this, ID_UP_DIR
,
1080 wxArtProvider::GetBitmap(wxART_GO_DIR_UP
, wxART_CMN_DIALOG
));
1082 butDirUp
->SetToolTip( _("Go to parent directory") );
1084 buttonsizer
->Add( butDirUp
, 0, wxALL
, 5 );
1086 #ifndef __DOS__ // VS: Home directory is meaningless in MS-DOS...
1087 but
= new wxBitmapButton(this, ID_PARENT_DIR
,
1088 wxArtProvider::GetBitmap(wxART_GO_HOME
, wxART_CMN_DIALOG
));
1090 but
->SetToolTip( _("Go to home directory") );
1092 buttonsizer
->Add( but
, 0, wxALL
, 5);
1094 buttonsizer
->Add( 20, 20 );
1097 wxWindow
*butNewDir
=
1098 new wxBitmapButton(this, ID_NEW_DIR
,
1099 wxArtProvider::GetBitmap(wxART_NEW_DIR
, wxART_CMN_DIALOG
));
1101 butNewDir
->SetToolTip( _("Create new directory") );
1103 buttonsizer
->Add( butNewDir
, 0, wxALL
, 5 );
1106 mainsizer
->Add( buttonsizer
, 0, wxALL
| wxEXPAND
, 0 );
1108 mainsizer
->Add( buttonsizer
, 0, wxALL
| wxEXPAND
, 5 );
1111 wxBoxSizer
*staticsizer
= new wxBoxSizer( wxHORIZONTAL
);
1113 staticsizer
->Add( new wxStaticText( this, -1, _("Current directory:") ), 0, wxRIGHT
, 10 );
1115 m_static
= new wxStaticText( this, -1, m_dir
);
1116 staticsizer
->Add( m_static
, 1 );
1117 mainsizer
->Add( staticsizer
, 0, wxEXPAND
| wxLEFT
|wxRIGHT
|wxBOTTOM
, 10 );
1119 if (m_dialogStyle
& wxMULTIPLE
)
1120 m_list
= new wxFileCtrl( this, ID_LIST_CTRL
, m_dir
, firstWild
, wxDefaultPosition
,
1121 wxSize(540,200), s_lastViewStyle
| wxSUNKEN_BORDER
);
1123 m_list
= new wxFileCtrl( this, ID_LIST_CTRL
, m_dir
, firstWild
, wxDefaultPosition
,
1124 wxSize(540,200), s_lastViewStyle
| wxSUNKEN_BORDER
| wxLC_SINGLE_SEL
);
1125 m_list
->ShowHidden(s_lastShowHidden
);
1126 m_list
->SetNewDirControl(butNewDir
);
1127 m_list
->SetGoToParentControl(butDirUp
);
1130 // PDAs have a different screen layout
1131 mainsizer
->Add( m_list
, 1, wxEXPAND
| wxLEFT
|wxRIGHT
, 5 );
1133 wxBoxSizer
*choicesizer
= new wxBoxSizer( wxHORIZONTAL
);
1134 m_choice
= new wxChoice( this, ID_CHOICE
);
1135 choicesizer
->Add( m_choice
, 1, wxCENTER
|wxALL
, 5 );
1136 mainsizer
->Add( choicesizer
, 0, wxEXPAND
);
1138 wxBoxSizer
*textsizer
= new wxBoxSizer( wxHORIZONTAL
);
1139 m_text
= new wxTextCtrl( this, ID_TEXT
, m_fileName
, wxDefaultPosition
, wxDefaultSize
, wxPROCESS_ENTER
);
1140 textsizer
->Add( m_text
, 1, wxCENTER
| wxALL
, 5 );
1141 mainsizer
->Add( textsizer
, 0, wxEXPAND
);
1143 m_check
= new wxCheckBox( this, ID_CHECK
, _("Show hidden files") );
1144 m_check
->SetValue( s_lastShowHidden
);
1145 textsizer
->Add( m_check
, 0, wxCENTER
|wxALL
, 5 );
1147 buttonsizer
= new wxBoxSizer( wxHORIZONTAL
);
1148 buttonsizer
->Add( new wxButton( this, wxID_OK
, _("OK") ), 0, wxCENTER
| wxALL
, 5 );
1149 buttonsizer
->Add( new wxButton( this, wxID_CANCEL
, _("Cancel") ), 0, wxCENTER
| wxALL
, 5 );
1150 mainsizer
->Add( buttonsizer
, 0, wxALIGN_RIGHT
);
1153 mainsizer
->Add( m_list
, 1, wxEXPAND
| wxLEFT
|wxRIGHT
, 10 );
1155 wxBoxSizer
*textsizer
= new wxBoxSizer( wxHORIZONTAL
);
1156 m_text
= new wxTextCtrl( this, ID_TEXT
, m_fileName
, wxDefaultPosition
, wxDefaultSize
, wxPROCESS_ENTER
);
1157 textsizer
->Add( m_text
, 1, wxCENTER
| wxLEFT
|wxRIGHT
|wxTOP
, 10 );
1158 textsizer
->Add( new wxButton( this, wxID_OK
, _("OK") ), 0, wxCENTER
| wxLEFT
|wxRIGHT
|wxTOP
, 10 );
1159 mainsizer
->Add( textsizer
, 0, wxEXPAND
);
1161 wxBoxSizer
*choicesizer
= new wxBoxSizer( wxHORIZONTAL
);
1162 m_choice
= new wxChoice( this, ID_CHOICE
);
1163 choicesizer
->Add( m_choice
, 1, wxCENTER
|wxALL
, 10 );
1164 m_check
= new wxCheckBox( this, ID_CHECK
, _("Show hidden files") );
1165 m_check
->SetValue( s_lastShowHidden
);
1166 choicesizer
->Add( m_check
, 0, wxCENTER
|wxALL
, 10 );
1167 choicesizer
->Add( new wxButton( this, wxID_CANCEL
, _("Cancel") ), 0, wxCENTER
| wxALL
, 10 );
1168 mainsizer
->Add( choicesizer
, 0, wxEXPAND
);
1172 m_choice
->Append( firstWildText
, (void*) new wxString( firstWild
) );
1173 while (tokens
.HasMoreTokens())
1175 firstWildText
= tokens
.GetNextToken();
1176 firstWild
= tokens
.GetNextToken();
1177 m_choice
->Append( firstWildText
, (void*) new wxString( firstWild
) );
1179 m_choice
->SetSelection( 0 );
1181 SetAutoLayout( TRUE
);
1182 SetSizer( mainsizer
);
1184 mainsizer
->Fit( this );
1185 mainsizer
->SetSizeHints( this );
1190 if (m_fileName.IsEmpty())
1197 wxFileDialog::~wxFileDialog()
1199 if (wxConfig::Get(FALSE
))
1201 wxConfig::Get()->Write(wxT("/wxWindows/wxFileDialog/ViewStyle"),
1203 wxConfig::Get()->Write(wxT("/wxWindows/wxFileDialog/ShowHidden"),
1208 void wxFileDialog::OnChoice( wxCommandEvent
&event
)
1210 int index
= (int)event
.GetInt();
1211 wxString
*str
= (wxString
*) m_choice
->GetClientData( index
);
1212 m_list
->SetWild( *str
);
1213 m_filterIndex
= index
;
1214 if ( str
-> Left( 2 ) == wxT("*.") )
1216 m_filterExtension
= str
-> Mid( 1 );
1217 if (m_filterExtension
== ".*") m_filterExtension
= wxEmptyString
;
1220 m_filterExtension
= wxEmptyString
;
1223 void wxFileDialog::OnCheck( wxCommandEvent
&event
)
1225 m_list
->ShowHidden( (s_lastShowHidden
= event
.GetInt() != 0) );
1228 void wxFileDialog::OnActivated( wxListEvent
&event
)
1230 HandleAction( event
.m_item
.m_text
);
1233 void wxFileDialog::OnTextEnter( wxCommandEvent
&WXUNUSED(event
) )
1235 wxCommandEvent
cevent(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_OK
);
1236 cevent
.SetEventObject( this );
1237 GetEventHandler()->ProcessEvent( cevent
);
1240 void wxFileDialog::OnSelected( wxListEvent
&event
)
1242 wxString
filename( event
.m_item
.m_text
);
1243 if (filename
== wxT("..")) return;
1246 m_list
->GetDir( dir
);
1247 if (!IsTopMostDir(dir
))
1248 dir
+= wxFILE_SEP_PATH
;
1250 if (wxDirExists(dir
)) return;
1252 m_text
->SetValue( filename
);
1255 void wxFileDialog::HandleAction( const wxString
&fn
)
1257 wxString
filename( fn
);
1259 m_list
->GetDir( dir
);
1260 if (filename
.IsEmpty()) return;
1261 if (filename
== wxT(".")) return;
1263 if (filename
== wxT(".."))
1265 m_list
->GoToParentDir();
1267 m_list
->GetDir( dir
);
1268 m_static
->SetLabel( dir
);
1273 if (filename
== wxT("~"))
1275 m_list
->GoToHomeDir();
1277 m_list
->GetDir( dir
);
1278 m_static
->SetLabel( dir
);
1282 if (filename
[0u] == wxT('~'))
1284 filename
.Remove( 0, 1 );
1285 wxString
tmp( wxGetUserHome() );
1292 if ((filename
.Find(wxT('*')) != wxNOT_FOUND
) ||
1293 (filename
.Find(wxT('?')) != wxNOT_FOUND
))
1295 if (filename
.Find(wxFILE_SEP_PATH
) != wxNOT_FOUND
)
1297 wxMessageBox(_("Illegal file specification."), _("Error"), wxOK
| wxICON_ERROR
);
1300 m_list
->SetWild( filename
);
1304 if (!IsTopMostDir(dir
))
1305 dir
+= wxFILE_SEP_PATH
;
1306 if (!wxIsAbsolutePath(filename
))
1312 if (wxDirExists(filename
))
1314 m_list
->GoToDir( filename
);
1315 m_list
->GetDir( dir
);
1316 m_static
->SetLabel( dir
);
1321 if ( (m_dialogStyle
& wxSAVE
) && (m_dialogStyle
& wxOVERWRITE_PROMPT
) )
1323 if (filename
.Find( wxT('.') ) == wxNOT_FOUND
||
1324 filename
.AfterLast( wxT('.') ).Find( wxFILE_SEP_PATH
) != wxNOT_FOUND
)
1325 filename
<< m_filterExtension
;
1326 if (wxFileExists( filename
))
1329 msg
.Printf( _("File '%s' already exists, do you really want to "
1330 "overwrite it?"), filename
.c_str() );
1332 if (wxMessageBox(msg
, _("Confirm"), wxYES_NO
) != wxYES
)
1336 else if ( m_dialogStyle
& wxOPEN
)
1338 if ( !wxFileExists( filename
) )
1339 if (filename
.Find( wxT('.') ) == wxNOT_FOUND
||
1340 filename
.AfterLast( wxT('.') ).Find( wxFILE_SEP_PATH
) != wxNOT_FOUND
)
1341 filename
<< m_filterExtension
;
1343 if ( m_dialogStyle
& wxFILE_MUST_EXIST
)
1345 if ( !wxFileExists( filename
) )
1347 wxMessageBox(_("Please choose an existing file."), _("Error"), wxOK
| wxICON_ERROR
);
1353 SetPath( filename
);
1355 // change to the directory where the user went if asked
1356 if ( m_dialogStyle
& wxCHANGE_DIR
)
1359 wxSplitPath(filename
, &cwd
, NULL
, NULL
);
1361 if ( cwd
!= wxGetWorkingDirectory() )
1363 wxSetWorkingDirectory(cwd
);
1367 wxCommandEvent event
;
1368 wxDialog::OnOK(event
);
1371 void wxFileDialog::OnListOk( wxCommandEvent
&WXUNUSED(event
) )
1373 HandleAction( m_text
->GetValue() );
1376 void wxFileDialog::OnList( wxCommandEvent
&WXUNUSED(event
) )
1378 m_list
->ChangeToListMode();
1379 s_lastViewStyle
= wxLC_LIST
;
1383 void wxFileDialog::OnReport( wxCommandEvent
&WXUNUSED(event
) )
1385 m_list
->ChangeToReportMode();
1386 s_lastViewStyle
= wxLC_REPORT
;
1390 void wxFileDialog::OnUp( wxCommandEvent
&WXUNUSED(event
) )
1392 m_list
->GoToParentDir();
1395 m_list
->GetDir( dir
);
1396 m_static
->SetLabel( dir
);
1399 void wxFileDialog::OnHome( wxCommandEvent
&WXUNUSED(event
) )
1401 m_list
->GoToHomeDir();
1404 m_list
->GetDir( dir
);
1405 m_static
->SetLabel( dir
);
1408 void wxFileDialog::OnNew( wxCommandEvent
&WXUNUSED(event
) )
1413 void wxFileDialog::SetPath( const wxString
& path
)
1415 // not only set the full path but also update filename and dir
1420 wxSplitPath(path
, &m_dir
, &m_fileName
, &ext
);
1423 m_fileName
+= wxT(".");
1429 void wxFileDialog::GetPaths( wxArrayString
& paths
) const
1432 if (m_list
->GetSelectedItemCount() == 0)
1434 paths
.Add( GetPath() );
1438 paths
.Alloc( m_list
->GetSelectedItemCount() );
1441 m_list
->GetDir( dir
);
1443 if (dir
!= wxT("/"))
1445 dir
+= wxFILE_SEP_PATH
;
1448 item
.m_mask
= wxLIST_MASK_TEXT
;
1450 item
.m_itemId
= m_list
->GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1451 while ( item
.m_itemId
!= -1 )
1453 m_list
->GetItem( item
);
1454 paths
.Add( dir
+ item
.m_text
);
1455 item
.m_itemId
= m_list
->GetNextItem( item
.m_itemId
,
1456 wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1460 void wxFileDialog::GetFilenames(wxArrayString
& files
) const
1463 if (m_list
->GetSelectedItemCount() == 0)
1465 files
.Add( GetFilename() );
1468 files
.Alloc( m_list
->GetSelectedItemCount() );
1471 item
.m_mask
= wxLIST_MASK_TEXT
;
1473 item
.m_itemId
= m_list
->GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1474 while ( item
.m_itemId
!= -1 )
1476 m_list
->GetItem( item
);
1477 files
.Add( item
.m_text
);
1478 item
.m_itemId
= m_list
->GetNextItem( item
.m_itemId
,
1479 wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1485 // ----------------------------------------------------------------------------
1487 // ----------------------------------------------------------------------------
1490 wxFileSelectorEx(const wxChar
*message
,
1491 const wxChar
*default_path
,
1492 const wxChar
*default_filename
,
1493 int *WXUNUSED(indexDefaultExtension
),
1494 const wxChar
*wildcard
,
1499 // TODO: implement this somehow
1500 return wxFileSelector(message
, default_path
, default_filename
, wxT(""),
1501 wildcard
, flags
, parent
, x
, y
);
1504 wxString
wxFileSelector( const wxChar
*title
,
1505 const wxChar
*defaultDir
, const wxChar
*defaultFileName
,
1506 const wxChar
*defaultExtension
, const wxChar
*filter
, int flags
,
1507 wxWindow
*parent
, int x
, int y
)
1510 if ( defaultExtension
&& !filter
)
1511 filter2
= wxString(wxT("*.")) + wxString(defaultExtension
) ;
1515 wxString defaultDirString
;
1517 defaultDirString
= defaultDir
;
1519 wxString defaultFilenameString
;
1520 if (defaultFileName
)
1521 defaultFilenameString
= defaultFileName
;
1523 wxFileDialog
fileDialog( parent
, title
, defaultDirString
, defaultFilenameString
, filter2
, flags
, wxPoint(x
, y
) );
1525 if ( fileDialog
.ShowModal() == wxID_OK
)
1527 return fileDialog
.GetPath();
1531 return wxEmptyString
;
1535 wxString
wxLoadFileSelector( const wxChar
*what
, const wxChar
*ext
, const wxChar
*default_name
, wxWindow
*parent
)
1537 wxString prompt
= wxString::Format(_("Load %s file"), what
);
1539 if (*ext
== wxT('.'))
1542 wxString wild
= wxString::Format(_T("*.%s"), ext
);
1544 return wxFileSelector(prompt
, (const wxChar
*) NULL
, default_name
,
1545 ext
, wild
, 0, parent
);
1548 wxString
wxSaveFileSelector(const wxChar
*what
, const wxChar
*extension
, const wxChar
*default_name
,
1551 wxChar
*ext
= (wxChar
*)extension
;
1553 wxString prompt
= wxString::Format(_("Save %s file"), what
);
1555 if (*ext
== wxT('.'))
1558 wxString wild
= wxString::Format(_T("*.%s"), ext
);
1560 return wxFileSelector(prompt
, (const wxChar
*) NULL
, default_name
,
1561 ext
, wild
, 0, parent
);
1569 // A module to allow icons table cleanup
1571 class wxFileDialogGenericModule
: public wxModule
1573 DECLARE_DYNAMIC_CLASS(wxFileDialogGenericModule
)
1575 wxFileDialogGenericModule() {}
1576 bool OnInit() { return TRUE
; }
1577 void OnExit() { if (g_IconsTable
) {delete g_IconsTable
; g_IconsTable
= NULL
;} }
1580 IMPLEMENT_DYNAMIC_CLASS(wxFileDialogGenericModule
, wxModule
)
1582 #endif // wxUSE_FILEDLG