1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/filedlg.cpp
3 // Purpose: native implementation of wxFileDialog
4 // Author: Robert Roebling, Zbigniew Zagorski
6 // Copyright: (c) 1998 Robert Roebling, 2004 Zbigniew Zagorski
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
11 #pragma implementation "filedlggtk.h"
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
19 #include "wx/filedlg.h"
22 #include "wx/filename.h"
23 #include "wx/msgdlg.h"
29 #include "wx/gtk/private.h"
31 //-----------------------------------------------------------------------------
33 //-----------------------------------------------------------------------------
35 extern void wxapp_install_idle_handler();
38 //-----------------------------------------------------------------------------
39 // "clicked" for OK-button
40 //-----------------------------------------------------------------------------
43 static void gtk_filedialog_ok_callback(GtkWidget
*widget
, wxFileDialog
*dialog
)
45 int style
= dialog
->GetStyle();
46 gchar
* text
= gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget
));
47 wxString filename
= wxConvFileName
->cMB2WX( text
);
48 if ( filename
.empty() )
50 // this is totally lame but better than silent error
51 wxLogWarning(_("This filename can't be used by wxWidgets because it contains invalid UTF-8 characters, please rename the file."));
55 if ((style
& wxSAVE
) && (style
& wxOVERWRITE_PROMPT
))
57 if (wxFileExists(filename
))
61 _("File '%s' already exists, do you really want to overwrite it?"),
64 wxMessageDialog
dlg(dialog
, msg
, _("Confirm"),
65 wxYES_NO
| wxICON_QUESTION
);
66 if (dlg
.ShowModal() != wxID_YES
)
70 else if ((style
& wxOPEN
) && ( style
& wxFILE_MUST_EXIST
))
72 if (!wxFileExists( filename
))
74 wxMessageDialog
dlg(dialog
,
75 _("Please choose an existing file."),
76 _("Error"), wxOK
| wxICON_ERROR
);
83 // change to the directory where the user went if asked
84 if (style
& wxCHANGE_DIR
)
87 wxSplitPath(filename
, &cwd
, NULL
, NULL
);
89 if (cwd
!= wxGetCwd())
91 wxSetWorkingDirectory(cwd
);
95 dialog
->SetPath(filename
);
96 dialog
->UpdateFromDialog();
98 wxCommandEvent
event(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_OK
);
99 event
.SetEventObject(dialog
);
100 dialog
->GetEventHandler()->ProcessEvent(event
);
104 //-----------------------------------------------------------------------------
105 // "clicked" for Cancel-button
106 //-----------------------------------------------------------------------------
109 static void gtk_filedialog_cancel_callback(GtkWidget
*WXUNUSED(w
),
110 wxFileDialog
*dialog
)
112 wxCommandEvent
event(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_CANCEL
);
113 event
.SetEventObject(dialog
);
114 dialog
->GetEventHandler()->ProcessEvent(event
);
119 static void gtk_filedialog_response_callback(GtkWidget
*w
,
121 wxFileDialog
*dialog
)
123 wxapp_install_idle_handler();
125 if (response
== GTK_RESPONSE_ACCEPT
)
126 gtk_filedialog_ok_callback(w
, dialog
);
127 else if (response
== GTK_RESPONSE_CANCEL
)
128 gtk_filedialog_cancel_callback(w
, dialog
);
131 gtk_filedialog_cancel_callback(w
, dialog
);
132 dialog
->m_destroyed_by_delete
= true;
137 #endif // __WXGTK24__
139 //-----------------------------------------------------------------------------
141 //-----------------------------------------------------------------------------
143 IMPLEMENT_DYNAMIC_CLASS(wxFileDialog
,wxGenericFileDialog
)
145 BEGIN_EVENT_TABLE(wxFileDialog
,wxGenericFileDialog
)
146 EVT_BUTTON(wxID_OK
, wxFileDialog::OnFakeOk
)
149 wxFileDialog::wxFileDialog(wxWindow
*parent
, const wxString
& message
,
150 const wxString
& defaultDir
,
151 const wxString
& defaultFileName
,
152 const wxString
& wildCard
,
153 long style
, const wxPoint
& pos
)
154 : wxGenericFileDialog(parent
, message
, defaultDir
, defaultFileName
,
155 wildCard
, style
, pos
, true )
158 if (!gtk_check_version(2,4,0))
160 m_needParent
= false;
161 m_destroyed_by_delete
= false;
163 if (!PreCreation(parent
, pos
, wxDefaultSize
) ||
164 !CreateBase(parent
, wxID_ANY
, pos
, wxDefaultSize
, style
,
165 wxDefaultValidator
, wxT("filedialog")))
167 wxFAIL_MSG( wxT("wxFileDialog creation failed") );
171 bool multiple
= (style
& wxMULTIPLE
) == wxMULTIPLE
;
172 GtkFileChooserAction gtk_action
;
173 GtkWindow
* gtk_parent
= NULL
;
175 gtk_parent
= GTK_WINDOW(parent
->m_widget
);
178 if ((style
& wxSAVE
) == wxSAVE
)
180 gtk_action
= GTK_FILE_CHOOSER_ACTION_SAVE
;
181 ok_btn_stock
= GTK_STOCK_SAVE
;
185 gtk_action
= GTK_FILE_CHOOSER_ACTION_OPEN
;
186 ok_btn_stock
= GTK_STOCK_OPEN
;
188 m_widget
= gtk_file_chooser_dialog_new(
189 wxGTK_CONV(m_message
),
192 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
193 ok_btn_stock
, GTK_RESPONSE_ACCEPT
,
196 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(m_widget
), multiple
);
198 gtk_signal_connect(GTK_OBJECT(m_widget
),
200 GTK_SIGNAL_FUNC(gtk_filedialog_response_callback
),
204 if (!m_path
.empty() && m_path
.Last() != wxT('/'))
206 m_path
+= m_fileName
;
209 SetWildcard(wildCard
);
214 wxGenericFileDialog::Create( parent
, message
, defaultDir
, defaultFileName
, wildCard
, style
, pos
);
217 wxFileDialog::~wxFileDialog()
220 if (!gtk_check_version(2,4,0))
222 if (m_destroyed_by_delete
)
228 void wxFileDialog::OnFakeOk( wxCommandEvent
&event
)
231 if (!gtk_check_version(2,4,0))
232 wxDialog::OnOK( event
);
235 wxGenericFileDialog::OnListOk( event
);
238 int wxFileDialog::ShowModal()
241 if (!gtk_check_version(2,4,0))
242 return wxDialog::ShowModal();
245 return wxGenericFileDialog::ShowModal();
248 bool wxFileDialog::Show( bool show
)
251 if (!gtk_check_version(2,4,0))
252 return wxDialog::Show( show
);
255 return wxGenericFileDialog::Show( show
);
258 void wxFileDialog::GetFilenames(wxArrayString
& files
) const
261 if (!gtk_check_version(2,4,0))
264 for (size_t n
= 0; n
< files
.GetCount(); n
++ )
267 wxSplitPath(files
[n
], NULL
, &name
, &ext
);
278 wxGenericFileDialog::GetFilenames( files
);
281 void wxFileDialog::GetPaths(wxArrayString
& paths
) const
284 if (!gtk_check_version(2,4,0))
287 if (GetWindowStyle() & wxMULTIPLE
)
290 gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(m_widget
));
291 GSList
*gpaths
= gpathsi
;
294 wxString file
= wxGTK_CONV_BACK((gchar
*) gpathsi
->data
);
296 g_free(gpathsi
->data
);
297 gpathsi
= gpathsi
->next
;
300 g_slist_free(gpaths
);
303 if ( paths
.IsEmpty() )
305 paths
.Add(m_fileName
);
310 wxGenericFileDialog::GetPaths( paths
);
313 void wxFileDialog::SetMessage(const wxString
& message
)
316 if (!gtk_check_version(2,4,0))
323 wxGenericFileDialog::SetMessage( message
);
326 void wxFileDialog::SetPath(const wxString
& path
)
329 if (!gtk_check_version(2,4,0))
331 if (path
.empty()) return;
334 m_path
= fn
.GetFullPath();
335 m_dir
= fn
.GetPath();
336 m_fileName
= fn
.GetFullName();
341 wxGenericFileDialog::SetPath( path
);
344 void wxFileDialog::SetDirectory(const wxString
& dir
)
347 if (!gtk_check_version(2,4,0))
349 if (wxPathExists(dir
))
352 m_path
= wxFileName(m_dir
, m_fileName
).GetFullPath();
358 wxGenericFileDialog::SetDirectory( dir
);
361 void wxFileDialog::SetFilename(const wxString
& name
)
364 if (!gtk_check_version(2,4,0))
367 m_path
= wxFileName(m_dir
, m_fileName
).GetFullPath();
372 wxGenericFileDialog::SetFilename( name
);
375 void wxFileDialog::SetWildcard(const wxString
& wildCard
)
378 if (!gtk_check_version(2,4,0))
380 m_wildCard
= wildCard
;
381 GtkFileChooser
* chooser
= GTK_FILE_CHOOSER(m_widget
);
383 // empty current filter list:
384 GSList
* ifilters
= gtk_file_chooser_list_filters(chooser
);
385 GSList
* filters
= ifilters
;
388 gtk_file_chooser_remove_filter(chooser
,GTK_FILE_FILTER(ifilters
->data
));
389 ifilters
= ifilters
->next
;
391 g_slist_free(filters
);
394 wxArrayString wildDescriptions
, wildFilters
;
395 if (!wxParseCommonDialogsFilter(m_wildCard
, wildDescriptions
, wildFilters
))
397 wxFAIL_MSG( wxT("Wrong file type description") );
401 // add parsed to GtkChooser
402 for (size_t n
= 0; n
< wildFilters
.GetCount(); n
++)
404 GtkFileFilter
* filter
= gtk_file_filter_new();
405 gtk_file_filter_set_name(filter
,wxGTK_CONV(wildDescriptions
[n
]));
406 wxString after
= wildFilters
[n
];
409 wxString ext
= after
.BeforeFirst(wxT(';'));
410 gtk_file_filter_add_pattern(filter
,wxGTK_CONV(ext
));
411 if (after
.Find(wxT(';')) == wxNOT_FOUND
)
413 after
= after
.AfterLast(wxT(';'));
415 while (!after
.empty());
417 gtk_file_chooser_add_filter(chooser
, filter
);
423 wxGenericFileDialog::SetWildcard( wildCard
);
426 void wxFileDialog::SetFilterIndex(int filterIndex
)
429 if (!gtk_check_version(2,4,0))
431 m_filterIndex
= filterIndex
;
433 GtkFileChooser
*chooser
= GTK_FILE_CHOOSER(m_widget
);
434 GSList
*fnode
= gtk_file_chooser_list_filters(chooser
);
435 GSList
*filters
= fnode
;
439 if (i
== filterIndex
)
441 gtk_file_chooser_set_filter(chooser
, GTK_FILE_FILTER(fnode
->data
));
448 g_slist_free(filters
);
452 wxGenericFileDialog::SetFilterIndex( filterIndex
);
455 void wxFileDialog::UpdateDialog()
458 // set currently selected directory to match the path:
459 if (!m_dir
.empty() && wxPathExists(m_dir
))
461 // NB: This is important -- if we set directory only and not the path,
462 // then dialog will still remember old path set using previous
463 // call to gtk_chooser_set_filename. If the previous directory
464 // was a subdirectory of the directory we want to select now,
465 // the dialog would still contain directory selector controls
466 // for the subdirectory (with the parent directory selected),
467 // instead of showing only the parent directory as expected.
468 // This way, we force GtkFileChooser to really change the
469 // directory. Finally, it doesn't have to be done if filename
470 // is not empty because of the code that sets the filename below.
471 if (m_fileName
.empty())
472 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(m_widget
),
475 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(m_widget
),
479 // if the user set only the directory (e.g. by calling SetDirectory)
480 // and not the default filename, then we don't want to set the filename:
481 if (!m_fileName
.empty())
483 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(m_widget
),
486 // pre-fill the filename when saving, too (there's no text entry
487 // control when opening a file, so it doesn't make sense to
488 // do this when opening files):
489 if (GetWindowStyle() & wxSAVE
)
491 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(m_widget
),
492 wxGTK_CONV(m_fileName
));
498 void wxFileDialog::UpdateFromDialog()
501 // update filterIndex
502 GSList
*fnode
= gtk_file_chooser_list_filters(GTK_FILE_CHOOSER(m_widget
));
503 GSList
*filters
= fnode
;
504 GtkFileFilter
*current
=
505 gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(m_widget
));
511 if (fnode
->data
== (gpointer
)current
)
519 g_slist_free(filters
);
523 #endif // wxUSE_FILEDLG