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"
24 #error wxFileDialog currently only supports unix
27 #include "wx/filedlg.h"
31 #include "wx/msgdlg.h"
33 #include "wx/bmpbuttn.h"
35 #include "sys/types.h"
42 #include "wx/generic/home.xpm"
43 #include "wx/generic/listview.xpm"
44 #include "wx/generic/repview.xpm"
47 static char * folder_xpm
[] = {
48 /* width height ncolors chars_per_pixel */
75 //-----------------------------------------------------------------------------
77 //-----------------------------------------------------------------------------
79 IMPLEMENT_DYNAMIC_CLASS(wxFileData
,wxObject
);
81 wxFileData::wxFileData( const wxString
&name
, const wxString
&fname
)
87 stat( m_fileName
.GetData(), &buff
);
89 lstat( m_fileName
.GetData(), &lbuff
);
91 struct tm
*t
= localtime( &lbuff
.st_mtime
);
92 // struct passwd *user = getpwuid( buff.st_uid );
93 // struct group *grp = getgrgid( buff.st_gid );
95 m_isDir
= S_ISDIR( buff
.st_mode
);
96 m_isLink
= S_ISLNK( lbuff
.st_mode
);
97 m_isExe
= ((buff
.st_mode
& S_IXUSR
) == S_IXUSR
);
99 m_size
= buff
.st_size
;
102 m_minute
= t
->tm_min
;
103 m_month
= t
->tm_mon
+1;
107 m_permissions
.sprintf( "%c%c%c",
108 ((( buff
.st_mode
& S_IRUSR
) == S_IRUSR
) ? 'r' : '-'),
109 ((( buff
.st_mode
& S_IWUSR
) == S_IWUSR
) ? 'w' : '-'),
110 ((( buff
.st_mode
& S_IXUSR
) == S_IXUSR
) ? 'x' : '-') );
113 wxString
wxFileData::GetName() const
118 wxString
wxFileData::GetFullName() const
123 wxString
wxFileData::GetHint() const
125 wxString s
= m_fileName
;
127 if (m_isDir
) s
+= _("<DIR> ");
128 else if (m_isLink
) s
+= _("<LINK> ");
131 s
+= LongToString( m_size
);
134 s
+= IntToString( m_day
);
136 s
+= IntToString( m_month
);
138 s
+= IntToString( m_year
);
140 s
+= IntToString( m_hour
);
142 s
+= IntToString( m_minute
);
148 wxString
wxFileData::GetEntry( const int num
)
157 if (m_isDir
) s
= _("<DIR>");
158 else if (m_isLink
) s
= _("<LINK>");
159 else s
= LongToString( m_size
);
162 if (m_day
< 10) s
= _T("0"); else s
= _T("");
163 s
+= IntToString( m_day
);
165 if (m_month
< 10) s
+= _T("0");
166 s
+= IntToString( m_month
);
168 if (m_year
< 10) s
+= _T("0"); // this should happen real soon...
169 s
+= IntToString( m_year
);
172 if (m_hour
< 10) s
= _T("0"); else s
= _T("");
173 s
+= IntToString( m_hour
);
175 if (m_minute
< 10) s
+= _T("0");
176 s
+= IntToString( m_minute
);
188 bool wxFileData::IsDir()
193 bool wxFileData::IsExe()
198 bool wxFileData::IsLink()
203 long wxFileData::GetSize()
208 void wxFileData::SetNewName( const wxString
&name
, const wxString
&fname
)
214 void wxFileData::MakeItem( wxListItem
&item
)
216 item
.m_text
= m_name
;
217 item
.m_colour
= wxBLACK
;
218 if (IsExe()) item
.m_colour
= wxRED
;
219 if (IsDir()) item
.m_colour
= wxBLUE
;
220 if (IsDir()) item
.m_image
= 0; else item
.m_image
= -1;
223 wxColour
*dg
= wxTheColourDatabase
->FindColour( "MEDIUM GREY" );
226 item
.m_data
= (long)this;
229 //-----------------------------------------------------------------------------
231 //-----------------------------------------------------------------------------
233 IMPLEMENT_DYNAMIC_CLASS(wxFileCtrl
,wxListCtrl
);
235 BEGIN_EVENT_TABLE(wxFileCtrl
,wxListCtrl
)
236 EVT_LIST_DELETE_ITEM(-1, wxFileCtrl::OnListDeleteItem
)
237 EVT_LIST_END_LABEL_EDIT(-1, wxFileCtrl::OnListEndLabelEdit
)
240 wxFileCtrl::wxFileCtrl()
243 m_showHidden
= FALSE
;
246 wxFileCtrl::wxFileCtrl( wxWindow
*win
, wxWindowID id
,
247 const wxString
&dirName
, const wxString
&wild
,
248 const wxPoint
&pos
, const wxSize
&size
,
249 long style
, const wxValidator
&validator
, const wxString
&name
) :
250 wxListCtrl( win
, id
, pos
, size
, style
, validator
, name
)
252 wxImageList
*imageList
= new wxImageList( 16, 16 );
253 imageList
->Add( wxBitmap( folder_xpm
) );
254 SetImageList( imageList
, wxIMAGE_LIST_SMALL
);
258 m_showHidden
= FALSE
;
262 void wxFileCtrl::ChangeToListMode()
264 SetSingleStyle( wxLC_LIST
);
268 void wxFileCtrl::ChangeToReportMode()
270 SetSingleStyle( wxLC_REPORT
);
274 void wxFileCtrl::ChangeToIconMode()
276 SetSingleStyle( wxLC_ICON
);
280 void wxFileCtrl::ShowHidden( bool show
)
286 int ListCompare( const long data1
, const long data2
, const long WXUNUSED(data
) )
288 wxFileData
*fd1
= (wxFileData
*)data1
;
289 wxFileData
*fd2
= (wxFileData
*)data2
;
290 if (fd1
->GetName() == _T("..")) return -1;
291 if (fd2
->GetName() == _T("..")) return 1;
292 if (fd1
->IsDir() && !fd2
->IsDir()) return -1;
293 if (fd2
->IsDir() && !fd1
->IsDir()) return 1;
294 return strcmp( fd1
->GetName(), fd2
->GetName() );
297 long wxFileCtrl::Add( wxFileData
*fd
, wxListItem
&item
)
300 item
.m_mask
= wxLIST_MASK_TEXT
+ wxLIST_MASK_DATA
+ wxLIST_MASK_IMAGE
;
301 fd
->MakeItem( item
);
302 long my_style
= GetWindowStyleFlag();
303 if (my_style
& wxLC_REPORT
)
305 ret
= InsertItem( item
);
306 for (int i
= 1; i
< 5; i
++) SetItem( item
.m_itemId
, i
, fd
->GetEntry( i
) );
308 else if (my_style
& wxLC_LIST
)
310 ret
= InsertItem( item
);
315 void wxFileCtrl::Update()
318 long my_style
= GetWindowStyleFlag();
319 if (my_style
& wxLC_REPORT
)
321 InsertColumn( 0, _("Name"), wxLIST_FORMAT_LEFT
, 110 );
322 InsertColumn( 1, _("Size"), wxLIST_FORMAT_LEFT
, 60 );
323 InsertColumn( 2, _("Date"), wxLIST_FORMAT_LEFT
, 55 );
324 InsertColumn( 3, _("Time"), wxLIST_FORMAT_LEFT
, 50 );
325 InsertColumn( 4, _("Permissions"), wxLIST_FORMAT_LEFT
, 120 );
327 wxFileData
*fd
= (wxFileData
*) NULL
;
332 if (m_dirName
!= _T("/"))
334 wxString
p( wxPathOnly(m_dirName
) );
335 if (p
.IsEmpty()) p
= _T("/");
336 fd
= new wxFileData( _T(".."), p
);
341 wxString res
= m_dirName
+ _T("/") + m_wild
;
342 wxString
f( wxFindFirstFile( res
.GetData(), 0 ) );
345 res
= wxFileNameFromPath( f
);
346 fd
= new wxFileData( res
, f
);
347 wxString s
= fd
->GetName();
348 if (m_showHidden
|| (s
[0] != _T('.')))
353 f
= wxFindNextFile();
355 SortItems( ListCompare
, 0 );
358 void wxFileCtrl::SetWild( const wxString
&wild
)
364 void wxFileCtrl::MakeDir()
366 wxString
new_name( _T("NewName") );
367 wxString
path( m_dirName
);
370 if (wxFileExists(path
))
372 // try NewName0, NewName1 etc.
375 new_name
= _("NewName");
377 num
.Printf( _T("%d"), i
);
384 } while (wxFileExists(path
));
390 wxMessageDialog
dialog(this, _("Operation not permitted."), _("Error"), wxOK
| wxICON_ERROR
);
395 wxFileData
*fd
= new wxFileData( new_name
, path
);
399 int id
= Add( fd
, item
);
403 SortItems( ListCompare
, 0 );
404 id
= FindItem( 0, (long)fd
);
410 void wxFileCtrl::GoToParentDir()
412 if (m_dirName
!= _T("/"))
414 wxString
fname( wxFileNameFromPath(m_dirName
) );
415 m_dirName
= wxPathOnly( m_dirName
);
416 if (m_dirName
.IsEmpty()) m_dirName
= _T("/");
418 int id
= FindItem( 0, fname
);
421 SetItemState( id
, wxLIST_STATE_SELECTED
, wxLIST_STATE_SELECTED
);
427 void wxFileCtrl::GoToHomeDir()
429 wxString s
= wxGetUserHome( wxString() );
434 void wxFileCtrl::GoToDir( const wxString
&dir
)
440 void wxFileCtrl::GetDir( wxString
&dir
)
445 void wxFileCtrl::OnListDeleteItem( wxListEvent
&event
)
447 wxFileData
*fd
= (wxFileData
*)event
.m_item
.m_data
;
451 void wxFileCtrl::OnListEndLabelEdit( wxListEvent
&event
)
453 wxFileData
*fd
= (wxFileData
*)event
.m_item
.m_data
;
456 if ((event
.GetLabel().IsEmpty()) ||
457 (event
.GetLabel() == _(".")) ||
458 (event
.GetLabel() == _("..")) ||
459 (event
.GetLabel().First( _T("/") ) != wxNOT_FOUND
))
461 wxMessageDialog
dialog(this, _("Illegal directory name."), _("Error"), wxOK
| wxICON_ERROR
);
467 wxString
new_name( wxPathOnly( fd
->GetFullName() ) );
469 new_name
+= event
.GetLabel();
473 if (wxFileExists(new_name
))
475 wxMessageDialog
dialog(this, _("File name exists already."), _("Error"), wxOK
| wxICON_ERROR
);
480 if (wxRenameFile(fd
->GetFullName(),new_name
))
482 fd
->SetNewName( new_name
, event
.GetLabel() );
483 SetItemState( event
.GetItem(), wxLIST_STATE_SELECTED
, wxLIST_STATE_SELECTED
);
484 EnsureVisible( event
.GetItem() );
488 wxMessageDialog
dialog(this, _("Operation not permitted."), _("Error"), wxOK
| wxICON_ERROR
);
494 //-----------------------------------------------------------------------------
496 //-----------------------------------------------------------------------------
498 #define ID_LIST_CTRL 5010
499 #define ID_LIST_MODE 5000
500 #define ID_REPORT_MODE 5001
501 #define ID_UP_DIR 5005
502 #define ID_PARENT_DIR 5006
503 #define ID_NEW_DIR 5007
505 IMPLEMENT_DYNAMIC_CLASS(wxFileDialog
,wxDialog
)
507 BEGIN_EVENT_TABLE(wxFileDialog
,wxDialog
)
508 EVT_BUTTON(ID_LIST_MODE
, wxFileDialog::OnList
)
509 EVT_BUTTON(ID_REPORT_MODE
, wxFileDialog::OnReport
)
510 EVT_BUTTON(ID_UP_DIR
, wxFileDialog::OnUp
)
511 EVT_BUTTON(ID_PARENT_DIR
, wxFileDialog::OnHome
)
512 EVT_BUTTON(ID_NEW_DIR
, wxFileDialog::OnNew
)
513 EVT_BUTTON(wxID_OK
, wxFileDialog::OnListOk
)
514 EVT_LIST_ITEM_SELECTED(ID_LIST_CTRL
, wxFileDialog::OnSelected
)
515 EVT_LIST_ITEM_ACTIVATED(ID_LIST_CTRL
, wxFileDialog::OnActivated
)
518 wxFileDialog::wxFileDialog(wxWindow
*parent
,
519 const wxString
& message
,
520 const wxString
& defaultDir
,
521 const wxString
& defaultFile
,
522 const wxString
& wildCard
,
524 const wxPoint
& pos
) :
525 wxDialog( parent
, -1, message
)
530 m_dialogStyle
= style
;
532 if (m_dir
.IsEmpty()) m_dir
= wxGetUserHome();
535 m_path
+= defaultFile
;
536 m_fileName
= defaultFile
;
537 m_wildCard
= wildCard
;
540 wxBoxSizer
*mainsizer
= new wxBoxSizer( wxVERTICAL
);
542 wxBoxSizer
*buttonsizer
= new wxBoxSizer( wxHORIZONTAL
);
544 buttonsizer
->Add( new wxBitmapButton( this, ID_LIST_MODE
, wxBitmap( listview_xpm
) ), 0, wxALL
, 5 );
545 buttonsizer
->Add( new wxBitmapButton( this, ID_REPORT_MODE
, wxBitmap( repview_xpm
) ), 0, wxALL
, 5 );
546 buttonsizer
->Add( 30, 5, 1 );
547 buttonsizer
->Add( new wxButton( this, ID_UP_DIR
, "Up" ), 0, wxALL
, 5 );
548 buttonsizer
->Add( new wxBitmapButton( this, ID_PARENT_DIR
, wxBitmap(home_xpm
) ), 0, wxALL
, 5 );
549 buttonsizer
->Add( new wxButton( this, ID_NEW_DIR
, "New..." ), 0, wxALL
, 5 );
550 mainsizer
->Add( buttonsizer
, 0, wxALL
| wxEXPAND
, 5 );
552 m_list
= new wxFileCtrl( this, ID_LIST_CTRL
, m_dir
, "*", wxDefaultPosition
, wxSize(450,180),
553 wxLC_LIST
| wxSUNKEN_BORDER
| wxLC_SINGLE_SEL
);
554 mainsizer
->Add( m_list
, 1, wxEXPAND
| wxLEFT
|wxRIGHT
, 10 );
556 wxBoxSizer
*textsizer
= new wxBoxSizer( wxHORIZONTAL
);
557 m_text
= new wxTextCtrl( this, -1, m_fileName
);
558 textsizer
->Add( m_text
, 1, wxCENTER
| wxLEFT
|wxRIGHT
|wxTOP
, 10 );
559 textsizer
->Add( new wxButton( this, wxID_OK
, _("OK") ), 0, wxCENTER
| wxLEFT
|wxRIGHT
|wxTOP
, 10 );
560 mainsizer
->Add( textsizer
, 0, wxEXPAND
);
562 wxBoxSizer
*choicesizer
= new wxBoxSizer( wxHORIZONTAL
);
563 m_choice
= new wxChoice( this, -1 );
564 m_choice
->Append( "*.txt" );
565 choicesizer
->Add( m_choice
, 1, wxCENTER
|wxALL
, 10 );
566 choicesizer
->Add( new wxButton( this, wxID_CANCEL
, _("Cancel") ), 0, wxCENTER
| wxALL
, 10 );
567 mainsizer
->Add( choicesizer
, 0, wxEXPAND
);
569 SetAutoLayout( TRUE
);
570 SetSizer( mainsizer
);
572 mainsizer
->Fit( this );
573 mainsizer
->SetSizeHints( this );
582 void wxFileDialog::OnActivated( wxListEvent
&WXUNUSED(event
) )
584 wxCommandEvent
cevent(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_OK
);
585 cevent
.SetEventObject( this );
586 GetEventHandler()->ProcessEvent( cevent
);
589 void wxFileDialog::OnSelected( wxListEvent
&event
)
591 m_text
->SetValue( event
.m_item
.m_text
);
594 void wxFileDialog::OnListOk( wxCommandEvent
&event
)
596 wxString
filename( m_text
->GetValue() );
598 m_list
->GetDir( dir
);
599 if (filename
.IsEmpty()) return;
601 if (filename
== _T(".."))
603 m_list
->GoToParentDir();
608 if (dir
!= _T("/")) dir
+= _T("/");
612 if (wxDirExists(filename
))
614 m_list
->GoToDir( filename
);
615 m_text
->SetValue( _T("") );
619 if ( (m_dialogStyle
& wxSAVE
) && (m_dialogStyle
& wxOVERWRITE_PROMPT
) )
621 if (wxFileExists( filename
))
624 msg
.Printf( _("File '%s' already exists, do you really want to "
625 "overwrite it?"), filename
.c_str() );
627 if (wxMessageBox(msg
, _("Confirm"), wxYES_NO
) != wxYES
)
631 else if ( (m_dialogStyle
& wxOPEN
) && (m_dialogStyle
& wxFILE_MUST_EXIST
) )
633 if ( !wxFileExists( filename
) )
635 wxMessageBox(_("Please choose an existing file."), _("Error"), wxOK
);
645 void wxFileDialog::OnList( wxCommandEvent
&WXUNUSED(event
) )
647 m_list
->ChangeToListMode();
651 void wxFileDialog::OnReport( wxCommandEvent
&WXUNUSED(event
) )
653 m_list
->ChangeToReportMode();
657 void wxFileDialog::OnUp( wxCommandEvent
&WXUNUSED(event
) )
659 m_list
->GoToParentDir();
663 void wxFileDialog::OnHome( wxCommandEvent
&WXUNUSED(event
) )
665 m_list
->GoToHomeDir();
669 void wxFileDialog::OnNew( wxCommandEvent
&WXUNUSED(event
) )
674 void wxFileDialog::SetPath( const wxString
& path
)
676 // not only set the full path but also update filename and dir
681 wxSplitPath(path
, &m_dir
, &m_fileName
, &ext
);
684 m_fileName
+= _T(".");
690 // ----------------------------------------------------------------------------
692 // ----------------------------------------------------------------------------
695 wxFileSelectorEx(const wxChar
*message
,
696 const wxChar
*default_path
,
697 const wxChar
*default_filename
,
698 int *indexDefaultExtension
,
699 const wxChar
*wildcard
,
704 // TODO: implement this somehow
705 return wxFileSelector(message
, default_path
, default_filename
, _T(""),
706 wildcard
, flags
, parent
, x
, y
);
709 wxString
wxFileSelector( const wxChar
*title
,
710 const wxChar
*defaultDir
, const wxChar
*defaultFileName
,
711 const wxChar
*defaultExtension
, const wxChar
*filter
, int flags
,
712 wxWindow
*parent
, int x
, int y
)
715 if ( defaultExtension
&& !filter
)
716 filter2
= wxString(_T("*.")) + wxString(defaultExtension
) ;
720 wxString defaultDirString
;
722 defaultDirString
= defaultDir
;
724 wxString defaultFilenameString
;
726 defaultFilenameString
= defaultFileName
;
728 wxFileDialog
fileDialog( parent
, title
, defaultDirString
, defaultFilenameString
, filter2
, flags
, wxPoint(x
, y
) );
730 if ( fileDialog
.ShowModal() == wxID_OK
)
732 return fileDialog
.GetPath();
736 return wxEmptyString
;
740 wxString
wxLoadFileSelector( const wxChar
*what
, const wxChar
*extension
, const wxChar
*default_name
, wxWindow
*parent
)
742 wxChar
*ext
= (wxChar
*)extension
;
745 wxString str
= _("Load %s file");
746 wxSprintf(prompt
, str
, what
);
748 if (*ext
== _T('.')) ext
++;
750 wxSprintf(wild
, _T("*.%s"), ext
);
752 return wxFileSelector (prompt
, (const wxChar
*) NULL
, default_name
, ext
, wild
, 0, parent
);
755 wxString
wxSaveFileSelector(const wxChar
*what
, const wxChar
*extension
, const wxChar
*default_name
,
758 wxChar
*ext
= (wxChar
*)extension
;
761 wxString str
= _("Save %s file");
762 wxSprintf(prompt
, str
, what
);
764 if (*ext
== _T('.')) ext
++;
766 wxSprintf(wild
, _T("*.%s"), ext
);
768 return wxFileSelector (prompt
, (const wxChar
*) NULL
, default_name
, ext
, wild
, 0, parent
);