]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/gtk/filedlg.cpp
cleanup - more reformatting; fixed bug introduced in prior commit
[wxWidgets.git] / src / gtk / filedlg.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: gtk/filedlg.cpp
3// Purpose: native implementation of wxFileDialog
4// Author: Robert Roebling, Zbigniew Zagorski, Mart Raudsepp
5// Id: $Id$
6// Copyright: (c) 1998 Robert Roebling, 2004 Zbigniew Zagorski, 2005 Mart Raudsepp
7// Licence: wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
10// For compilers that support precompilation, includes "wx.h".
11#include "wx/wxprec.h"
12
13// Include setup.h to get wxUSE flags for compilers that do not support precompilation of headers
14#include "wx/setup.h"
15
16#if wxUSE_FILEDLG
17
18#include "wx/filedlg.h"
19
20#ifdef __WXGTK24__
21
22#include <gtk/gtk.h>
23#include "wx/gtk/private.h"
24
25#include <unistd.h> // chdir
26
27#include "wx/intl.h"
28#include "wx/filename.h" // wxFilename
29#include "wx/tokenzr.h" // wxStringTokenizer
30#include "wx/filefn.h" // ::wxGetCwd
31#include "wx/msgdlg.h" // wxMessageDialog
32
33//-----------------------------------------------------------------------------
34// idle system
35//-----------------------------------------------------------------------------
36
37extern void wxapp_install_idle_handler();
38
39//-----------------------------------------------------------------------------
40// "clicked" for OK-button
41//-----------------------------------------------------------------------------
42
43extern "C" {
44static void gtk_filedialog_ok_callback(GtkWidget *widget, wxFileDialog *dialog)
45{
46 int style = dialog->GetStyle();
47 gchar* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget));
48
49 // gtk version numbers must be identical with the one in ctor (that calls set_do_overwrite_confirmation)
50#if GTK_CHECK_VERSION(2,7,3)
51 if(gtk_check_version(2,7,3) != NULL)
52#endif
53 if ((style & wxSAVE) && (style & wxOVERWRITE_PROMPT))
54 {
55 if ( g_file_test(filename, G_FILE_TEST_EXISTS) )
56 {
57 wxString msg;
58
59 msg.Printf(
60 _("File '%s' already exists, do you really want to overwrite it?"),
61 wxString(wxConvFileName->cMB2WX(filename)).c_str());
62
63 wxMessageDialog dlg(dialog, msg, _("Confirm"),
64 wxYES_NO | wxICON_QUESTION);
65 if (dlg.ShowModal() != wxID_YES)
66 return;
67 }
68 }
69
70 // change to the directory where the user went if asked
71 if (style & wxCHANGE_DIR)
72 {
73 // Use chdir to not care about filename encodings
74 gchar* folder = g_path_get_dirname(filename);
75 chdir(folder);
76 g_free(folder);
77 }
78
79 g_free(filename);
80
81 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK);
82 event.SetEventObject(dialog);
83 dialog->GetEventHandler()->ProcessEvent(event);
84}
85}
86
87//-----------------------------------------------------------------------------
88// "clicked" for Cancel-button
89//-----------------------------------------------------------------------------
90
91extern "C" {
92static void gtk_filedialog_cancel_callback(GtkWidget *WXUNUSED(w),
93 wxFileDialog *dialog)
94{
95 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
96 event.SetEventObject(dialog);
97 dialog->GetEventHandler()->ProcessEvent(event);
98}
99}
100
101extern "C" {
102static void gtk_filedialog_response_callback(GtkWidget *w,
103 gint response,
104 wxFileDialog *dialog)
105{
106 wxapp_install_idle_handler();
107
108 if (response == GTK_RESPONSE_ACCEPT)
109 gtk_filedialog_ok_callback(w, dialog);
110 else if (response == GTK_RESPONSE_CANCEL)
111 gtk_filedialog_cancel_callback(w, dialog);
112 else // "delete"
113 {
114 gtk_filedialog_cancel_callback(w, dialog);
115 dialog->m_destroyed_by_delete = true;
116 }
117}
118}
119
120#endif // __WXGTK24__
121
122//-----------------------------------------------------------------------------
123// wxFileDialog
124//-----------------------------------------------------------------------------
125
126IMPLEMENT_DYNAMIC_CLASS(wxFileDialog,wxGenericFileDialog)
127
128BEGIN_EVENT_TABLE(wxFileDialog,wxGenericFileDialog)
129 EVT_BUTTON(wxID_OK, wxFileDialog::OnFakeOk)
130END_EVENT_TABLE()
131
132wxFileDialog::wxFileDialog(wxWindow *parent, const wxString& message,
133 const wxString& defaultDir,
134 const wxString& defaultFileName,
135 const wxString& wildCard,
136 long style, const wxPoint& pos)
137 : wxGenericFileDialog(parent, message, defaultDir, defaultFileName,
138 wildCard, style, pos, true )
139{
140#ifdef __WXGTK24__
141 if (!gtk_check_version(2,4,0))
142 {
143 wxASSERT_MSG( !( (style & wxSAVE) && (style & wxMULTIPLE) ), wxT("wxFileDialog - wxMULTIPLE used on a save dialog" ) );
144 m_needParent = false;
145 m_destroyed_by_delete = false;
146
147 if (!PreCreation(parent, pos, wxDefaultSize) ||
148 !CreateBase(parent, wxID_ANY, pos, wxDefaultSize, style,
149 wxDefaultValidator, wxT("filedialog")))
150 {
151 wxFAIL_MSG( wxT("wxFileDialog creation failed") );
152 return;
153 }
154
155 GtkFileChooserAction gtk_action;
156 GtkWindow* gtk_parent = NULL;
157 if (parent)
158 gtk_parent = GTK_WINDOW( gtk_widget_get_toplevel(parent->m_widget) );
159
160 const gchar* ok_btn_stock;
161 if ( style & wxSAVE )
162 {
163 gtk_action = GTK_FILE_CHOOSER_ACTION_SAVE;
164 ok_btn_stock = GTK_STOCK_SAVE;
165 }
166 else
167 {
168 gtk_action = GTK_FILE_CHOOSER_ACTION_OPEN;
169 ok_btn_stock = GTK_STOCK_OPEN;
170 }
171
172 m_widget = gtk_file_chooser_dialog_new(
173 wxGTK_CONV(m_message),
174 gtk_parent,
175 gtk_action,
176 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
177 ok_btn_stock, GTK_RESPONSE_ACCEPT,
178 NULL);
179
180 if ( style & wxMULTIPLE )
181 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(m_widget), true);
182
183 // local-only property could be set to false to allow non-local files to be loaded.
184 // In that case get/set_uri(s) should be used instead of get/set_filename(s) everywhere
185 // and the GtkFileChooserDialog should probably also be created with a backend,
186 // e.g "gnome-vfs", "default", ... (gtk_file_chooser_dialog_new_with_backend).
187 // Currently local-only is kept as the default - true:
188 // gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(m_widget), true);
189
190 g_signal_connect(G_OBJECT(m_widget), "response",
191 GTK_SIGNAL_FUNC(gtk_filedialog_response_callback), (gpointer)this);
192
193 SetWildcard(wildCard);
194
195 if ( style & wxSAVE )
196 {
197 if ( !defaultDir.empty() )
198 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(m_widget),
199 wxConvFileName->cWX2MB(defaultDir));
200
201 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(m_widget),
202 wxConvFileName->cWX2MB(defaultFileName));
203
204#if GTK_CHECK_VERSION(2,7,3)
205 if (!gtk_check_version(2,7,3))
206 gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(m_widget), TRUE);
207#endif
208 }
209 else
210 {
211 if ( !defaultFileName.empty() )
212 {
213 wxString dir;
214 if ( defaultDir.empty() )
215 dir = ::wxGetCwd();
216 else
217 dir = defaultDir;
218
219 gtk_file_chooser_set_filename(
220 GTK_FILE_CHOOSER(m_widget),
221 wxConvFileName->cWX2MB( wxFileName(dir, defaultFileName).GetFullPath() ) );
222 }
223 else if ( !defaultDir.empty() )
224 gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER(m_widget),
225 wxConvFileName->cWX2MB(defaultDir) );
226 }
227 }
228 else
229#endif
230 wxGenericFileDialog::Create( parent, message, defaultDir, defaultFileName, wildCard, style, pos );
231}
232
233wxFileDialog::~wxFileDialog()
234{
235#ifdef __WXGTK24__
236 if (!gtk_check_version(2,4,0))
237 {
238 if (m_destroyed_by_delete)
239 m_widget = NULL;
240 }
241#endif
242}
243
244void wxFileDialog::OnFakeOk( wxCommandEvent &event )
245{
246#ifdef __WXGTK24__
247 if (!gtk_check_version(2,4,0))
248 wxDialog::OnOK( event );
249 else
250#endif
251 wxGenericFileDialog::OnListOk( event );
252}
253
254int wxFileDialog::ShowModal()
255{
256#ifdef __WXGTK24__
257 if (!gtk_check_version(2,4,0))
258 return wxDialog::ShowModal();
259 else
260#endif
261 return wxGenericFileDialog::ShowModal();
262}
263
264bool wxFileDialog::Show( bool show )
265{
266#ifdef __WXGTK24__
267 if (!gtk_check_version(2,4,0))
268 return wxDialog::Show( show );
269 else
270#endif
271 return wxGenericFileDialog::Show( show );
272}
273
274void wxFileDialog::DoSetSize(int x, int y, int width, int height, int sizeFlags )
275{
276 if (!m_wxwindow)
277 return;
278 else
279 wxGenericFileDialog::DoSetSize( x, y, width, height, sizeFlags );
280}
281
282wxString wxFileDialog::GetPath() const
283{
284#ifdef __WXGTK24__
285 if (!gtk_check_version(2,4,0))
286 return wxConvFileName->cMB2WX(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(m_widget)));
287 else
288#endif
289 return wxGenericFileDialog::GetPath();
290}
291
292void wxFileDialog::GetFilenames(wxArrayString& files) const
293{
294#ifdef __WXGTK24__
295 if (!gtk_check_version(2,4,0))
296 {
297 GetPaths(files);
298 for (size_t n = 0; n < files.GetCount(); ++n )
299 {
300 wxFileName file(files[n]);
301 files[n] = file.GetFullName();
302 }
303 }
304 else
305#endif
306 wxGenericFileDialog::GetFilenames( files );
307}
308
309void wxFileDialog::GetPaths(wxArrayString& paths) const
310{
311#ifdef __WXGTK24__
312 if (!gtk_check_version(2,4,0))
313 {
314 paths.Empty();
315 if (gtk_file_chooser_get_select_multiple(GTK_FILE_CHOOSER(m_widget)))
316 {
317 GSList *gpathsi = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(m_widget));
318 GSList *gpaths = gpathsi;
319 while (gpathsi)
320 {
321 wxString file(wxConvFileName->cMB2WX((gchar*) gpathsi->data));
322 paths.Add(file);
323 g_free(gpathsi->data);
324 gpathsi = gpathsi->next;
325 }
326
327 g_slist_free(gpaths);
328 }
329 else
330 paths.Add(GetPath());
331 }
332 else
333#endif
334 wxGenericFileDialog::GetPaths( paths );
335}
336
337void wxFileDialog::SetMessage(const wxString& message)
338{
339#ifdef __WXGTK24__
340 if (!gtk_check_version(2,4,0))
341 {
342 m_message = message;
343 SetTitle(message);
344 }
345 else
346#endif
347 wxGenericFileDialog::SetMessage( message );
348}
349
350void wxFileDialog::SetPath(const wxString& path)
351{
352#ifdef __WXGTK24__
353 if (!gtk_check_version(2,4,0))
354 {
355 if (path.empty()) return;
356
357 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(m_widget), wxConvFileName->cWX2MB(path));
358 }
359 else
360#endif
361 wxGenericFileDialog::SetPath( path );
362}
363
364void wxFileDialog::SetDirectory(const wxString& dir)
365{
366#ifdef __WXGTK24__
367 if (!gtk_check_version(2,4,0))
368 {
369 if (wxDirExists(dir))
370 {
371 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(m_widget), wxConvFileName->cWX2MB(dir));
372 }
373 }
374 else
375#endif
376 wxGenericFileDialog::SetDirectory( dir );
377}
378
379wxString wxFileDialog::GetDirectory() const
380{
381#ifdef __WXGTK24__
382 if (!gtk_check_version(2,4,0))
383 return wxConvFileName->cMB2WX(
384 gtk_file_chooser_get_current_folder( GTK_FILE_CHOOSER(m_widget) ) );
385 else
386#endif
387 return wxGenericFileDialog::GetDirectory();
388}
389
390void wxFileDialog::SetFilename(const wxString& name)
391{
392#ifdef __WXGTK24__
393 if (!gtk_check_version(2,4,0))
394 {
395 if (GetStyle() & wxSAVE)
396 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(m_widget), wxConvFileName->cWX2MB(name));
397 else
398 SetPath(wxFileName(GetDirectory(), name).GetFullPath());
399 }
400 else
401#endif
402 wxGenericFileDialog::SetFilename( name );
403}
404
405wxString wxFileDialog::GetFilename() const
406{
407#ifdef __WXGTK24__
408 if (!gtk_check_version(2,4,0))
409 return wxFileName(
410 wxConvFileName->cMB2WX(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(m_widget))) ).GetFullName();
411 else
412#endif
413 return wxGenericFileDialog::GetFilename();
414}
415
416void wxFileDialog::SetWildcard(const wxString& wildCard)
417{
418#ifdef __WXGTK24__
419 if (!gtk_check_version(2,4,0))
420 {
421 // parse filters
422 wxArrayString wildDescriptions, wildFilters;
423 if (!wxParseCommonDialogsFilter(wildCard, wildDescriptions, wildFilters))
424 {
425 wxFAIL_MSG( wxT("wxFileDialog::SetWildCard - bad wildcard string") );
426 }
427 else
428 {
429 // Parsing went fine. Set m_wildCard to be returned by wxFileDialogBase::GetWildcard
430 m_wildCard = wildCard;
431
432 GtkFileChooser* chooser = GTK_FILE_CHOOSER(m_widget);
433
434 // empty current filter list:
435 GSList* ifilters = gtk_file_chooser_list_filters(chooser);
436 GSList* filters = ifilters;
437
438 while (ifilters)
439 {
440 gtk_file_chooser_remove_filter(chooser,GTK_FILE_FILTER(ifilters->data));
441 ifilters = ifilters->next;
442 }
443 g_slist_free(filters);
444
445 // add parsed to GtkChooser
446 for (size_t n = 0; n < wildFilters.GetCount(); ++n)
447 {
448 GtkFileFilter* filter = gtk_file_filter_new();
449 gtk_file_filter_set_name(filter, wxGTK_CONV(wildDescriptions[n]));
450
451 wxStringTokenizer exttok(wildFilters[n], wxT(";"));
452 while (exttok.HasMoreTokens())
453 {
454 wxString token = exttok.GetNextToken();
455 gtk_file_filter_add_pattern(filter, wxGTK_CONV(token));
456 }
457
458 gtk_file_chooser_add_filter(chooser, filter);
459 }
460
461 // Reset the filter index
462 SetFilterIndex(0);
463 }
464 }
465 else
466#endif
467 wxGenericFileDialog::SetWildcard( wildCard );
468}
469
470void wxFileDialog::SetFilterIndex(int filterIndex)
471{
472#ifdef __WXGTK24__
473 if (!gtk_check_version(2,4,0))
474 {
475 gpointer filter;
476 GtkFileChooser *chooser = GTK_FILE_CHOOSER(m_widget);
477 GSList *filters = gtk_file_chooser_list_filters(chooser);
478
479 filter = g_slist_nth_data(filters, filterIndex);
480
481 if (filter != NULL)
482 {
483 gtk_file_chooser_set_filter(chooser, GTK_FILE_FILTER(filter));
484 }
485 else
486 {
487 wxFAIL_MSG( wxT("wxFileDialog::SetFilterIndex - bad filter index") );
488 }
489
490 g_slist_free(filters);
491 }
492 else
493#endif
494 wxGenericFileDialog::SetFilterIndex( filterIndex );
495}
496
497int wxFileDialog::GetFilterIndex() const
498{
499#ifdef __WXGTK24__
500 if (!gtk_check_version(2,4,0))
501 {
502 GtkFileChooser *chooser = GTK_FILE_CHOOSER(m_widget);
503 GtkFileFilter *filter = gtk_file_chooser_get_filter(chooser);
504 GSList *filters = gtk_file_chooser_list_filters(chooser);
505 gint index = g_slist_index(filters, filter);
506 g_slist_free(filters);
507
508 if (index == -1)
509 {
510 wxFAIL_MSG( wxT("wxFileDialog::GetFilterIndex - bad filter index returned by gtk+") );
511 return 0;
512 }
513 else
514 return index;
515 }
516 else
517#endif
518 return wxGenericFileDialog::GetFilterIndex();
519}
520
521#endif // wxUSE_FILEDLG