1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/filedlg.cpp
3 // Purpose: native implementation of wxFileDialog
4 // Author: Robert Roebling, Zbigniew Zagorski
6 // Copyright: (c) 1998 Robert Roebling, 2004 Zbigniew Zagorski
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
11 #pragma implementation "filedlg.h"
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
19 #include "wx/filedlg.h"
22 #include "wx/filename.h"
23 #include "wx/msgdlg.h"
28 #include "wx/gtk/private.h"
30 //-----------------------------------------------------------------------------
32 //-----------------------------------------------------------------------------
34 extern void wxapp_install_idle_handler();
37 //-----------------------------------------------------------------------------
38 // "clicked" for OK-button
39 //-----------------------------------------------------------------------------
41 static void gtk_filedialog_ok_callback(GtkWidget
*widget
, wxFileDialog
*dialog
)
43 int style
= dialog
->GetStyle();
44 gchar
* text
= gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget
));
45 wxString
filename(wxGTK_CONV_BACK(text
));
47 if ((style
& wxSAVE
) && (style
& wxOVERWRITE_PROMPT
))
49 if (wxFileExists(filename
))
53 _("File '%s' already exists, do you really want to overwrite it?"),
56 wxMessageDialog
dlg(dialog
, msg
, _("Confirm"),
57 wxYES_NO
| wxICON_QUESTION
);
58 if (dlg
.ShowModal() != wxID_YES
)
62 else if ((style
& wxOPEN
) && ( style
& wxFILE_MUST_EXIST
))
64 if (!wxFileExists( filename
))
66 wxMessageDialog
dlg(dialog
,
67 _("Please choose an existing file."),
68 _("Error"), wxOK
| wxICON_ERROR
);
75 // change to the directory where the user went if asked
76 if (style
& wxCHANGE_DIR
)
79 wxSplitPath(filename
, &cwd
, NULL
, NULL
);
81 if (cwd
!= wxGetCwd())
83 wxSetWorkingDirectory(cwd
);
87 dialog
->SetPath(filename
);
88 dialog
->UpdateFromDialog();
90 wxCommandEvent
event(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_OK
);
91 event
.SetEventObject(dialog
);
92 dialog
->GetEventHandler()->ProcessEvent(event
);
95 //-----------------------------------------------------------------------------
96 // "clicked" for Cancel-button
97 //-----------------------------------------------------------------------------
99 static void gtk_filedialog_cancel_callback(GtkWidget
*WXUNUSED(w
),
100 wxFileDialog
*dialog
)
102 wxCommandEvent
event(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_CANCEL
);
103 event
.SetEventObject(dialog
);
104 dialog
->GetEventHandler()->ProcessEvent(event
);
107 static void gtk_filedialog_response_callback(GtkWidget
*w
,
109 wxFileDialog
*dialog
)
111 wxapp_install_idle_handler();
113 if (response
== GTK_RESPONSE_ACCEPT
)
114 gtk_filedialog_ok_callback(w
, dialog
);
115 else if (response
== GTK_RESPONSE_CANCEL
)
116 gtk_filedialog_cancel_callback(w
, dialog
);
119 gtk_filedialog_cancel_callback(w
, dialog
);
120 dialog
->m_destroyed_by_delete
= TRUE
;
125 //-----------------------------------------------------------------------------
127 //-----------------------------------------------------------------------------
129 IMPLEMENT_DYNAMIC_CLASS(wxFileDialog
,wxGenericFileDialog
)
131 BEGIN_EVENT_TABLE(wxFileDialog
,wxGenericFileDialog
)
132 EVT_BUTTON(wxID_OK
, wxFileDialog
::OnFakeOk
)
135 wxFileDialog
::wxFileDialog(wxWindow
*parent
, const wxString
& message
,
136 const wxString
& defaultDir
,
137 const wxString
& defaultFileName
,
138 const wxString
& wildCard
,
139 long style
, const wxPoint
& pos
)
140 : wxGenericFileDialog(parent
, message
, defaultDir
, defaultFileName
,
141 wildCard
, style
, pos
, true )
144 m_needParent
= FALSE
;
145 m_destroyed_by_delete
= FALSE
;
147 if (!PreCreation(parent
, pos
, wxDefaultSize
) ||
148 !CreateBase(parent
, wxID_ANY
, pos
, wxDefaultSize
, style
,
149 wxDefaultValidator
, wxT("filedialog")))
151 wxFAIL_MSG( wxT("wxFileDialog creation failed") );
155 bool multiple
= (style
& wxMULTIPLE
) == wxMULTIPLE
;
156 GtkFileChooserAction gtk_action
;
157 GtkWindow
* gtk_parent
= NULL
;
159 gtk_parent
= GTK_WINDOW(parent
->m_widget
);
162 if ((style
& wxSAVE
) == wxSAVE
)
164 gtk_action
= GTK_FILE_CHOOSER_ACTION_SAVE
;
165 ok_btn_stock
= GTK_STOCK_SAVE
;
169 gtk_action
= GTK_FILE_CHOOSER_ACTION_OPEN
;
170 ok_btn_stock
= GTK_STOCK_OPEN
;
172 m_widget
= gtk_file_chooser_dialog_new(
173 wxGTK_CONV(m_message
),
176 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
177 ok_btn_stock
, GTK_RESPONSE_ACCEPT
,
180 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(m_widget
), multiple
);
182 gtk_signal_connect(GTK_OBJECT(m_widget
),
184 GTK_SIGNAL_FUNC(gtk_filedialog_response_callback
),
188 if (!m_path
.empty() && m_path
.Last() != wxT('/'))
190 m_path
+= m_fileName
;
193 SetWildcard(wildCard
);
196 wxGenericFileDialog
::Create( parent
, message
, defaultDir
, defaultFileName
, wildCard
, style
, pos
);
200 wxFileDialog
::~wxFileDialog()
203 if (m_destroyed_by_delete
)
208 void wxFileDialog
::OnFakeOk( wxCommandEvent
&event
)
211 wxDialog
::OnOK( event
);
213 wxGenericFileDialog
::OnListOk( event
);
217 int wxFileDialog
::ShowModal()
220 return wxDialog
::ShowModal();
222 return wxGenericFileDialog
::ShowModal();
226 bool wxFileDialog
::Show( bool show
)
229 return wxDialog
::Show( show
);
231 return wxGenericFileDialog
::Show( show
);
235 void wxFileDialog
::GetFilenames(wxArrayString
& files
) const
239 for (size_t n
= 0; n
< files
.GetCount(); n
++ )
242 wxSplitPath(files
[n
], NULL
, &name
, &ext
);
251 wxGenericFileDialog
::GetFilenames( files
);
255 void wxFileDialog
::GetPaths(wxArrayString
& paths
) const
259 if (GetWindowStyle() & wxMULTIPLE
)
262 gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(m_widget
));
263 GSList
*gpaths
= gpathsi
;
266 wxString file
= wxGTK_CONV_BACK((gchar
*) gpathsi
->data
);
268 g_free(gpathsi
->data
);
269 gpathsi
= gpathsi
->next
;
272 g_slist_free(gpaths
);
276 paths
.Add(m_fileName
);
279 wxGenericFileDialog
::GetPaths( paths
);
283 void wxFileDialog
::SetMessage(const wxString
& message
)
289 wxGenericFileDialog
::SetMessage( message
);
293 void wxFileDialog
::SetPath(const wxString
& path
)
296 if (path
.empty()) return;
299 m_path
= fn
.GetFullPath();
300 m_dir
= fn
.GetPath();
301 m_fileName
= fn
.GetFullName();
304 wxGenericFileDialog
::SetPath( path
);
308 void wxFileDialog
::SetDirectory(const wxString
& dir
)
311 if (wxDirExists(dir
))
314 m_path
= wxFileName(m_dir
, m_fileName
).GetFullPath();
318 wxGenericFileDialog
::SetDirectory( dir
);
322 void wxFileDialog
::SetFilename(const wxString
& name
)
326 m_path
= wxFileName(m_dir
, m_fileName
).GetFullPath();
329 wxGenericFileDialog
::SetFilename( name
);
333 void wxFileDialog
::SetWildcard(const wxString
& wildCard
)
336 m_wildCard
= wildCard
;
338 GtkFileChooser
* chooser
= GTK_FILE_CHOOSER(m_widget
);
340 // empty current filter list:
341 GSList
* ifilters
= gtk_file_chooser_list_filters(chooser
);
342 GSList
* filters
= ifilters
;
345 gtk_file_chooser_remove_filter(chooser
,GTK_FILE_FILTER(ifilters
->data
));
346 ifilters
= ifilters
->next
;
348 g_slist_free(filters
);
351 wxArrayString wildDescriptions
, wildFilters
;
352 if (!wxParseCommonDialogsFilter(m_wildCard
, wildDescriptions
, wildFilters
))
354 wxFAIL_MSG( wxT("Wrong file type description") );
358 // add parsed to GtkChooser
359 for (size_t n
= 0; n
< wildFilters
.GetCount(); n
++)
361 GtkFileFilter
* filter
= gtk_file_filter_new();
362 gtk_file_filter_set_name(filter
,wxGTK_CONV(wildDescriptions
[n
]));
363 wxString after
= wildFilters
[n
];
366 wxString ext
= after
.BeforeFirst(wxT(';'));
367 gtk_file_filter_add_pattern(filter
,wxGTK_CONV(ext
));
368 if (after
.Find(wxT(';')) == wxNOT_FOUND
)
370 after
= after
.AfterLast(wxT(';'));
372 while (!after
.empty());
374 gtk_file_chooser_add_filter(chooser
, filter
);
378 wxGenericFileDialog
::SetWildcard( wildCard
);
382 void wxFileDialog
::SetFilterIndex(int filterIndex
)
385 m_filterIndex
= filterIndex
;
387 GtkFileChooser
*chooser
= GTK_FILE_CHOOSER(m_widget
);
388 GSList
*fnode
= gtk_file_chooser_list_filters(chooser
);
389 GSList
*filters
= fnode
;
393 if (i
== filterIndex
)
395 gtk_file_chooser_set_filter(chooser
, GTK_FILE_FILTER(fnode
->data
));
402 g_slist_free(filters
);
404 wxGenericFileDialog
::SetFilterIndex( filterIndex
);
408 void wxFileDialog
::UpdateDialog()
411 // set currently selected directory to match the path:
412 if (!m_dir
.empty() && wxDirExists(m_dir
))
414 // NB: This is important -- if we set directory only and not the path,
415 // then dialog will still remember old path set using previous
416 // call to gtk_chooser_set_filename. If the previous directory
417 // was a subdirectory of the directory we want to select now,
418 // the dialog would still contain directory selector controls
419 // for the subdirectory (with the parent directory selected),
420 // instead of showing only the parent directory as expected.
421 // This way, we force GtkFileChooser to really change the
422 // directory. Finally, it doesn't have to be done if filename
423 // is not empty because of the code that sets the filename below.
424 if (m_fileName
.empty())
425 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(m_widget
),
428 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(m_widget
),
432 // if the user set only the directory (e.g. by calling SetDirectory)
433 // and not the default filename, then we don't want to set the filename:
434 if (!m_fileName
.empty())
436 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(m_widget
),
439 // pre-fill the filename when saving, too (there's no text entry
440 // control when opening a file, so it doesn't make sense to
441 // do this when opening files):
442 if (GetWindowStyle() & wxSAVE
)
444 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(m_widget
),
445 wxGTK_CONV(m_fileName
));
451 void wxFileDialog
::UpdateFromDialog()
454 // update filterIndex
455 GSList
*fnode
= gtk_file_chooser_list_filters(GTK_FILE_CHOOSER(m_widget
));
456 GSList
*filters
= fnode
;
457 GtkFileFilter
*current
=
458 gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(m_widget
));
464 if (fnode
->data
== (gpointer
)current
)
472 g_slist_free(filters
);
476 #endif // wxUSE_FILEDLG