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