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"
32 #include "wx/msgdlg.h"
35 #include "sys/types.h"
42 #include "wx/generic/folder.xpm"
43 #include "wx/generic/txt.xpm"
44 #include "wx/generic/list.xpm"
45 #include "wx/generic/find.xpm"
47 //-----------------------------------------------------------------------------
49 //-----------------------------------------------------------------------------
51 IMPLEMENT_DYNAMIC_CLASS(wxFileData
,wxObject
);
53 wxFileData::wxFileData( const wxString
&name
, const wxString
&fname
)
59 stat( m_fileName
.GetData(), &buff
);
61 lstat( m_fileName
.GetData(), &lbuff
);
63 struct tm
*t
= localtime( &lbuff
.st_mtime
);
64 // struct passwd *user = getpwuid( buff.st_uid );
65 // struct group *grp = getgrgid( buff.st_gid );
67 m_isDir
= S_ISDIR( buff
.st_mode
);
68 m_isLink
= S_ISLNK( lbuff
.st_mode
);
69 m_isExe
= ((buff
.st_mode
& S_IXUSR
) == S_IXUSR
);
71 m_size
= buff
.st_size
;
75 m_month
= t
->tm_mon
+1;
79 m_permissions
.sprintf( "%c%c%c",
80 ((( buff
.st_mode
& S_IRUSR
) == S_IRUSR
) ? 'r' : '-'),
81 ((( buff
.st_mode
& S_IWUSR
) == S_IWUSR
) ? 'w' : '-'),
82 ((( buff
.st_mode
& S_IXUSR
) == S_IXUSR
) ? 'x' : '-') );
85 wxString
wxFileData::GetName() const
90 wxString
wxFileData::GetFullName() const
95 wxString
wxFileData::GetHint() const
97 wxString s
= m_fileName
;
99 if (m_isDir
) s
+= _("<DIR> ");
100 else if (m_isLink
) s
+= _("<LINK> ");
103 s
+= LongToString( m_size
);
106 s
+= IntToString( m_day
);
108 s
+= IntToString( m_month
);
110 s
+= IntToString( m_year
);
112 s
+= IntToString( m_hour
);
114 s
+= IntToString( m_minute
);
120 wxString
wxFileData::GetEntry( const int num
)
129 if (m_isDir
) s
= _("<DIR>");
130 else if (m_isLink
) s
= _("<LINK>");
131 else s
= LongToString( m_size
);
134 if (m_day
< 10) s
= _T("0"); else s
= _T("");
135 s
+= IntToString( m_day
);
137 if (m_month
< 10) s
+= _T("0");
138 s
+= IntToString( m_month
);
140 if (m_year
< 10) s
+= _T("0"); // this should happen real soon...
141 s
+= IntToString( m_year
);
144 if (m_hour
< 10) s
= _T("0"); else s
= _T("");
145 s
+= IntToString( m_hour
);
147 if (m_minute
< 10) s
+= _T("0");
148 s
+= IntToString( m_minute
);
160 bool wxFileData::IsDir()
165 bool wxFileData::IsExe()
170 bool wxFileData::IsLink()
175 long wxFileData::GetSize()
180 bool wxFileData::NewNameIsLegal( const wxString
&s
)
182 wxString fileName
= wxPathOnly( m_fileName
);
185 return (!wxFileExists( fileName
));
188 bool wxFileData::Rename( const wxString
&s
)
190 wxString fileName
= wxPathOnly( m_fileName
);
193 bool ret
= wxRenameFile( m_fileName
, fileName
);
196 m_fileName
= fileName
;
202 void wxFileData::MakeItem( wxListItem
&item
)
204 item
.m_text
= m_name
;
205 item
.m_colour
= wxBLACK
;
206 if (IsExe()) item
.m_colour
= wxRED
;
207 if (IsDir()) item
.m_colour
= wxBLUE
;
210 wxColour
*dg
= wxTheColourDatabase
->FindColour( "MEDIUM GREY" );
213 item
.m_data
= (long)this;
216 //-----------------------------------------------------------------------------
218 //-----------------------------------------------------------------------------
220 IMPLEMENT_DYNAMIC_CLASS(wxFileCtrl
,wxListCtrl
);
222 BEGIN_EVENT_TABLE(wxFileCtrl
,wxListCtrl
)
225 wxFileCtrl::wxFileCtrl()
228 m_showHidden
= FALSE
;
231 wxFileCtrl::wxFileCtrl( wxWindow
*win
, wxWindowID id
, const wxString
&dirName
,
232 const wxPoint
&pos
, const wxSize
&size
,
233 long style
, const wxValidator
&validator
, const wxString
&name
) :
234 wxListCtrl( win
, id
, pos
, size
, style
, validator
, name
)
236 SetItemSpacing( 40 );
237 wxImageList
*imageList
= new wxImageList( 30, 30 );
238 imageList
->Add( wxBitmap( folder_xpm
) );
239 imageList
->Add( wxBitmap( txt_xpm
) );
240 imageList
->Add( wxBitmap( list_xpm
) );
241 imageList
->Add( wxBitmap( find_xpm
) );
243 SetImageList( imageList
, wxIMAGE_LIST_NORMAL
);
246 m_showHidden
= FALSE
;
249 // SetDropTarget( new wxFileDropTarget() );
252 void wxFileCtrl::ChangeToListMode()
254 SetSingleStyle( wxLC_LIST
);
258 void wxFileCtrl::ChangeToReportMode()
260 SetSingleStyle( wxLC_REPORT
);
264 void wxFileCtrl::ChangeToIconMode()
266 SetSingleStyle( wxLC_ICON
);
270 void wxFileCtrl::ShowHidden( bool show
)
276 int ListCompare( const long data1
, const long data2
, const long WXUNUSED(data
) )
278 wxFileData
*fd1
= (wxFileData
*)data1
;
279 wxFileData
*fd2
= (wxFileData
*)data2
;
280 if (fd1
->IsDir() && !fd2
->IsDir()) return -1;
281 if (fd2
->IsDir() && !fd1
->IsDir()) return 1;
282 return strcmp( fd1
->GetName(), fd2
->GetName() );
285 void wxFileCtrl::Update()
288 long my_style
= GetWindowStyleFlag();
289 if (my_style
& wxLC_REPORT
)
291 InsertColumn( 0, _("Name"), wxLIST_FORMAT_LEFT
, 110 );
292 InsertColumn( 1, _("Size"), wxLIST_FORMAT_LEFT
, 60 );
293 InsertColumn( 2, _("Date"), wxLIST_FORMAT_LEFT
, 55 );
294 InsertColumn( 3, _("Time"), wxLIST_FORMAT_LEFT
, 50 );
295 InsertColumn( 4, _("Permissions"), wxLIST_FORMAT_LEFT
, 120 );
297 wxFileData
*fd
= (wxFileData
*) NULL
;
299 item
.m_mask
= wxLIST_MASK_TEXT
+ wxLIST_MASK_DATA
;
300 if (my_style
& wxLC_ICON
) item
.m_mask
+= wxLIST_MASK_IMAGE
;
304 wxString res
= m_dirName
+ _T("/*");
305 wxString
f( wxFindFirstFile( res
.GetData(), 0 ) );
308 res
= wxFileNameFromPath( f
);
309 fd
= new wxFileData( res
, f
);
311 if (m_showHidden
|| (s
[0] != '.'))
313 fd
->MakeItem( item
);
314 if (my_style
& wxLC_REPORT
)
317 for (int i
= 1; i
< 5; i
++) SetItem( item
.m_itemId
, i
, fd
->GetEntry( i
) );
319 else if (my_style
& wxLC_LIST
)
323 else if (my_style
& wxLC_ICON
)
325 if (fd
->IsDir()) item
.m_image
= 0; else item
.m_image
= 1;
330 f
= wxFindNextFile();
332 SortItems( ListCompare
, 0 );
335 int wxFileCtrl::FillList( wxStringList
&list
)
342 index
= GetNextItem( index
, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
343 if (index
== -1) break;
345 item
.m_itemId
= index
;
347 wxFileData
*fd
= (wxFileData
*)item
.m_data
;
348 list
.Add( fd
->GetFullName() );
354 index
= GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_FOCUSED
);
355 if (index
== -1) return 0;
357 item
.m_itemId
= index
;
359 wxFileData
*fd
= (wxFileData
*)item
.m_data
;
360 list
.Add( fd
->GetFullName() );
366 void wxFileCtrl::DeleteFiles()
370 int count = FillList( list );
373 wxString s = "Delete ";
374 s += wxIntToString( count );
375 s += " selected file";
376 if (count > 1) s += "s";
378 if (count > 1) s += "ies?"; else s+= "y?";
379 if (wxYES == wxMessageBox( s, "Delete", wxYES_NO ))
380 wxDeleteStatusDia( NULL, &list );
385 void wxFileCtrl::CopyFiles( char *WXUNUSED(dest
) )
389 int count = FillList( list );
391 int ret = 0; // 0 = nix, 1 = copy, 2 = move
392 wxCopyMoveDia( (wxFrame*)GetParent(), count, &ret, &s );
394 wxCopyStatusDia( NULL, s, &list );
398 void wxFileCtrl::MoveFiles( char *WXUNUSED(dest
) )
402 void wxFileCtrl::RenameFile()
406 void wxFileCtrl::MakeDir()
409 wxString s = wxGetTextFromUser( "Enter new directory name:", "Make directory" );
410 if (s.IsNull()) return;
412 if ((s == ".") || (s == ".."))
414 wxMessageBox( "This was obviously an invalid directory name.", "Go away." );
421 if (wxFileExists( dir ))
423 wxMessageBox( "Filename exists already. Cannot create directoy.", "Make directory" );
431 void wxFileCtrl::GoToParentDir()
433 wxString s
= m_dirName
;
434 int pos
= s
.Last( _T('/') );
435 if ((pos
>= 0) && (s
!= _T("/")))
437 s
.Remove( pos
, s
.Length()-pos
);
438 if (s
.Length() == 0) s
= _T("/");
444 void wxFileCtrl::GoToHomeDir()
446 wxString s
= wxGetUserHome( wxString() );
451 void wxFileCtrl::GoToDir( const wxString
&dir
)
457 void wxFileCtrl::GetDir( wxString
&dir
)
463 void wxFileCtrl::OnDropFiles( int WXUNUSED(n), char **WXUNUSED(data), int WXUNUSED(x), int WXUNUSED(y) )
467 int flag = wxLIST_HITTEST_ONITEM;
468 long hit = HitTest( pt, flag );
474 wxFileData *fd = (wxFileData*)li.m_data;
475 if (fd->IsDir()) fd->GetFullName( destDir );
477 if (destDir.IsNull()) destDir = m_dirName;
478 int ret = 0; // 0 = nix, 1 = copy, 2 = move
479 wxCopyMoveDia( (wxFrame*)GetParent(), n, &ret, &destDir );
483 for (int i = 0; i < n; i++) slist.Add( data[i] );
484 wxCopyStatusDia( NULL, destDir.GetData(), &slist );
490 void wxFileCtrl::OnListDeleteItem( wxListEvent
&event
)
492 wxFileData
*fd
= (wxFileData
*)event
.m_item
.m_data
;
496 void wxFileCtrl::OnListKeyDown( wxListEvent
&event
)
498 wxFileData
*fd
= (wxFileData
*)event
.m_item
.m_data
;
501 m_dirName
= fd
->GetFullName();
508 wxExecute( fd
->GetFullName() );
513 void wxFileCtrl::OnListEndLabelEdit( wxListEvent
&event
)
515 wxFileData
*fd
= (wxFileData
*)event
.m_item
.m_data
;
516 wxString newName
= event
.m_item
.m_text
;
517 if (fd
->NewNameIsLegal( newName
))
519 if (fd
->Rename( newName
))
525 wxString s
= _("Could not rename file to ");
528 wxMessageBox( s
, _("File dialog"), wxOK
);
533 wxString s
= "File name ";
535 s
+= " exists already or is invalid.\n";
536 s
+= "Could not rename file.";
537 wxMessageBox( s
, _("File dialog"), wxOK
);
542 //-----------------------------------------------------------------------------
544 //-----------------------------------------------------------------------------
548 #define ID_LIST_CTRL 5010
549 #define ID_LIST_MODE 5000
550 #define ID_REPORT_MODE 5001
551 #define ID_ICON_MODE 5002
552 #define ID_UP_DIR 5005
553 #define ID_PARENT_DIR 5006
555 IMPLEMENT_DYNAMIC_CLASS(wxFileDialog
,wxDialog
)
557 BEGIN_EVENT_TABLE(wxFileDialog
,wxDialog
)
558 EVT_BUTTON(ID_LIST_MODE
, wxFileDialog::OnList
)
559 EVT_BUTTON(ID_REPORT_MODE
, wxFileDialog::OnReport
)
560 EVT_BUTTON(ID_ICON_MODE
, wxFileDialog::OnIcon
)
561 EVT_BUTTON(ID_UP_DIR
, wxFileDialog::OnUp
)
562 EVT_BUTTON(ID_PARENT_DIR
, wxFileDialog::OnHome
)
563 EVT_BUTTON(wxID_OK
, wxFileDialog::OnListOk
)
564 EVT_LIST_ITEM_SELECTED(ID_LIST_CTRL
, wxFileDialog::OnSelected
)
565 EVT_LIST_ITEM_ACTIVATED(ID_LIST_CTRL
, wxFileDialog::OnActivated
)
568 wxFileDialog::wxFileDialog(wxWindow
*parent
,
569 const wxString
& message
,
570 const wxString
& defaultDir
,
571 const wxString
& defaultFile
,
572 const wxString
& wildCard
,
574 const wxPoint
& pos
) :
575 wxDialog( parent
, -1, message
)
580 m_dialogStyle
= style
;
582 if (m_dir
.IsEmpty()) m_dir
= wxGetUserHome();
585 m_path
+= defaultFile
;
586 m_fileName
= defaultFile
;
587 m_wildCard
= wildCard
;
590 wxBoxSizer
*mainsizer
= new wxBoxSizer( wxVERTICAL
);
592 wxBoxSizer
*buttonsizer
= new wxBoxSizer( wxHORIZONTAL
);
594 buttonsizer
->Add( new wxButton( this, ID_LIST_MODE
, "List" ), 0, wxALL
, 5 );
595 buttonsizer
->Add( new wxButton( this, ID_REPORT_MODE
, "Report" ), 0, wxALL
, 5 );
596 buttonsizer
->Add( new wxButton( this, ID_ICON_MODE
, "Icon" ), 0, wxALL
, 5 );
597 buttonsizer
->Add( 30, 5 );
598 buttonsizer
->Add( new wxButton( this, ID_UP_DIR
, "Up" ), 0, wxALL
, 5 );
599 buttonsizer
->Add( new wxButton( this, ID_PARENT_DIR
, "Home" ), 0, wxALL
, 5 );
600 buttonsizer
->Add( new wxButton( this, -1, "New..." ), 0, wxALL
, 5 );
601 mainsizer
->Add( buttonsizer
, 0, wxALL
| wxALIGN_RIGHT
, 5 );
603 m_list
= new wxFileCtrl( this, ID_LIST_CTRL
, "/", wxDefaultPosition
, wxSize(200,180),
604 wxLC_LIST
| wxSUNKEN_BORDER
| wxLC_SINGLE_SEL
);
605 mainsizer
->Add( m_list
, 1, wxEXPAND
| wxALL
, 10 );
607 wxBoxSizer
*textsizer
= new wxBoxSizer( wxHORIZONTAL
);
608 m_text
= new wxTextCtrl( this, -1, m_fileName
);
609 textsizer
->Add( m_text
, 1, wxCENTER
|wxALL
, 10 );
610 textsizer
->Add( new wxButton( this, wxID_OK
, _("OK") ), 0, wxCENTER
| wxLEFT
|wxRIGHT
|wxTOP
, 10 );
611 mainsizer
->Add( textsizer
, 0, wxEXPAND
);
613 wxBoxSizer
*choicesizer
= new wxBoxSizer( wxHORIZONTAL
);
614 m_choice
= new wxChoice( this, -1 );
615 m_choice
->Append( "*.txt" );
616 choicesizer
->Add( m_choice
, 1, wxCENTER
|wxALL
, 10 );
617 choicesizer
->Add( new wxButton( this, wxID_CANCEL
, _("Cancel") ), 0, wxCENTER
| wxALL
, 10 );
618 mainsizer
->Add( choicesizer
, 0, wxEXPAND
);
620 SetAutoLayout( TRUE
);
621 SetSizer( mainsizer
);
623 mainsizer
->Fit( this );
624 mainsizer
->SetSizeHints( this );
631 void wxFileDialog::OnActivated( wxListEvent
&WXUNUSED(event
) )
633 wxCommandEvent
cevent(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_OK
);
634 cevent
.SetEventObject( this );
635 GetEventHandler()->ProcessEvent( cevent
);
638 void wxFileDialog::OnSelected( wxListEvent
&event
)
640 m_text
->SetValue( event
.m_item
.m_text
);
643 void wxFileDialog::OnListOk( wxCommandEvent
&event
)
645 wxString
filename( m_text
->GetValue() );
647 m_list
->GetDir( dir
);
648 if (filename
.IsEmpty()) return;
654 if (wxDirExists(filename
))
656 m_list
->GoToDir( filename
);
657 m_text
->SetValue( _T("") );
661 if ( (m_dialogStyle
& wxSAVE
) && (m_dialogStyle
& wxOVERWRITE_PROMPT
) )
663 if (wxFileExists( filename
))
666 msg
.Printf( _("File '%s' already exists, do you really want to "
667 "overwrite it?"), filename
.c_str() );
669 if (wxMessageBox(msg
, _("Confirm"), wxYES_NO
) != wxYES
)
673 else if ( (m_dialogStyle
& wxOPEN
) && (m_dialogStyle
& wxFILE_MUST_EXIST
) )
675 if ( !wxFileExists( filename
) )
677 wxMessageBox(_("Please choose an existing file."), _("Error"), wxOK
);
687 void wxFileDialog::OnList( wxCommandEvent
&WXUNUSED(event
) )
689 m_list
->ChangeToListMode();
692 void wxFileDialog::OnReport( wxCommandEvent
&WXUNUSED(event
) )
694 m_list
->ChangeToReportMode();
697 void wxFileDialog::OnIcon( wxCommandEvent
&WXUNUSED(event
) )
699 m_list
->ChangeToIconMode();
702 void wxFileDialog::OnUp( wxCommandEvent
&WXUNUSED(event
) )
704 m_list
->GoToParentDir();
707 void wxFileDialog::OnHome( wxCommandEvent
&WXUNUSED(event
) )
709 m_list
->GoToHomeDir();
712 void wxFileDialog::SetPath( const wxString
& path
)
714 // not only set the full path but also update filename and dir
719 wxSplitPath(path
, &m_dir
, &m_fileName
, &ext
);
722 m_fileName
+= _T(".");
728 // ----------------------------------------------------------------------------
730 // ----------------------------------------------------------------------------
733 wxFileSelectorEx(const wxChar
*message
,
734 const wxChar
*default_path
,
735 const wxChar
*default_filename
,
736 int *indexDefaultExtension
,
737 const wxChar
*wildcard
,
742 // TODO: implement this somehow
743 return wxFileSelector(message
, default_path
, default_filename
, _T(""),
744 wildcard
, flags
, parent
, x
, y
);
747 wxString
wxFileSelector( const wxChar
*title
,
748 const wxChar
*defaultDir
, const wxChar
*defaultFileName
,
749 const wxChar
*defaultExtension
, const wxChar
*filter
, int flags
,
750 wxWindow
*parent
, int x
, int y
)
753 if ( defaultExtension
&& !filter
)
754 filter2
= wxString(_T("*.")) + wxString(defaultExtension
) ;
758 wxString defaultDirString
;
760 defaultDirString
= defaultDir
;
762 wxString defaultFilenameString
;
764 defaultFilenameString
= defaultFileName
;
766 wxFileDialog
fileDialog( parent
, title
, defaultDirString
, defaultFilenameString
, filter2
, flags
, wxPoint(x
, y
) );
768 if ( fileDialog
.ShowModal() == wxID_OK
)
770 return fileDialog
.GetPath();
774 return wxEmptyString
;
778 wxString
wxLoadFileSelector( const wxChar
*what
, const wxChar
*extension
, const wxChar
*default_name
, wxWindow
*parent
)
780 wxChar
*ext
= (wxChar
*)extension
;
783 wxString str
= _("Load %s file");
784 wxSprintf(prompt
, str
, what
);
786 if (*ext
== _T('.')) ext
++;
788 wxSprintf(wild
, _T("*.%s"), ext
);
790 return wxFileSelector (prompt
, (const wxChar
*) NULL
, default_name
, ext
, wild
, 0, parent
);
793 wxString
wxSaveFileSelector(const wxChar
*what
, const wxChar
*extension
, const wxChar
*default_name
,
796 wxChar
*ext
= (wxChar
*)extension
;
799 wxString str
= _("Save %s file");
800 wxSprintf(prompt
, str
, what
);
802 if (*ext
== _T('.')) ext
++;
804 wxSprintf(wild
, _T("*.%s"), ext
);
806 return wxFileSelector (prompt
, (const wxChar
*) NULL
, default_name
, ext
, wild
, 0, parent
);