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