]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/filedlg.cpp
Correction to previous commit
[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();
acfd422a 42
291a8f20
RR
43//-----------------------------------------------------------------------------
44// "clicked" for OK-button
c801d85f
KB
45//-----------------------------------------------------------------------------
46
865bb325 47extern "C" {
9755e73b 48static void gtk_filedialog_ok_callback(GtkWidget *widget, wxFileDialog *dialog)
c801d85f 49{
2748d251 50 int style = dialog->GetStyle();
f8bc53eb 51 gchar* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget));
035b704a 52
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
77f70672 160 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
f8bc53eb
JS
180 if ( style & wxMULTIPLE )
181 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(m_widget), true);
27b2dd53 182
f8bc53eb
JS
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);
27b2dd53 189
f8bc53eb
JS
190 g_signal_connect(G_OBJECT(m_widget), "response",
191 GTK_SIGNAL_FUNC(gtk_filedialog_response_callback), (gpointer)this);
27b2dd53 192
77f70672 193 SetWildcard(wildCard);
f8bc53eb
JS
194
195 if ( style & wxSAVE )
196 {
da865fdd 197 if ( !defaultDir.empty() )
f8bc53eb
JS
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 else
205 {
da865fdd 206 if ( !defaultFileName.empty() )
f8bc53eb
JS
207 {
208 wxString dir;
da865fdd 209 if ( defaultDir.empty() )
f8bc53eb
JS
210 dir = ::wxGetCwd();
211 else
212 dir = defaultDir;
213
214 gtk_file_chooser_set_filename(
215 GTK_FILE_CHOOSER(m_widget),
216 wxConvFileName->cWX2MB( wxFileName(dir, defaultFileName).GetFullPath() ) );
217 }
da865fdd 218 else if ( !defaultDir.empty() )
f8bc53eb
JS
219 gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER(m_widget),
220 wxConvFileName->cWX2MB(defaultDir) );
221 }
77f70672
RR
222 }
223 else
4e1901b7 224#endif
77f70672 225 wxGenericFileDialog::Create( parent, message, defaultDir, defaultFileName, wildCard, style, pos );
9755e73b 226}
0e1399b3 227
76840ed0 228wxFileDialog::~wxFileDialog()
9755e73b 229{
4e1901b7 230#ifdef __WXGTK24__
77f70672
RR
231 if (!gtk_check_version(2,4,0))
232 {
233 if (m_destroyed_by_delete)
234 m_widget = NULL;
235 }
4e1901b7
RR
236#endif
237}
238
239void wxFileDialog::OnFakeOk( wxCommandEvent &event )
240{
241#ifdef __WXGTK24__
77f70672
RR
242 if (!gtk_check_version(2,4,0))
243 wxDialog::OnOK( event );
244 else
4e1901b7 245#endif
77f70672 246 wxGenericFileDialog::OnListOk( event );
4e1901b7
RR
247}
248
249int wxFileDialog::ShowModal()
250{
251#ifdef __WXGTK24__
77f70672
RR
252 if (!gtk_check_version(2,4,0))
253 return wxDialog::ShowModal();
254 else
4e1901b7 255#endif
77f70672 256 return wxGenericFileDialog::ShowModal();
4e1901b7
RR
257}
258
259bool wxFileDialog::Show( bool show )
260{
261#ifdef __WXGTK24__
77f70672
RR
262 if (!gtk_check_version(2,4,0))
263 return wxDialog::Show( show );
264 else
4e1901b7 265#endif
77f70672 266 return wxGenericFileDialog::Show( show );
9755e73b 267}
0e1399b3 268
5b2e23bf
RR
269void wxFileDialog::DoSetSize(int x, int y, int width, int height, int sizeFlags )
270{
271 if (!m_wxwindow)
272 return;
273 else
274 wxGenericFileDialog::DoSetSize( x, y, width, height, sizeFlags );
275}
276
f8bc53eb
JS
277wxString wxFileDialog::GetPath() const
278{
279#ifdef __WXGTK24__
280 if (!gtk_check_version(2,4,0))
281 return wxConvFileName->cMB2WX(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(m_widget)));
282 else
283#endif
284 return wxGenericFileDialog::GetPath();
285}
286
27b2dd53 287void wxFileDialog::GetFilenames(wxArrayString& files) const
9755e73b 288{
4e1901b7 289#ifdef __WXGTK24__
77f70672 290 if (!gtk_check_version(2,4,0))
9755e73b 291 {
77f70672 292 GetPaths(files);
f8bc53eb 293 for (size_t n = 0; n < files.GetCount(); ++n )
9755e73b 294 {
f8bc53eb
JS
295 wxFileName file(files[n]);
296 files[n] = file.GetFullName();
9755e73b 297 }
9755e73b 298 }
77f70672 299 else
4e1901b7 300#endif
77f70672 301 wxGenericFileDialog::GetFilenames( files );
9755e73b 302}
76840ed0 303
27b2dd53 304void wxFileDialog::GetPaths(wxArrayString& paths) const
9755e73b 305{
4e1901b7 306#ifdef __WXGTK24__
77f70672 307 if (!gtk_check_version(2,4,0))
9755e73b 308 {
27b2dd53 309 paths.Empty();
f8bc53eb 310 if (gtk_file_chooser_get_select_multiple(GTK_FILE_CHOOSER(m_widget)))
9755e73b 311 {
f8bc53eb 312 GSList *gpathsi = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(m_widget));
77f70672
RR
313 GSList *gpaths = gpathsi;
314 while (gpathsi)
315 {
f8bc53eb
JS
316 wxString file(wxConvFileName->cMB2WX((gchar*) gpathsi->data));
317 paths.Add(file);
77f70672
RR
318 g_free(gpathsi->data);
319 gpathsi = gpathsi->next;
320 }
0832aaaf 321
f8bc53eb 322 g_slist_free(gpaths);
9755e73b 323 }
f8bc53eb
JS
324 else
325 paths.Add(GetPath());
9755e73b
VS
326 }
327 else
4e1901b7 328#endif
77f70672 329 wxGenericFileDialog::GetPaths( paths );
9755e73b 330}
035b704a 331
9755e73b
VS
332void wxFileDialog::SetMessage(const wxString& message)
333{
4e1901b7 334#ifdef __WXGTK24__
77f70672
RR
335 if (!gtk_check_version(2,4,0))
336 {
337 m_message = message;
338 SetTitle(message);
339 }
340 else
27b2dd53 341#endif
77f70672 342 wxGenericFileDialog::SetMessage( message );
9755e73b
VS
343}
344
76840ed0
RR
345void wxFileDialog::SetPath(const wxString& path)
346{
4e1901b7 347#ifdef __WXGTK24__
77f70672
RR
348 if (!gtk_check_version(2,4,0))
349 {
350 if (path.empty()) return;
351
f8bc53eb 352 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(m_widget), wxConvFileName->cWX2MB(path));
77f70672
RR
353 }
354 else
27b2dd53 355#endif
77f70672 356 wxGenericFileDialog::SetPath( path );
76840ed0
RR
357}
358
9755e73b
VS
359void wxFileDialog::SetDirectory(const wxString& dir)
360{
4e1901b7 361#ifdef __WXGTK24__
77f70672 362 if (!gtk_check_version(2,4,0))
76840ed0 363 {
da865fdd 364 if (wxDirExists(dir))
77f70672 365 {
f8bc53eb 366 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(m_widget), wxConvFileName->cWX2MB(dir));
77f70672 367 }
76840ed0 368 }
77f70672 369 else
27b2dd53 370#endif
77f70672 371 wxGenericFileDialog::SetDirectory( dir );
9755e73b
VS
372}
373
f8bc53eb
JS
374wxString wxFileDialog::GetDirectory() const
375{
376#ifdef __WXGTK24__
377 if (!gtk_check_version(2,4,0))
378 return wxConvFileName->cMB2WX(
379 gtk_file_chooser_get_current_folder( GTK_FILE_CHOOSER(m_widget) ) );
380 else
381#endif
382 return wxGenericFileDialog::GetDirectory();
383}
384
9755e73b
VS
385void wxFileDialog::SetFilename(const wxString& name)
386{
4e1901b7 387#ifdef __WXGTK24__
77f70672
RR
388 if (!gtk_check_version(2,4,0))
389 {
f8bc53eb
JS
390 if (GetStyle() & wxSAVE)
391 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(m_widget), wxConvFileName->cWX2MB(name));
392 else
393 SetPath(wxFileName(GetDirectory(), name).GetFullPath());
77f70672
RR
394 }
395 else
4e1901b7 396#endif
77f70672 397 wxGenericFileDialog::SetFilename( name );
9755e73b 398}
035b704a 399
f8bc53eb
JS
400wxString wxFileDialog::GetFilename() const
401{
402#ifdef __WXGTK24__
403 if (!gtk_check_version(2,4,0))
404 return wxFileName(
405 wxConvFileName->cMB2WX(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(m_widget))) ).GetFullName();
406 else
407#endif
408 return wxGenericFileDialog::GetFilename();
409}
410
9755e73b
VS
411void wxFileDialog::SetWildcard(const wxString& wildCard)
412{
4e1901b7 413#ifdef __WXGTK24__
77f70672 414 if (!gtk_check_version(2,4,0))
9755e73b 415 {
77f70672
RR
416 // parse filters
417 wxArrayString wildDescriptions, wildFilters;
f8bc53eb 418 if (!wxParseCommonDialogsFilter(wildCard, wildDescriptions, wildFilters))
77f70672 419 {
f8bc53eb 420 wxFAIL_MSG( wxT("wxFileDialog::SetWildCard - bad wildcard string") );
77f70672
RR
421 }
422 else
9755e73b 423 {
f8bc53eb
JS
424 // Parsing went fine. Set m_wildCard to be returned by wxFileDialogBase::GetWildcard
425 m_wildCard = wildCard;
426
427 GtkFileChooser* chooser = GTK_FILE_CHOOSER(m_widget);
428
429 // empty current filter list:
430 GSList* ifilters = gtk_file_chooser_list_filters(chooser);
431 GSList* filters = ifilters;
432
433 while (ifilters)
434 {
435 gtk_file_chooser_remove_filter(chooser,GTK_FILE_FILTER(ifilters->data));
436 ifilters = ifilters->next;
437 }
438 g_slist_free(filters);
439
77f70672 440 // add parsed to GtkChooser
f8bc53eb 441 for (size_t n = 0; n < wildFilters.GetCount(); ++n)
9755e73b 442 {
77f70672 443 GtkFileFilter* filter = gtk_file_filter_new();
f8bc53eb
JS
444 gtk_file_filter_set_name(filter, wxGTK_CONV(wildDescriptions[n]));
445
446 wxStringTokenizer exttok(wildFilters[n], wxT(";"));
447 while (exttok.HasMoreTokens())
77f70672 448 {
f8bc53eb
JS
449 wxString token = exttok.GetNextToken();
450 gtk_file_filter_add_pattern(filter, wxGTK_CONV(token));
77f70672 451 }
27b2dd53 452
77f70672
RR
453 gtk_file_chooser_add_filter(chooser, filter);
454 }
f8bc53eb
JS
455
456 // Reset the filter index
457 SetFilterIndex(0);
9755e73b
VS
458 }
459 }
77f70672 460 else
4e1901b7 461#endif
77f70672 462 wxGenericFileDialog::SetWildcard( wildCard );
9755e73b 463}
a3622daa 464
9755e73b
VS
465void wxFileDialog::SetFilterIndex(int filterIndex)
466{
4e1901b7 467#ifdef __WXGTK24__
77f70672 468 if (!gtk_check_version(2,4,0))
9755e73b 469 {
f8bc53eb 470 gpointer filter;
77f70672 471 GtkFileChooser *chooser = GTK_FILE_CHOOSER(m_widget);
f8bc53eb
JS
472 GSList *filters = gtk_file_chooser_list_filters(chooser);
473
474 filter = g_slist_nth_data(filters, filterIndex);
475
476 if (filter != NULL)
9755e73b 477 {
f8bc53eb
JS
478 gtk_file_chooser_set_filter(chooser, GTK_FILE_FILTER(filter));
479 }
480 else
481 {
482 wxFAIL_MSG( wxT("wxFileDialog::SetFilterIndex - bad filter index") );
9755e73b 483 }
f8bc53eb 484
77f70672 485 g_slist_free(filters);
9755e73b 486 }
77f70672 487 else
4e1901b7 488#endif
77f70672 489 wxGenericFileDialog::SetFilterIndex( filterIndex );
4e1901b7
RR
490}
491
f8bc53eb 492int wxFileDialog::GetFilterIndex() const
4e1901b7
RR
493{
494#ifdef __WXGTK24__
f8bc53eb 495 if (!gtk_check_version(2,4,0))
4e1901b7 496 {
f8bc53eb
JS
497 GtkFileChooser *chooser = GTK_FILE_CHOOSER(m_widget);
498 GtkFileFilter *filter = gtk_file_chooser_get_filter(chooser);
499 GSList *filters = gtk_file_chooser_list_filters(chooser);
500 gint index = g_slist_index(filters, filter);
501 g_slist_free(filters);
3502e687 502
f8bc53eb 503 if (index == -1)
9755e73b 504 {
f8bc53eb
JS
505 wxFAIL_MSG( wxT("wxFileDialog::GetFilterIndex - bad filter index returned by gtk+") );
506 return 0;
9755e73b 507 }
f8bc53eb
JS
508 else
509 return index;
9755e73b 510 }
f8bc53eb 511 else
4e1901b7 512#endif
f8bc53eb 513 return wxGenericFileDialog::GetFilterIndex();
9755e73b 514}
3f6638b8 515
4e1901b7 516#endif // wxUSE_FILEDLG