]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/filedlg.cpp
added wxConvFileName which is a variable, not define as wxConvFile; added comments...
[wxWidgets.git] / src / gtk1 / filedlg.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
3f6638b8 2// Name: gtk/filedlg.cpp
9755e73b
VS
3// Purpose: native implementation of wxFileDialog
4// Author: Robert Roebling, Zbigniew Zagorski
a81258be 5// Id: $Id$
9755e73b 6// Copyright: (c) 1998 Robert Roebling, 2004 Zbigniew Zagorski
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
4e1901b7 17#if wxUSE_FILEDLG
9755e73b 18
c801d85f
KB
19#include "wx/filedlg.h"
20#include "wx/utils.h"
21#include "wx/intl.h"
9755e73b 22#include "wx/filename.h"
f3613896 23#include "wx/msgdlg.h"
c801d85f 24
071a2d78 25#include <gtk/gtk.h>
4e1901b7
RR
26
27#ifdef __WXGTK24__
9755e73b 28#include "wx/gtk/private.h"
83624f79 29
acfd422a
RR
30//-----------------------------------------------------------------------------
31// idle system
32//-----------------------------------------------------------------------------
33
34extern void wxapp_install_idle_handler();
35extern bool g_isIdle;
36
291a8f20
RR
37//-----------------------------------------------------------------------------
38// "clicked" for OK-button
c801d85f
KB
39//-----------------------------------------------------------------------------
40
865bb325 41extern "C" {
9755e73b 42static void gtk_filedialog_ok_callback(GtkWidget *widget, wxFileDialog *dialog)
c801d85f 43{
2748d251 44 int style = dialog->GetStyle();
9755e73b
VS
45 gchar* text = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget));
46 wxString filename(wxGTK_CONV_BACK(text));
035b704a 47
9755e73b 48 if ((style & wxSAVE) && (style & wxOVERWRITE_PROMPT))
bfc6fde4 49 {
9755e73b 50 if (wxFileExists(filename))
0e1399b3
VZ
51 {
52 wxString msg;
9755e73b
VS
53 msg.Printf(
54 _("File '%s' already exists, do you really want to overwrite it?"),
55 filename.c_str());
0e1399b3 56
9755e73b
VS
57 wxMessageDialog dlg(dialog, msg, _("Confirm"),
58 wxYES_NO | wxICON_QUESTION);
59 if (dlg.ShowModal() != wxID_YES)
0e1399b3
VZ
60 return;
61 }
83624f79 62 }
9755e73b 63 else if ((style & wxOPEN) && ( style & wxFILE_MUST_EXIST))
bfc6fde4 64 {
9755e73b 65 if (!wxFileExists( filename ))
bfc6fde4 66 {
9755e73b
VS
67 wxMessageDialog dlg(dialog,
68 _("Please choose an existing file."),
69 _("Error"), wxOK | wxICON_ERROR);
70 dlg.ShowModal();
bfc6fde4
VZ
71
72 return;
73 }
74 }
035b704a 75
3f6638b8 76 // change to the directory where the user went if asked
9755e73b 77 if (style & wxCHANGE_DIR)
3f6638b8
VZ
78 {
79 wxString cwd;
80 wxSplitPath(filename, &cwd, NULL, NULL);
81
9755e73b 82 if (cwd != wxGetCwd())
3f6638b8
VZ
83 {
84 wxSetWorkingDirectory(cwd);
85 }
86 }
87
76840ed0 88 dialog->SetPath(filename);
9755e73b 89 dialog->UpdateFromDialog();
27b2dd53 90
bfc6fde4 91 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK);
9755e73b
VS
92 event.SetEventObject(dialog);
93 dialog->GetEventHandler()->ProcessEvent(event);
ff7b1510 94}
865bb325 95}
c801d85f 96
291a8f20
RR
97//-----------------------------------------------------------------------------
98// "clicked" for Cancel-button
99//-----------------------------------------------------------------------------
100
865bb325 101extern "C" {
9755e73b
VS
102static void gtk_filedialog_cancel_callback(GtkWidget *WXUNUSED(w),
103 wxFileDialog *dialog)
c801d85f 104{
bfc6fde4 105 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
9755e73b
VS
106 event.SetEventObject(dialog);
107 dialog->GetEventHandler()->ProcessEvent(event);
108}
865bb325 109}
9755e73b 110
865bb325 111extern "C" {
9755e73b
VS
112static void gtk_filedialog_response_callback(GtkWidget *w,
113 int response,
114 wxFileDialog *dialog)
115{
116 wxapp_install_idle_handler();
27b2dd53 117
a7334928 118 if (response == GTK_RESPONSE_ACCEPT)
9755e73b 119 gtk_filedialog_ok_callback(w, dialog);
c2740a5a
RR
120 else if (response == GTK_RESPONSE_CANCEL)
121 gtk_filedialog_cancel_callback(w, dialog);
122 else // "delete"
123 {
a7334928 124 gtk_filedialog_cancel_callback(w, dialog);
27b2dd53 125 dialog->m_destroyed_by_delete = true;
c2740a5a 126 }
ff7b1510 127}
865bb325
VZ
128}
129
130#endif // __WXGTK24__
c801d85f 131
291a8f20
RR
132//-----------------------------------------------------------------------------
133// wxFileDialog
134//-----------------------------------------------------------------------------
135
4e1901b7
RR
136IMPLEMENT_DYNAMIC_CLASS(wxFileDialog,wxGenericFileDialog)
137
138BEGIN_EVENT_TABLE(wxFileDialog,wxGenericFileDialog)
139 EVT_BUTTON(wxID_OK, wxFileDialog::OnFakeOk)
140END_EVENT_TABLE()
c801d85f 141
9755e73b
VS
142wxFileDialog::wxFileDialog(wxWindow *parent, const wxString& message,
143 const wxString& defaultDir,
144 const wxString& defaultFileName,
145 const wxString& wildCard,
146 long style, const wxPoint& pos)
4e1901b7
RR
147 : wxGenericFileDialog(parent, message, defaultDir, defaultFileName,
148 wildCard, style, pos, true )
c801d85f 149{
4e1901b7 150#ifdef __WXGTK24__
77f70672
RR
151 if (!gtk_check_version(2,4,0))
152 {
27b2dd53
WS
153 m_needParent = false;
154 m_destroyed_by_delete = false;
83624f79 155
77f70672
RR
156 if (!PreCreation(parent, pos, wxDefaultSize) ||
157 !CreateBase(parent, wxID_ANY, pos, wxDefaultSize, style,
9755e73b 158 wxDefaultValidator, wxT("filedialog")))
77f70672
RR
159 {
160 wxFAIL_MSG( wxT("wxFileDialog creation failed") );
161 return;
162 }
3f6638b8 163
77f70672
RR
164 bool multiple = (style & wxMULTIPLE) == wxMULTIPLE;
165 GtkFileChooserAction gtk_action;
166 GtkWindow* gtk_parent = NULL;
167 if (parent)
168 gtk_parent = GTK_WINDOW(parent->m_widget);
27b2dd53 169
77f70672
RR
170 gchar* ok_btn_stock;
171 if ((style & wxSAVE) == wxSAVE)
172 {
173 gtk_action = GTK_FILE_CHOOSER_ACTION_SAVE;
174 ok_btn_stock = GTK_STOCK_SAVE;
175 }
176 else
177 {
178 gtk_action = GTK_FILE_CHOOSER_ACTION_OPEN;
179 ok_btn_stock = GTK_STOCK_OPEN;
180 }
181 m_widget = gtk_file_chooser_dialog_new(
9755e73b
VS
182 wxGTK_CONV(m_message),
183 gtk_parent,
184 gtk_action,
185 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
186 ok_btn_stock, GTK_RESPONSE_ACCEPT,
187 NULL);
188
77f70672 189 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(m_widget), multiple);
27b2dd53 190
77f70672 191 gtk_signal_connect(GTK_OBJECT(m_widget),
27b2dd53 192 "response",
9755e73b
VS
193 GTK_SIGNAL_FUNC(gtk_filedialog_response_callback),
194 (gpointer*)this);
27b2dd53 195
77f70672
RR
196 m_path = m_dir;
197 if (!m_path.empty() && m_path.Last() != wxT('/'))
198 m_path += wxT('/');
199 m_path += m_fileName;
200 SetPath(m_path);
27b2dd53 201
77f70672
RR
202 SetWildcard(wildCard);
203 SetFilterIndex(0);
204 }
205 else
4e1901b7 206#endif
77f70672 207 wxGenericFileDialog::Create( parent, message, defaultDir, defaultFileName, wildCard, style, pos );
9755e73b 208}
0e1399b3 209
76840ed0 210wxFileDialog::~wxFileDialog()
9755e73b 211{
4e1901b7 212#ifdef __WXGTK24__
77f70672
RR
213 if (!gtk_check_version(2,4,0))
214 {
215 if (m_destroyed_by_delete)
216 m_widget = NULL;
217 }
4e1901b7
RR
218#endif
219}
220
221void wxFileDialog::OnFakeOk( wxCommandEvent &event )
222{
223#ifdef __WXGTK24__
77f70672
RR
224 if (!gtk_check_version(2,4,0))
225 wxDialog::OnOK( event );
226 else
4e1901b7 227#endif
77f70672 228 wxGenericFileDialog::OnListOk( event );
4e1901b7
RR
229}
230
231int wxFileDialog::ShowModal()
232{
233#ifdef __WXGTK24__
77f70672
RR
234 if (!gtk_check_version(2,4,0))
235 return wxDialog::ShowModal();
236 else
4e1901b7 237#endif
77f70672 238 return wxGenericFileDialog::ShowModal();
4e1901b7
RR
239}
240
241bool wxFileDialog::Show( bool show )
242{
243#ifdef __WXGTK24__
77f70672
RR
244 if (!gtk_check_version(2,4,0))
245 return wxDialog::Show( show );
246 else
4e1901b7 247#endif
77f70672 248 return wxGenericFileDialog::Show( show );
9755e73b 249}
0e1399b3 250
27b2dd53 251void wxFileDialog::GetFilenames(wxArrayString& files) const
9755e73b 252{
4e1901b7 253#ifdef __WXGTK24__
77f70672 254 if (!gtk_check_version(2,4,0))
9755e73b 255 {
77f70672
RR
256 GetPaths(files);
257 for (size_t n = 0; n < files.GetCount(); n++ )
9755e73b 258 {
77f70672
RR
259 wxString name,ext;
260 wxSplitPath(files[n], NULL, &name, &ext);
27b2dd53 261 if (!ext.empty())
77f70672
RR
262 {
263 name += wxT(".");
264 name += ext;
265 }
266 files[n] = name;
9755e73b 267 }
9755e73b 268 }
77f70672 269 else
4e1901b7 270#endif
77f70672 271 wxGenericFileDialog::GetFilenames( files );
9755e73b 272}
76840ed0 273
27b2dd53 274void wxFileDialog::GetPaths(wxArrayString& paths) const
9755e73b 275{
4e1901b7 276#ifdef __WXGTK24__
77f70672 277 if (!gtk_check_version(2,4,0))
9755e73b 278 {
27b2dd53 279 paths.Empty();
77f70672 280 if (GetWindowStyle() & wxMULTIPLE)
9755e73b 281 {
27b2dd53 282 GSList *gpathsi =
77f70672
RR
283 gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(m_widget));
284 GSList *gpaths = gpathsi;
285 while (gpathsi)
286 {
287 wxString file = wxGTK_CONV_BACK((gchar*) gpathsi->data);
288 paths.Add(file);
289 g_free(gpathsi->data);
290 gpathsi = gpathsi->next;
291 }
27b2dd53 292 if (gpaths)
77f70672
RR
293 g_slist_free(gpaths);
294 }
295 else
296 {
297 paths.Add(m_fileName);
9755e73b 298 }
9755e73b
VS
299 }
300 else
4e1901b7 301#endif
77f70672 302 wxGenericFileDialog::GetPaths( paths );
9755e73b 303}
035b704a 304
9755e73b
VS
305void wxFileDialog::SetMessage(const wxString& message)
306{
4e1901b7 307#ifdef __WXGTK24__
77f70672
RR
308 if (!gtk_check_version(2,4,0))
309 {
310 m_message = message;
311 SetTitle(message);
312 }
313 else
27b2dd53 314#endif
77f70672 315 wxGenericFileDialog::SetMessage( message );
9755e73b
VS
316}
317
76840ed0
RR
318void wxFileDialog::SetPath(const wxString& path)
319{
4e1901b7 320#ifdef __WXGTK24__
77f70672
RR
321 if (!gtk_check_version(2,4,0))
322 {
323 if (path.empty()) return;
324
325 wxFileName fn(path);
326 m_path = fn.GetFullPath();
327 m_dir = fn.GetPath();
328 m_fileName = fn.GetFullName();
329 UpdateDialog();
330 }
331 else
27b2dd53 332#endif
77f70672 333 wxGenericFileDialog::SetPath( path );
76840ed0
RR
334}
335
9755e73b
VS
336void wxFileDialog::SetDirectory(const wxString& dir)
337{
4e1901b7 338#ifdef __WXGTK24__
77f70672 339 if (!gtk_check_version(2,4,0))
76840ed0 340 {
27b2dd53 341 if (wxPathExists(dir))
77f70672
RR
342 {
343 m_dir = dir;
344 m_path = wxFileName(m_dir, m_fileName).GetFullPath();
345 UpdateDialog();
346 }
76840ed0 347 }
77f70672 348 else
27b2dd53 349#endif
77f70672 350 wxGenericFileDialog::SetDirectory( dir );
9755e73b
VS
351}
352
353void wxFileDialog::SetFilename(const wxString& name)
354{
4e1901b7 355#ifdef __WXGTK24__
77f70672
RR
356 if (!gtk_check_version(2,4,0))
357 {
358 m_fileName = name;
359 m_path = wxFileName(m_dir, m_fileName).GetFullPath();
360 UpdateDialog();
361 }
362 else
4e1901b7 363#endif
77f70672 364 wxGenericFileDialog::SetFilename( name );
9755e73b 365}
035b704a 366
9755e73b
VS
367void wxFileDialog::SetWildcard(const wxString& wildCard)
368{
4e1901b7 369#ifdef __WXGTK24__
77f70672 370 if (!gtk_check_version(2,4,0))
9755e73b 371 {
77f70672
RR
372 m_wildCard = wildCard;
373 GtkFileChooser* chooser = GTK_FILE_CHOOSER(m_widget);
27b2dd53 374
77f70672
RR
375 // empty current filter list:
376 GSList* ifilters = gtk_file_chooser_list_filters(chooser);
377 GSList* filters = ifilters;
378 while (ifilters)
379 {
380 gtk_file_chooser_remove_filter(chooser,GTK_FILE_FILTER(ifilters->data));
381 ifilters = ifilters->next;
382 }
383 g_slist_free(filters);
27b2dd53 384
77f70672
RR
385 // parse filters
386 wxArrayString wildDescriptions, wildFilters;
387 if (!wxParseCommonDialogsFilter(m_wildCard, wildDescriptions, wildFilters))
388 {
389 wxFAIL_MSG( wxT("Wrong file type description") );
390 }
391 else
9755e73b 392 {
77f70672
RR
393 // add parsed to GtkChooser
394 for (size_t n = 0; n < wildFilters.GetCount(); n++)
9755e73b 395 {
77f70672
RR
396 GtkFileFilter* filter = gtk_file_filter_new();
397 gtk_file_filter_set_name(filter,wxGTK_CONV(wildDescriptions[n]));
398 wxString after = wildFilters[n];
399 do
400 {
401 wxString ext = after.BeforeFirst(wxT(';'));
402 gtk_file_filter_add_pattern(filter,wxGTK_CONV(ext));
403 if (after.Find(wxT(';')) == wxNOT_FOUND)
404 break;
405 after = after.AfterLast(wxT(';'));
406 }
407 while (!after.empty());
27b2dd53 408
77f70672
RR
409 gtk_file_chooser_add_filter(chooser, filter);
410 }
9755e73b
VS
411 }
412 }
77f70672 413 else
4e1901b7 414#endif
77f70672 415 wxGenericFileDialog::SetWildcard( wildCard );
9755e73b 416}
a3622daa 417
9755e73b
VS
418void wxFileDialog::SetFilterIndex(int filterIndex)
419{
4e1901b7 420#ifdef __WXGTK24__
77f70672 421 if (!gtk_check_version(2,4,0))
9755e73b 422 {
77f70672
RR
423 m_filterIndex = filterIndex;
424
425 GtkFileChooser *chooser = GTK_FILE_CHOOSER(m_widget);
426 GSList *fnode = gtk_file_chooser_list_filters(chooser);
427 GSList *filters = fnode;
428 int i = 0;
429 while (fnode)
9755e73b 430 {
77f70672
RR
431 if (i == filterIndex)
432 {
433 gtk_file_chooser_set_filter(chooser, GTK_FILE_FILTER(fnode->data));
434 m_filterIndex = i;
435 break;
436 }
437 i++;
438 fnode = fnode->next;
9755e73b 439 }
77f70672 440 g_slist_free(filters);
9755e73b 441 }
77f70672 442 else
4e1901b7 443#endif
77f70672 444 wxGenericFileDialog::SetFilterIndex( filterIndex );
4e1901b7
RR
445}
446
447void wxFileDialog::UpdateDialog()
448{
449#ifdef __WXGTK24__
450 // set currently selected directory to match the path:
27b2dd53 451 if (!m_dir.empty() && wxPathExists(m_dir))
4e1901b7
RR
452 {
453 // NB: This is important -- if we set directory only and not the path,
454 // then dialog will still remember old path set using previous
455 // call to gtk_chooser_set_filename. If the previous directory
456 // was a subdirectory of the directory we want to select now,
457 // the dialog would still contain directory selector controls
458 // for the subdirectory (with the parent directory selected),
459 // instead of showing only the parent directory as expected.
460 // This way, we force GtkFileChooser to really change the
461 // directory. Finally, it doesn't have to be done if filename
462 // is not empty because of the code that sets the filename below.
463 if (m_fileName.empty())
464 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(m_widget),
465 wxGTK_CONV(m_dir));
27b2dd53 466
4e1901b7
RR
467 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(m_widget),
468 wxGTK_CONV(m_dir));
469 }
27b2dd53 470
4e1901b7
RR
471 // if the user set only the directory (e.g. by calling SetDirectory)
472 // and not the default filename, then we don't want to set the filename:
473 if (!m_fileName.empty())
474 {
475 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(m_widget),
476 wxGTK_CONV(m_path));
27b2dd53 477
4e1901b7
RR
478 // pre-fill the filename when saving, too (there's no text entry
479 // control when opening a file, so it doesn't make sense to
480 // do this when opening files):
481 if (GetWindowStyle() & wxSAVE)
482 {
483 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(m_widget),
484 wxGTK_CONV(m_fileName));
485 }
486 }
487#endif
9755e73b 488}
3502e687 489
9755e73b
VS
490void wxFileDialog::UpdateFromDialog()
491{
4e1901b7 492#ifdef __WXGTK24__
9755e73b
VS
493 // update filterIndex
494 GSList *fnode = gtk_file_chooser_list_filters(GTK_FILE_CHOOSER(m_widget));
495 GSList *filters = fnode;
496 GtkFileFilter *current =
497 gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(m_widget));
27b2dd53 498
9755e73b
VS
499 int i = 0;
500 m_filterIndex = 0;
501 while (fnode)
502 {
503 if (fnode->data == (gpointer)current)
504 {
505 m_filterIndex = i;
506 break;
507 }
508 i++;
509 fnode = fnode->next;
510 }
511 g_slist_free(filters);
4e1901b7 512#endif
9755e73b 513}
3f6638b8 514
4e1901b7 515#endif // wxUSE_FILEDLG