1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxFileDialog
4 // Author: Robert Roebling
8 // Copyright: (c) Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation "filedlgg.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
33 #if !defined(__UNIX__) && !defined(__DOS__)
34 #error wxFileDialog currently only supports Unix and DOS
37 #include "wx/checkbox.h"
38 #include "wx/textctrl.h"
39 #include "wx/choice.h"
40 #include "wx/checkbox.h"
41 #include "wx/stattext.h"
42 #include "wx/filedlg.h"
46 #include "wx/listctrl.h"
47 #include "wx/msgdlg.h"
49 #include "wx/bmpbuttn.h"
50 #include "wx/tokenzr.h"
51 #include "wx/mimetype.h"
53 #include "wx/module.h"
54 #include "wx/config.h"
55 #include "wx/imaglist.h"
57 #include "wx/artprov.h"
60 #include "wx/tooltip.h"
63 #include <sys/types.h>
81 // ----------------------------------------------------------------------------
83 // ----------------------------------------------------------------------------
85 // the list ctrl fields in report view
98 //-----------------------------------------------------------------------------
100 //-----------------------------------------------------------------------------
105 wxFileData( const wxString
&name
, const wxString
&fname
);
106 wxString
GetName() const;
107 wxString
GetFullName() const;
108 wxString
GetHint() const;
109 wxString
GetEntry( FileListField num
) const;
111 bool IsDir() const { return m_isDir
; }
112 bool IsLink() const { return m_isLink
; }
113 bool IsExe() const { return m_isExe
; }
114 long GetSize() const { return m_size
; }
116 void MakeItem( wxListItem
&item
);
117 void SetNewName( const wxString
&name
, const wxString
&fname
);
128 wxString m_permissions
;
134 //-----------------------------------------------------------------------------
136 //-----------------------------------------------------------------------------
138 class wxFileCtrl
: public wxListCtrl
142 wxFileCtrl( wxWindow
*win
,
144 const wxString
&wild
,
146 const wxPoint
&pos
= wxDefaultPosition
,
147 const wxSize
&size
= wxDefaultSize
,
148 long style
= wxLC_LIST
,
149 const wxValidator
&validator
= wxDefaultValidator
,
150 const wxString
&name
= wxT("filelist") );
151 virtual ~wxFileCtrl();
153 void ChangeToListMode();
154 void ChangeToReportMode();
155 void ChangeToIconMode();
156 void ShowHidden( bool show
= TRUE
);
157 long Add( wxFileData
*fd
, wxListItem
&item
);
159 virtual void StatusbarText( wxChar
*WXUNUSED(text
) ) {};
161 void GoToParentDir();
163 void GoToDir( const wxString
&dir
);
164 void SetWild( const wxString
&wild
);
165 void GetDir( wxString
&dir
);
166 void OnListDeleteItem( wxListEvent
&event
);
167 void OnListEndLabelEdit( wxListEvent
&event
);
169 // Associate commonly used UI controls with wxFileCtrl so that they can be
170 // disabled when they cannot be used (e.g. can't go to parent directory
171 // if wxFileCtrl already is in the root dir):
172 void SetGoToParentControl(wxWindow
*ctrl
) { m_goToParentControl
= ctrl
; }
173 void SetNewDirControl(wxWindow
*ctrl
) { m_newDirControl
= ctrl
; }
176 void FreeItemData(const wxListItem
& item
);
177 void FreeAllItemsData();
183 wxWindow
*m_goToParentControl
;
184 wxWindow
*m_newDirControl
;
186 DECLARE_DYNAMIC_CLASS(wxFileCtrl
);
187 DECLARE_EVENT_TABLE()
190 // ----------------------------------------------------------------------------
191 // private classes - icons list management
192 // ----------------------------------------------------------------------------
194 class wxFileIconEntry
: public wxObject
197 wxFileIconEntry(int i
) { id
= i
; }
203 class wxFileIconsTable
208 int GetIconID(const wxString
& extension
, const wxString
& mime
= wxEmptyString
);
209 wxImageList
*GetImageList() { return &m_ImageList
; }
212 wxImageList m_ImageList
;
213 wxHashTable m_HashTable
;
216 static wxFileIconsTable
*g_IconsTable
= NULL
;
220 #define FI_EXECUTABLE 2
222 wxFileIconsTable::wxFileIconsTable() :
224 m_HashTable(wxKEY_STRING
)
226 m_HashTable
.DeleteContents(TRUE
);
228 m_ImageList
.Add(wxArtProvider::GetBitmap(wxART_FOLDER
, wxART_CMN_DIALOG
));
230 m_ImageList
.Add(wxArtProvider::GetBitmap(wxART_NORMAL_FILE
, wxART_CMN_DIALOG
));
232 if (GetIconID(wxEmptyString
, _T("application/x-executable")) == FI_UNKNOWN
)
234 m_ImageList
.Add(wxArtProvider::GetBitmap(wxART_EXECUTABLE_FILE
, wxART_CMN_DIALOG
));
235 m_HashTable
.Delete(_T("exe"));
236 m_HashTable
.Put(_T("exe"), new wxFileIconEntry(FI_EXECUTABLE
));
238 /* else put into list by GetIconID
239 (KDE defines application/x-executable for *.exe and has nice icon)
246 // VS: we don't need this function w/o wxMimeTypesManager because we'll only have
247 // one icon and we won't resize it
249 static wxBitmap
CreateAntialiasedBitmap(const wxImage
& img
)
251 wxImage
small(16, 16);
252 unsigned char *p1
, *p2
, *ps
;
253 unsigned char mr
= img
.GetMaskRed(),
254 mg
= img
.GetMaskGreen(),
255 mb
= img
.GetMaskBlue();
258 unsigned sr
, sg
, sb
, smask
;
260 p1
= img
.GetData(), p2
= img
.GetData() + 3 * 32, ps
= small
.GetData();
261 small
.SetMaskColour(mr
, mr
, mr
);
263 for (y
= 0; y
< 16; y
++)
265 for (x
= 0; x
< 16; x
++)
267 sr
= sg
= sb
= smask
= 0;
268 if (p1
[0] != mr
|| p1
[1] != mg
|| p1
[2] != mb
)
269 sr
+= p1
[0], sg
+= p1
[1], sb
+= p1
[2];
272 if (p1
[0] != mr
|| p1
[1] != mg
|| p1
[2] != mb
)
273 sr
+= p1
[0], sg
+= p1
[1], sb
+= p1
[2];
276 if (p2
[0] != mr
|| p2
[1] != mg
|| p2
[2] != mb
)
277 sr
+= p2
[0], sg
+= p2
[1], sb
+= p2
[2];
280 if (p2
[0] != mr
|| p2
[1] != mg
|| p2
[2] != mb
)
281 sr
+= p2
[0], sg
+= p2
[1], sb
+= p2
[2];
286 ps
[0] = ps
[1] = ps
[2] = mr
;
288 ps
[0] = sr
>> 2, ps
[1] = sg
>> 2, ps
[2] = sb
>> 2;
291 p1
+= 32 * 3, p2
+= 32 * 3;
294 return wxBitmap(small
);
297 // finds empty borders and return non-empty area of image:
298 static wxImage
CutEmptyBorders(const wxImage
& img
)
300 unsigned char mr
= img
.GetMaskRed(),
301 mg
= img
.GetMaskGreen(),
302 mb
= img
.GetMaskBlue();
303 unsigned char *dt
= img
.GetData(), *dttmp
;
304 unsigned w
= img
.GetWidth(), h
= img
.GetHeight();
306 unsigned top
, bottom
, left
, right
, i
;
309 #define MK_DTTMP(x,y) dttmp = dt + ((x + y * w) * 3)
310 #define NOEMPTY_PIX(empt) if (dttmp[0] != mr || dttmp[1] != mg || dttmp[2] != mb) {empt = FALSE; break;}
312 for (empt
= TRUE
, top
= 0; empt
&& top
< h
; top
++)
315 for (i
= 0; i
< w
; i
++, dttmp
+=3)
318 for (empt
= TRUE
, bottom
= h
-1; empt
&& bottom
> top
; bottom
--)
321 for (i
= 0; i
< w
; i
++, dttmp
+=3)
324 for (empt
= TRUE
, left
= 0; empt
&& left
< w
; left
++)
327 for (i
= 0; i
< h
; i
++, dttmp
+=3*w
)
330 for (empt
= TRUE
, right
= w
-1; empt
&& right
> left
; right
--)
333 for (i
= 0; i
< h
; i
++, dttmp
+=3*w
)
336 top
--, left
--, bottom
++, right
++;
338 return img
.GetSubImage(wxRect(left
, top
, right
- left
+ 1, bottom
- top
+ 1));
340 #endif // wxUSE_MIMETYPE
344 int wxFileIconsTable::GetIconID(const wxString
& extension
, const wxString
& mime
)
347 if (!extension
.IsEmpty())
349 wxFileIconEntry
*entry
= (wxFileIconEntry
*) m_HashTable
.Get(extension
);
350 if (entry
) return (entry
-> id
);
353 wxFileType
*ft
= (mime
.IsEmpty()) ?
354 wxTheMimeTypesManager
-> GetFileTypeFromExtension(extension
) :
355 wxTheMimeTypesManager
-> GetFileTypeFromMimeType(mime
);
357 if (ft
== NULL
|| (!ft
-> GetIcon(&ic
)) || (!ic
.Ok()))
359 int newid
= FI_UNKNOWN
;
360 m_HashTable
.Put(extension
, new wxFileIconEntry(newid
));
363 wxImage img
= ic
.ConvertToImage();
366 int id
= m_ImageList
.GetImageCount();
367 if (img
.GetWidth() == 16 && img
.GetHeight() == 16)
368 m_ImageList
.Add(wxBitmap(img
));
371 if (img
.GetWidth() != 32 || img
.GetHeight() != 32)
372 m_ImageList
.Add(CreateAntialiasedBitmap(CutEmptyBorders(img
).Rescale(32, 32)));
374 m_ImageList
.Add(CreateAntialiasedBitmap(img
));
376 m_HashTable
.Put(extension
, new wxFileIconEntry(id
));
379 #else // !wxUSE_MIMETYPE
381 if (extension
== wxT("exe"))
382 return FI_EXECUTABLE
;
385 #endif // wxUSE_MIMETYPE/!wxUSE_MIMETYPE
390 // ----------------------------------------------------------------------------
392 // ----------------------------------------------------------------------------
395 int ListCompare( long data1
, long data2
, long WXUNUSED(data
) )
397 wxFileData
*fd1
= (wxFileData
*)data1
;
398 wxFileData
*fd2
= (wxFileData
*)data2
;
399 if (fd1
->GetName() == wxT("..")) return -1;
400 if (fd2
->GetName() == wxT("..")) return 1;
401 if (fd1
->IsDir() && !fd2
->IsDir()) return -1;
402 if (fd2
->IsDir() && !fd1
->IsDir()) return 1;
403 return wxStrcmp( fd1
->GetName(), fd2
->GetName() );
407 #define IsTopMostDir(dir) (dir == wxT("/"))
410 #if defined(__DOS__) || defined(__WINDOWS__)
411 #define IsTopMostDir(dir) (dir.IsEmpty())
414 #if defined(__DOS__) || defined(__WINDOWS__)
415 extern bool wxIsDriveAvailable(const wxString
& dirName
);
418 //-----------------------------------------------------------------------------
420 //-----------------------------------------------------------------------------
422 wxFileData::wxFileData( const wxString
&name
, const wxString
&fname
)
427 #if defined(__DOS__) || defined(__WINDOWS__)
428 // VS: In case the file is root directory of a volume (e.g. "C:"),
429 // we don't want it stat()ed, since the drive may not be in:
430 if (name
.length() == 2 && name
[1u] == wxT(':'))
433 m_isExe
= m_isLink
= FALSE
;
440 wxStat( m_fileName
, &buff
);
442 #if defined(__UNIX__) && (!defined( __EMX__ ) && !defined(__VMS))
444 lstat( m_fileName
.fn_str(), &lbuff
);
445 m_isLink
= S_ISLNK( lbuff
.st_mode
);
446 struct tm
*t
= localtime( &lbuff
.st_mtime
);
449 struct tm
*t
= localtime( &buff
.st_mtime
);
452 // struct passwd *user = getpwuid( buff.st_uid );
453 // struct group *grp = getgrgid( buff.st_gid );
455 m_isDir
= S_ISDIR( buff
.st_mode
);
456 m_isExe
= ((buff
.st_mode
& S_IXUSR
) == S_IXUSR
);
458 m_size
= buff
.st_size
;
461 m_minute
= t
->tm_min
;
462 m_month
= t
->tm_mon
+1;
468 sprintf( buffer
, "%c%c%c",
469 ((( buff
.st_mode
& S_IRUSR
) == S_IRUSR
) ? 'r' : '-'),
470 ((( buff
.st_mode
& S_IWUSR
) == S_IWUSR
) ? 'w' : '-'),
471 ((( buff
.st_mode
& S_IXUSR
) == S_IXUSR
) ? 'x' : '-') );
473 m_permissions
= wxConvUTF8
.cMB2WC( buffer
);
475 m_permissions
= buffer
;
478 // m_permissions.sprintf( wxT("%c%c%c"),
479 // ((( buff.st_mode & S_IRUSR ) == S_IRUSR ) ? wxT('r') : wxT('-')),
480 // ((( buff.st_mode & S_IWUSR ) == S_IWUSR ) ? wxT('w') : wxT('-')),
481 // ((( buff.st_mode & S_IXUSR ) == S_IXUSR ) ? wxT('x') : wxT('-')) );
484 wxString
wxFileData::GetName() const
489 wxString
wxFileData::GetFullName() const
494 wxString
wxFileData::GetHint() const
496 wxString s
= m_fileName
;
498 if (m_isDir
) s
+= _("<DIR> ");
499 else if (m_isLink
) s
+= _("<LINK> ");
502 s
+= LongToString( m_size
);
505 s
+= IntToString( m_day
);
507 s
+= IntToString( m_month
);
509 s
+= IntToString( m_year
);
511 s
+= IntToString( m_hour
);
513 s
+= IntToString( m_minute
);
519 wxString
wxFileData::GetEntry( FileListField num
) const
534 s
.Printf(_T("%ld"), m_size
);
538 s
.Printf(_T("%02d.%02d.%d"), m_day
, m_month
, m_year
);
542 s
.Printf(_T("%02d:%02d"), m_hour
, m_minute
);
552 wxFAIL_MSG( _T("unexpected field in wxFileData::GetEntry()") );
558 void wxFileData::SetNewName( const wxString
&name
, const wxString
&fname
)
564 void wxFileData::MakeItem( wxListItem
&item
)
566 item
.m_text
= m_name
;
567 item
.ClearAttributes();
569 item
.SetTextColour(*wxRED
);
571 item
.SetTextColour(*wxBLUE
);
574 item
.m_image
= FI_FOLDER
;
576 item
.m_image
= FI_EXECUTABLE
;
577 else if (m_name
.Find(wxT('.')) != wxNOT_FOUND
)
578 item
.m_image
= g_IconsTable
->GetIconID(m_name
.AfterLast(wxT('.')));
580 item
.m_image
= FI_UNKNOWN
;
584 wxColour
*dg
= wxTheColourDatabase
->FindColour( _T("MEDIUM GREY") );
585 item
.SetTextColour(*dg
);
587 item
.m_data
= (long)this;
590 //-----------------------------------------------------------------------------
592 //-----------------------------------------------------------------------------
594 IMPLEMENT_DYNAMIC_CLASS(wxFileCtrl
,wxListCtrl
)
596 BEGIN_EVENT_TABLE(wxFileCtrl
,wxListCtrl
)
597 EVT_LIST_DELETE_ITEM(-1, wxFileCtrl::OnListDeleteItem
)
598 EVT_LIST_END_LABEL_EDIT(-1, wxFileCtrl::OnListEndLabelEdit
)
602 wxFileCtrl::wxFileCtrl()
604 m_showHidden
= FALSE
;
607 wxFileCtrl::wxFileCtrl(wxWindow
*win
,
609 const wxString
& wild
,
614 const wxValidator
&validator
,
615 const wxString
&name
)
616 : wxListCtrl(win
, id
, pos
, size
, style
, validator
, name
),
620 g_IconsTable
= new wxFileIconsTable
;
621 wxImageList
*imageList
= g_IconsTable
->GetImageList();
623 SetImageList( imageList
, wxIMAGE_LIST_SMALL
);
625 m_goToParentControl
=
626 m_newDirControl
= NULL
;
628 m_showHidden
= showHidden
;
631 void wxFileCtrl::ChangeToListMode()
633 SetSingleStyle( wxLC_LIST
);
637 void wxFileCtrl::ChangeToReportMode()
639 SetSingleStyle( wxLC_REPORT
);
643 void wxFileCtrl::ChangeToIconMode()
645 SetSingleStyle( wxLC_ICON
);
649 void wxFileCtrl::ShowHidden( bool show
)
655 long wxFileCtrl::Add( wxFileData
*fd
, wxListItem
&item
)
658 item
.m_mask
= wxLIST_MASK_TEXT
+ wxLIST_MASK_DATA
+ wxLIST_MASK_IMAGE
;
659 fd
->MakeItem( item
);
660 long my_style
= GetWindowStyleFlag();
661 if (my_style
& wxLC_REPORT
)
663 ret
= InsertItem( item
);
664 for (int i
= 1; i
< FileList_Max
; i
++)
665 SetItem( item
.m_itemId
, i
, fd
->GetEntry((FileListField
)i
) );
667 else if (my_style
& wxLC_LIST
)
669 ret
= InsertItem( item
);
674 void wxFileCtrl::UpdateFiles()
676 wxBusyCursor bcur
; // this may take a while...
678 long my_style
= GetWindowStyleFlag();
679 int name_col_width
= 0;
680 if (my_style
& wxLC_REPORT
)
682 if (GetColumnCount() > 0)
683 name_col_width
= GetColumnWidth( 0 );
689 if (my_style
& wxLC_REPORT
)
691 if (name_col_width
< 140) name_col_width
= 140;
692 InsertColumn( 0, _("Name"), wxLIST_FORMAT_LEFT
, name_col_width
);
693 InsertColumn( 1, _("Size"), wxLIST_FORMAT_LEFT
, 60 );
694 InsertColumn( 2, _("Date"), wxLIST_FORMAT_LEFT
, 65 );
695 InsertColumn( 3, _("Time"), wxLIST_FORMAT_LEFT
, 50 );
697 InsertColumn( 4, _("Permissions"), wxLIST_FORMAT_LEFT
, 120 );
700 wxFileData
*fd
= (wxFileData
*) NULL
;
705 #if defined(__DOS__) || defined(__WINDOWS__)
706 if ( IsTopMostDir(m_dirName
) )
708 // Pseudo-directory with all available drives listed...
709 for (int drive
= 1; drive
<= 26; drive
++)
712 path
.Printf(wxT("%c:\\"), (char)(drive
+ 'A' - 1));
713 if ( wxIsDriveAvailable(path
) )
716 fd
= new wxFileData(path
, path
);
726 if ( !IsTopMostDir(m_dirName
) )
728 wxString
p(wxPathOnly(m_dirName
));
730 if (p
.IsEmpty()) p
= wxT("/");
732 fd
= new wxFileData( wxT(".."), p
);
737 wxString
dirname(m_dirName
);
738 #if defined(__DOS__) || defined(__WINDOWS__)
739 if (dirname
.length() == 2 && dirname
[1u] == wxT(':'))
740 dirname
<< wxT('\\');
744 if ( dir
.IsOpened() )
746 wxString
dirPrefix(dirname
+ wxFILE_SEP_PATH
);
747 int hiddenFlag
= m_showHidden
? wxDIR_HIDDEN
: 0;
752 // Get the directories first (not matched against wildcards):
753 cont
= dir
.GetFirst(&f
, wxEmptyString
, wxDIR_DIRS
| hiddenFlag
);
756 fd
= new wxFileData(f
, dirPrefix
+ f
);
759 cont
= dir
.GetNext(&f
);
762 // Tokenize the wildcard string, so we can handle more than 1
763 // search pattern in a wildcard.
764 wxStringTokenizer
tokenWild(m_wild
, wxT(";"));
765 while ( tokenWild
.HasMoreTokens() )
767 cont
= dir
.GetFirst(&f
, tokenWild
.GetNextToken(),
768 wxDIR_FILES
| hiddenFlag
);
771 fd
= new wxFileData(f
, dirPrefix
+ f
);
774 cont
= dir
.GetNext(&f
);
780 SortItems(ListCompare
, 0);
782 if ( my_style
& wxLC_REPORT
)
784 SetColumnWidth(1, wxLIST_AUTOSIZE
);
785 SetColumnWidth(2, wxLIST_AUTOSIZE
);
786 SetColumnWidth(3, wxLIST_AUTOSIZE
);
789 // Finally, enable/disable context-dependent controls:
790 if ( m_goToParentControl
)
791 m_goToParentControl
->Enable(!IsTopMostDir(m_dirName
));
792 #if defined(__DOS__) || defined(__WINDOWS__)
793 if ( m_newDirControl
)
794 m_newDirControl
->Enable(!IsTopMostDir(m_dirName
));
798 void wxFileCtrl::SetWild( const wxString
&wild
)
804 void wxFileCtrl::MakeDir()
806 wxString
new_name( _("NewName") );
807 wxString
path( m_dirName
);
808 path
+= wxFILE_SEP_PATH
;
810 if (wxFileExists(path
))
812 // try NewName0, NewName1 etc.
815 new_name
= _("NewName");
817 num
.Printf( wxT("%d"), i
);
821 path
+= wxFILE_SEP_PATH
;
824 } while (wxFileExists(path
));
830 wxMessageDialog
dialog(this, _("Operation not permitted."), _("Error"), wxOK
| wxICON_ERROR
);
835 wxFileData
*fd
= new wxFileData( new_name
, path
);
839 long id
= Add( fd
, item
);
843 SortItems( ListCompare
, 0 );
844 id
= FindItem( 0, (long)fd
);
850 void wxFileCtrl::GoToParentDir()
852 if (!IsTopMostDir(m_dirName
))
854 size_t len
= m_dirName
.Len();
855 if (m_dirName
[len
-1] == wxFILE_SEP_PATH
)
856 m_dirName
.Remove( len
-1, 1 );
857 wxString
fname( wxFileNameFromPath(m_dirName
) );
858 m_dirName
= wxPathOnly( m_dirName
);
860 if (m_dirName
.IsEmpty())
861 m_dirName
= wxT("/");
864 long id
= FindItem( 0, fname
);
867 SetItemState( id
, wxLIST_STATE_SELECTED
, wxLIST_STATE_SELECTED
);
873 void wxFileCtrl::GoToHomeDir()
875 wxString s
= wxGetUserHome( wxString() );
879 void wxFileCtrl::GoToDir( const wxString
&dir
)
883 SetItemState( 0, wxLIST_STATE_SELECTED
, wxLIST_STATE_SELECTED
);
887 void wxFileCtrl::GetDir( wxString
&dir
)
892 void wxFileCtrl::FreeItemData(const wxListItem
& item
)
894 wxFileData
*fd
= (wxFileData
*)item
.m_data
;
898 void wxFileCtrl::OnListDeleteItem( wxListEvent
&event
)
900 FreeItemData(event
.m_item
);
903 void wxFileCtrl::FreeAllItemsData()
906 item
.m_mask
= wxLIST_MASK_DATA
;
908 item
.m_itemId
= GetNextItem( -1, wxLIST_NEXT_ALL
);
909 while ( item
.m_itemId
!= -1 )
913 item
.m_itemId
= GetNextItem( item
.m_itemId
, wxLIST_NEXT_ALL
);
917 void wxFileCtrl::OnListEndLabelEdit( wxListEvent
&event
)
919 wxFileData
*fd
= (wxFileData
*)event
.m_item
.m_data
;
922 if ((event
.GetLabel().IsEmpty()) ||
923 (event
.GetLabel() == _(".")) ||
924 (event
.GetLabel() == _("..")) ||
925 (event
.GetLabel().First( wxFILE_SEP_PATH
) != wxNOT_FOUND
))
927 wxMessageDialog
dialog(this, _("Illegal directory name."), _("Error"), wxOK
| wxICON_ERROR
);
933 wxString
new_name( wxPathOnly( fd
->GetFullName() ) );
934 new_name
+= wxFILE_SEP_PATH
;
935 new_name
+= event
.GetLabel();
939 if (wxFileExists(new_name
))
941 wxMessageDialog
dialog(this, _("File name exists already."), _("Error"), wxOK
| wxICON_ERROR
);
946 if (wxRenameFile(fd
->GetFullName(),new_name
))
948 fd
->SetNewName( new_name
, event
.GetLabel() );
949 SetItemState( event
.GetItem(), wxLIST_STATE_SELECTED
, wxLIST_STATE_SELECTED
);
950 EnsureVisible( event
.GetItem() );
954 wxMessageDialog
dialog(this, _("Operation not permitted."), _("Error"), wxOK
| wxICON_ERROR
);
960 wxFileCtrl::~wxFileCtrl()
965 //-----------------------------------------------------------------------------
967 //-----------------------------------------------------------------------------
969 #define ID_LIST_MODE (wxID_FILEDLGG )
970 #define ID_REPORT_MODE (wxID_FILEDLGG + 1)
971 #define ID_UP_DIR (wxID_FILEDLGG + 5)
972 #define ID_PARENT_DIR (wxID_FILEDLGG + 6)
973 #define ID_NEW_DIR (wxID_FILEDLGG + 7)
974 #define ID_CHOICE (wxID_FILEDLGG + 8)
975 #define ID_TEXT (wxID_FILEDLGG + 9)
976 #define ID_LIST_CTRL (wxID_FILEDLGG + 10)
977 #define ID_ACTIVATED (wxID_FILEDLGG + 11)
978 #define ID_CHECK (wxID_FILEDLGG + 12)
980 IMPLEMENT_DYNAMIC_CLASS(wxFileDialog
,wxDialog
)
982 BEGIN_EVENT_TABLE(wxFileDialog
,wxDialog
)
983 EVT_BUTTON(ID_LIST_MODE
, wxFileDialog::OnList
)
984 EVT_BUTTON(ID_REPORT_MODE
, wxFileDialog::OnReport
)
985 EVT_BUTTON(ID_UP_DIR
, wxFileDialog::OnUp
)
986 EVT_BUTTON(ID_PARENT_DIR
, wxFileDialog::OnHome
)
987 EVT_BUTTON(ID_NEW_DIR
, wxFileDialog::OnNew
)
988 EVT_BUTTON(wxID_OK
, wxFileDialog::OnListOk
)
989 EVT_LIST_ITEM_SELECTED(ID_LIST_CTRL
, wxFileDialog::OnSelected
)
990 EVT_LIST_ITEM_ACTIVATED(ID_LIST_CTRL
, wxFileDialog::OnActivated
)
991 EVT_CHOICE(ID_CHOICE
,wxFileDialog::OnChoice
)
992 EVT_TEXT_ENTER(ID_TEXT
,wxFileDialog::OnTextEnter
)
993 EVT_CHECKBOX(ID_CHECK
,wxFileDialog::OnCheck
)
996 long wxFileDialog::ms_lastViewStyle
= wxLC_LIST
;
997 bool wxFileDialog::ms_lastShowHidden
= FALSE
;
999 wxFileDialog::wxFileDialog(wxWindow
*parent
,
1000 const wxString
& message
,
1001 const wxString
& defaultDir
,
1002 const wxString
& defaultFile
,
1003 const wxString
& wildCard
,
1005 const wxPoint
& pos
)
1006 : wxDialog( parent
, -1, message
, pos
, wxDefaultSize
,
1007 wxDEFAULT_DIALOG_STYLE
| wxRESIZE_BORDER
)
1009 if (wxConfig::Get(FALSE
))
1011 wxConfig::Get()->Read(wxT("/wxWindows/wxFileDialog/ViewStyle"),
1013 wxConfig::Get()->Read(wxT("/wxWindows/wxFileDialog/ShowHidden"),
1014 &ms_lastShowHidden
);
1017 m_message
= message
;
1018 m_dialogStyle
= style
;
1020 if (m_dialogStyle
== 0)
1021 m_dialogStyle
= wxOPEN
;
1022 if ((m_dialogStyle
& wxMULTIPLE
) && !(m_dialogStyle
& wxOPEN
))
1023 m_dialogStyle
|= wxOPEN
;
1026 if ((m_dir
.empty()) || (m_dir
== wxT(".")))
1031 size_t len
= m_dir
.Len();
1032 if ((len
> 1) && (m_dir
[len
-1] == wxFILE_SEP_PATH
))
1033 m_dir
.Remove( len
-1, 1 );
1036 m_path
+= wxFILE_SEP_PATH
;
1037 m_path
+= defaultFile
;
1038 m_fileName
= defaultFile
;
1039 m_wildCard
= wildCard
;
1041 m_filterExtension
= wxEmptyString
;
1043 // interpret wildcards
1045 if (m_wildCard
.IsEmpty())
1046 m_wildCard
= _("All files (*)|*");
1048 wxStringTokenizer
tokens( m_wildCard
, wxT("|") );
1050 wxString firstWildText
;
1051 if (tokens
.CountTokens() == 1)
1053 firstWildText
= tokens
.GetNextToken();
1054 firstWild
= firstWildText
;
1058 wxASSERT_MSG( tokens
.CountTokens() % 2 == 0, wxT("Wrong file type descripition") );
1059 firstWildText
= tokens
.GetNextToken();
1060 firstWild
= tokens
.GetNextToken();
1062 if ( firstWild
.Left( 2 ) == wxT("*.") )
1063 m_filterExtension
= firstWild
.Mid( 1 );
1064 if ( m_filterExtension
== ".*" ) m_filterExtension
= wxEmptyString
;
1068 wxBoxSizer
*mainsizer
= new wxBoxSizer( wxVERTICAL
);
1070 wxBoxSizer
*buttonsizer
= new wxBoxSizer( wxHORIZONTAL
);
1072 wxBitmapButton
*but
;
1074 but
= new wxBitmapButton(this, ID_LIST_MODE
,
1075 wxArtProvider::GetBitmap(wxART_LIST_VIEW
, wxART_CMN_DIALOG
));
1077 but
->SetToolTip( _("View files as a list view") );
1079 buttonsizer
->Add( but
, 0, wxALL
, 5 );
1081 but
= new wxBitmapButton(this, ID_REPORT_MODE
,
1082 wxArtProvider::GetBitmap(wxART_REPORT_VIEW
, wxART_CMN_DIALOG
));
1084 but
->SetToolTip( _("View files as a detailed view") );
1086 buttonsizer
->Add( but
, 0, wxALL
, 5 );
1088 buttonsizer
->Add( 30, 5, 1 );
1090 wxWindow
*butDirUp
=
1091 new wxBitmapButton(this, ID_UP_DIR
,
1092 wxArtProvider::GetBitmap(wxART_GO_DIR_UP
, wxART_CMN_DIALOG
));
1094 butDirUp
->SetToolTip( _("Go to parent directory") );
1096 buttonsizer
->Add( butDirUp
, 0, wxALL
, 5 );
1098 #ifndef __DOS__ // VS: Home directory is meaningless in MS-DOS...
1099 but
= new wxBitmapButton(this, ID_PARENT_DIR
,
1100 wxArtProvider::GetBitmap(wxART_GO_HOME
, wxART_CMN_DIALOG
));
1102 but
->SetToolTip( _("Go to home directory") );
1104 buttonsizer
->Add( but
, 0, wxALL
, 5);
1106 buttonsizer
->Add( 20, 20 );
1109 wxWindow
*butNewDir
=
1110 new wxBitmapButton(this, ID_NEW_DIR
,
1111 wxArtProvider::GetBitmap(wxART_NEW_DIR
, wxART_CMN_DIALOG
));
1113 butNewDir
->SetToolTip( _("Create new directory") );
1115 buttonsizer
->Add( butNewDir
, 0, wxALL
, 5 );
1117 if (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA
)
1118 mainsizer
->Add( buttonsizer
, 0, wxALL
| wxEXPAND
, 0 );
1120 mainsizer
->Add( buttonsizer
, 0, wxALL
| wxEXPAND
, 5 );
1122 wxBoxSizer
*staticsizer
= new wxBoxSizer( wxHORIZONTAL
);
1123 if (wxSystemSettings::GetScreenType() > wxSYS_SCREEN_PDA
)
1124 staticsizer
->Add( new wxStaticText( this, -1, _("Current directory:") ), 0, wxRIGHT
, 10 );
1125 m_static
= new wxStaticText( this, -1, m_dir
);
1126 staticsizer
->Add( m_static
, 1 );
1127 mainsizer
->Add( staticsizer
, 0, wxEXPAND
| wxLEFT
|wxRIGHT
|wxBOTTOM
, 10 );
1129 long style2
= ms_lastViewStyle
| wxSUNKEN_BORDER
;
1130 if ( !(m_dialogStyle
& wxMULTIPLE
) )
1131 style2
|= wxLC_SINGLE_SEL
;
1133 m_list
= new wxFileCtrl( this, ID_LIST_CTRL
, firstWild
, ms_lastShowHidden
,
1134 wxDefaultPosition
, wxSize(540,200),
1137 m_list
->SetNewDirControl(butNewDir
);
1138 m_list
->SetGoToParentControl(butDirUp
);
1140 if (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA
)
1142 // PDAs have a different screen layout
1143 mainsizer
->Add( m_list
, 1, wxEXPAND
| wxLEFT
|wxRIGHT
, 5 );
1145 wxBoxSizer
*choicesizer
= new wxBoxSizer( wxHORIZONTAL
);
1146 m_choice
= new wxChoice( this, ID_CHOICE
);
1147 choicesizer
->Add( m_choice
, 1, wxCENTER
|wxALL
, 5 );
1148 mainsizer
->Add( choicesizer
, 0, wxEXPAND
);
1150 wxBoxSizer
*textsizer
= new wxBoxSizer( wxHORIZONTAL
);
1151 m_text
= new wxTextCtrl( this, ID_TEXT
, m_fileName
, wxDefaultPosition
, wxDefaultSize
, wxPROCESS_ENTER
);
1152 textsizer
->Add( m_text
, 1, wxCENTER
| wxALL
, 5 );
1153 mainsizer
->Add( textsizer
, 0, wxEXPAND
);
1155 m_check
= new wxCheckBox( this, ID_CHECK
, _("Show hidden files") );
1156 m_check
->SetValue( ms_lastShowHidden
);
1157 textsizer
->Add( m_check
, 0, wxCENTER
|wxALL
, 5 );
1159 buttonsizer
= new wxBoxSizer( wxHORIZONTAL
);
1160 buttonsizer
->Add( new wxButton( this, wxID_OK
, _("OK") ), 0, wxCENTER
| wxALL
, 5 );
1161 buttonsizer
->Add( new wxButton( this, wxID_CANCEL
, _("Cancel") ), 0, wxCENTER
| wxALL
, 5 );
1162 mainsizer
->Add( buttonsizer
, 0, wxALIGN_RIGHT
);
1166 mainsizer
->Add( m_list
, 1, wxEXPAND
| wxLEFT
|wxRIGHT
, 10 );
1168 wxBoxSizer
*textsizer
= new wxBoxSizer( wxHORIZONTAL
);
1169 m_text
= new wxTextCtrl( this, ID_TEXT
, m_fileName
, wxDefaultPosition
, wxDefaultSize
, wxPROCESS_ENTER
);
1170 textsizer
->Add( m_text
, 1, wxCENTER
| wxLEFT
|wxRIGHT
|wxTOP
, 10 );
1171 textsizer
->Add( new wxButton( this, wxID_OK
, _("OK") ), 0, wxCENTER
| wxLEFT
|wxRIGHT
|wxTOP
, 10 );
1172 mainsizer
->Add( textsizer
, 0, wxEXPAND
);
1174 wxBoxSizer
*choicesizer
= new wxBoxSizer( wxHORIZONTAL
);
1175 m_choice
= new wxChoice( this, ID_CHOICE
);
1176 choicesizer
->Add( m_choice
, 1, wxCENTER
|wxALL
, 10 );
1177 m_check
= new wxCheckBox( this, ID_CHECK
, _("Show hidden files") );
1178 m_check
->SetValue( ms_lastShowHidden
);
1179 choicesizer
->Add( m_check
, 0, wxCENTER
|wxALL
, 10 );
1180 choicesizer
->Add( new wxButton( this, wxID_CANCEL
, _("Cancel") ), 0, wxCENTER
| wxALL
, 10 );
1181 mainsizer
->Add( choicesizer
, 0, wxEXPAND
);
1184 m_choice
->Append( firstWildText
, (void*) new wxString( firstWild
) );
1185 while (tokens
.HasMoreTokens())
1187 firstWildText
= tokens
.GetNextToken();
1188 firstWild
= tokens
.GetNextToken();
1189 m_choice
->Append( firstWildText
, (void*) new wxString( firstWild
) );
1191 m_choice
->SetSelection( 0 );
1193 SetAutoLayout( TRUE
);
1194 SetSizer( mainsizer
);
1196 mainsizer
->Fit( this );
1197 mainsizer
->SetSizeHints( this );
1204 wxFileDialog::~wxFileDialog()
1206 if (wxConfig::Get(FALSE
))
1208 wxConfig::Get()->Write(wxT("/wxWindows/wxFileDialog/ViewStyle"),
1210 wxConfig::Get()->Write(wxT("/wxWindows/wxFileDialog/ShowHidden"),
1215 int wxFileDialog::ShowModal()
1217 m_list
->GoToDir(m_dir
);
1219 return wxDialog::ShowModal();
1222 void wxFileDialog::SetFilterIndex( int filterindex
)
1224 m_choice
->SetSelection( filterindex
);
1225 wxCommandEvent event
;
1226 event
.SetInt( filterindex
);
1230 void wxFileDialog::OnChoice( wxCommandEvent
&event
)
1232 int index
= (int)event
.GetInt();
1233 wxString
*str
= (wxString
*) m_choice
->GetClientData( index
);
1234 m_list
->SetWild( *str
);
1235 m_filterIndex
= index
;
1236 if ( str
-> Left( 2 ) == wxT("*.") )
1238 m_filterExtension
= str
-> Mid( 1 );
1239 if (m_filterExtension
== ".*") m_filterExtension
= wxEmptyString
;
1242 m_filterExtension
= wxEmptyString
;
1245 void wxFileDialog::OnCheck( wxCommandEvent
&event
)
1247 m_list
->ShowHidden( (ms_lastShowHidden
= event
.GetInt() != 0) );
1250 void wxFileDialog::OnActivated( wxListEvent
&event
)
1252 HandleAction( event
.m_item
.m_text
);
1255 void wxFileDialog::OnTextEnter( wxCommandEvent
&WXUNUSED(event
) )
1257 wxCommandEvent
cevent(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_OK
);
1258 cevent
.SetEventObject( this );
1259 GetEventHandler()->ProcessEvent( cevent
);
1262 void wxFileDialog::OnSelected( wxListEvent
&event
)
1264 wxString
filename( event
.m_item
.m_text
);
1265 if (filename
== wxT("..")) return;
1268 m_list
->GetDir( dir
);
1269 if (!IsTopMostDir(dir
))
1270 dir
+= wxFILE_SEP_PATH
;
1272 if (wxDirExists(dir
)) return;
1274 m_text
->SetValue( filename
);
1277 void wxFileDialog::HandleAction( const wxString
&fn
)
1279 wxString
filename( fn
);
1281 m_list
->GetDir( dir
);
1282 if (filename
.IsEmpty()) return;
1283 if (filename
== wxT(".")) return;
1285 if (filename
== wxT(".."))
1287 m_list
->GoToParentDir();
1289 m_list
->GetDir( dir
);
1290 m_static
->SetLabel( dir
);
1295 if (filename
== wxT("~"))
1297 m_list
->GoToHomeDir();
1299 m_list
->GetDir( dir
);
1300 m_static
->SetLabel( dir
);
1304 if (filename
[0u] == wxT('~'))
1306 filename
.Remove( 0, 1 );
1307 wxString
tmp( wxGetUserHome() );
1314 if ((filename
.Find(wxT('*')) != wxNOT_FOUND
) ||
1315 (filename
.Find(wxT('?')) != wxNOT_FOUND
))
1317 if (filename
.Find(wxFILE_SEP_PATH
) != wxNOT_FOUND
)
1319 wxMessageBox(_("Illegal file specification."), _("Error"), wxOK
| wxICON_ERROR
);
1322 m_list
->SetWild( filename
);
1326 if (!IsTopMostDir(dir
))
1327 dir
+= wxFILE_SEP_PATH
;
1328 if (!wxIsAbsolutePath(filename
))
1334 if (wxDirExists(filename
))
1336 m_list
->GoToDir( filename
);
1337 m_list
->GetDir( dir
);
1338 m_static
->SetLabel( dir
);
1343 if ( (m_dialogStyle
& wxSAVE
) && (m_dialogStyle
& wxOVERWRITE_PROMPT
) )
1345 if (filename
.Find( wxT('.') ) == wxNOT_FOUND
||
1346 filename
.AfterLast( wxT('.') ).Find( wxFILE_SEP_PATH
) != wxNOT_FOUND
)
1347 filename
<< m_filterExtension
;
1348 if (wxFileExists( filename
))
1351 msg
.Printf( _("File '%s' already exists, do you really want to "
1352 "overwrite it?"), filename
.c_str() );
1354 if (wxMessageBox(msg
, _("Confirm"), wxYES_NO
) != wxYES
)
1358 else if ( m_dialogStyle
& wxOPEN
)
1360 if ( !wxFileExists( filename
) )
1361 if (filename
.Find( wxT('.') ) == wxNOT_FOUND
||
1362 filename
.AfterLast( wxT('.') ).Find( wxFILE_SEP_PATH
) != wxNOT_FOUND
)
1363 filename
<< m_filterExtension
;
1365 if ( m_dialogStyle
& wxFILE_MUST_EXIST
)
1367 if ( !wxFileExists( filename
) )
1369 wxMessageBox(_("Please choose an existing file."), _("Error"), wxOK
| wxICON_ERROR
);
1375 SetPath( filename
);
1377 // change to the directory where the user went if asked
1378 if ( m_dialogStyle
& wxCHANGE_DIR
)
1381 wxSplitPath(filename
, &cwd
, NULL
, NULL
);
1383 if ( cwd
!= wxGetWorkingDirectory() )
1385 wxSetWorkingDirectory(cwd
);
1389 wxCommandEvent event
;
1390 wxDialog::OnOK(event
);
1393 void wxFileDialog::OnListOk( wxCommandEvent
&WXUNUSED(event
) )
1395 HandleAction( m_text
->GetValue() );
1398 void wxFileDialog::OnList( wxCommandEvent
&WXUNUSED(event
) )
1400 m_list
->ChangeToListMode();
1401 ms_lastViewStyle
= wxLC_LIST
;
1405 void wxFileDialog::OnReport( wxCommandEvent
&WXUNUSED(event
) )
1407 m_list
->ChangeToReportMode();
1408 ms_lastViewStyle
= wxLC_REPORT
;
1412 void wxFileDialog::OnUp( wxCommandEvent
&WXUNUSED(event
) )
1414 m_list
->GoToParentDir();
1417 m_list
->GetDir( dir
);
1418 m_static
->SetLabel( dir
);
1421 void wxFileDialog::OnHome( wxCommandEvent
&WXUNUSED(event
) )
1423 m_list
->GoToHomeDir();
1426 m_list
->GetDir( dir
);
1427 m_static
->SetLabel( dir
);
1432 void wxFileDialog::OnNew( wxCommandEvent
&WXUNUSED(event
) )
1437 void wxFileDialog::SetPath( const wxString
& path
)
1439 // not only set the full path but also update filename and dir
1441 if ( !path
.empty() )
1444 wxSplitPath(path
, &m_dir
, &m_fileName
, &ext
);
1447 m_fileName
+= wxT(".");
1453 void wxFileDialog::GetPaths( wxArrayString
& paths
) const
1456 if (m_list
->GetSelectedItemCount() == 0)
1458 paths
.Add( GetPath() );
1462 paths
.Alloc( m_list
->GetSelectedItemCount() );
1465 m_list
->GetDir( dir
);
1467 if (dir
!= wxT("/"))
1469 dir
+= wxFILE_SEP_PATH
;
1472 item
.m_mask
= wxLIST_MASK_TEXT
;
1474 item
.m_itemId
= m_list
->GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1475 while ( item
.m_itemId
!= -1 )
1477 m_list
->GetItem( item
);
1478 paths
.Add( dir
+ item
.m_text
);
1479 item
.m_itemId
= m_list
->GetNextItem( item
.m_itemId
,
1480 wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1484 void wxFileDialog::GetFilenames(wxArrayString
& files
) const
1487 if (m_list
->GetSelectedItemCount() == 0)
1489 files
.Add( GetFilename() );
1492 files
.Alloc( m_list
->GetSelectedItemCount() );
1495 item
.m_mask
= wxLIST_MASK_TEXT
;
1497 item
.m_itemId
= m_list
->GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1498 while ( item
.m_itemId
!= -1 )
1500 m_list
->GetItem( item
);
1501 files
.Add( item
.m_text
);
1502 item
.m_itemId
= m_list
->GetNextItem( item
.m_itemId
,
1503 wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1509 // ----------------------------------------------------------------------------
1511 // ----------------------------------------------------------------------------
1514 wxFileSelectorEx(const wxChar
*message
,
1515 const wxChar
*default_path
,
1516 const wxChar
*default_filename
,
1517 int *WXUNUSED(indexDefaultExtension
),
1518 const wxChar
*wildcard
,
1523 // TODO: implement this somehow
1524 return wxFileSelector(message
, default_path
, default_filename
, wxT(""),
1525 wildcard
, flags
, parent
, x
, y
);
1528 wxString
wxFileSelector( const wxChar
*title
,
1529 const wxChar
*defaultDir
, const wxChar
*defaultFileName
,
1530 const wxChar
*defaultExtension
, const wxChar
*filter
, int flags
,
1531 wxWindow
*parent
, int x
, int y
)
1534 if ( defaultExtension
&& !filter
)
1535 filter2
= wxString(wxT("*.")) + wxString(defaultExtension
) ;
1539 wxString defaultDirString
;
1541 defaultDirString
= defaultDir
;
1543 wxString defaultFilenameString
;
1544 if (defaultFileName
)
1545 defaultFilenameString
= defaultFileName
;
1547 wxFileDialog
fileDialog( parent
, title
, defaultDirString
, defaultFilenameString
, filter2
, flags
, wxPoint(x
, y
) );
1549 if ( fileDialog
.ShowModal() == wxID_OK
)
1551 return fileDialog
.GetPath();
1555 return wxEmptyString
;
1559 static wxString
GetWildcardString(const wxChar
*ext
)
1564 if ( *ext
== wxT('.') )
1567 wild
<< _T("*.") << ext
;
1569 else // no extension specified
1571 wild
= wxFileSelectorDefaultWildcardStr
;
1577 wxString
wxLoadFileSelector(const wxChar
*what
,
1579 const wxChar
*nameDef
,
1583 if ( what
&& *what
)
1584 prompt
= wxString::Format(_("Load %s file"), what
);
1586 prompt
= _("Load file");
1588 return wxFileSelector(prompt
, NULL
, nameDef
, ext
,
1589 GetWildcardString(ext
), 0, parent
);
1592 wxString
wxSaveFileSelector(const wxChar
*what
,
1594 const wxChar
*nameDef
,
1598 if ( what
&& *what
)
1599 prompt
= wxString::Format(_("Save %s file"), what
);
1601 prompt
= _("Save file");
1603 return wxFileSelector(prompt
, NULL
, nameDef
, ext
,
1604 GetWildcardString(ext
), 0, parent
);
1607 // A module to allow icons table cleanup
1609 class wxFileDialogGenericModule
: public wxModule
1611 DECLARE_DYNAMIC_CLASS(wxFileDialogGenericModule
)
1613 wxFileDialogGenericModule() {}
1614 bool OnInit() { return TRUE
; }
1615 void OnExit() { if (g_IconsTable
) {delete g_IconsTable
; g_IconsTable
= NULL
;} }
1618 IMPLEMENT_DYNAMIC_CLASS(wxFileDialogGenericModule
, wxModule
)
1620 #endif // wxUSE_FILEDLG