reverted, the problem is deeper than that
[wxWidgets.git] / src / gtk / filedlg.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/filedlg.cpp
3 // Purpose: native implementation of wxFileDialog
4 // Author: Robert Roebling, Zbigniew Zagorski
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling, 2004 Zbigniew Zagorski
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
11 #pragma implementation "filedlg.h"
12 #endif
13
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
16
17 #if wxUSE_FILEDLG && defined(__WXGTK24__)
18
19 #include "wx/filedlg.h"
20 #include "wx/utils.h"
21 #include "wx/intl.h"
22 #include "wx/filename.h"
23 #include "wx/msgdlg.h"
24
25 #include <gtk/gtk.h>
26 #include "wx/gtk/private.h"
27
28 //-----------------------------------------------------------------------------
29 // idle system
30 //-----------------------------------------------------------------------------
31
32 extern void wxapp_install_idle_handler();
33 extern bool g_isIdle;
34
35 //-----------------------------------------------------------------------------
36 // "clicked" for OK-button
37 //-----------------------------------------------------------------------------
38
39 static void gtk_filedialog_ok_callback(GtkWidget *widget, wxFileDialog *dialog)
40 {
41 int style = dialog->GetStyle();
42 gchar* text = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget));
43 wxString filename(wxGTK_CONV_BACK(text));
44
45 if ((style & wxSAVE) && (style & wxOVERWRITE_PROMPT))
46 {
47 if (wxFileExists(filename))
48 {
49 wxString msg;
50 msg.Printf(
51 _("File '%s' already exists, do you really want to overwrite it?"),
52 filename.c_str());
53
54 wxMessageDialog dlg(dialog, msg, _("Confirm"),
55 wxYES_NO | wxICON_QUESTION);
56 if (dlg.ShowModal() != wxID_YES)
57 return;
58 }
59 }
60 else if ((style & wxOPEN) && ( style & wxFILE_MUST_EXIST))
61 {
62 if (!wxFileExists( filename ))
63 {
64 wxMessageDialog dlg(dialog,
65 _("Please choose an existing file."),
66 _("Error"), wxOK | wxICON_ERROR);
67 dlg.ShowModal();
68
69 return;
70 }
71 }
72
73 // change to the directory where the user went if asked
74 if (style & wxCHANGE_DIR)
75 {
76 wxString cwd;
77 wxSplitPath(filename, &cwd, NULL, NULL);
78
79 if (cwd != wxGetCwd())
80 {
81 wxSetWorkingDirectory(cwd);
82 }
83 }
84
85 dialog->SetPath(filename);
86 dialog->UpdateFromDialog();
87
88 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK);
89 event.SetEventObject(dialog);
90 dialog->GetEventHandler()->ProcessEvent(event);
91 }
92
93 //-----------------------------------------------------------------------------
94 // "clicked" for Cancel-button
95 //-----------------------------------------------------------------------------
96
97 static void gtk_filedialog_cancel_callback(GtkWidget *WXUNUSED(w),
98 wxFileDialog *dialog)
99 {
100 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
101 event.SetEventObject(dialog);
102 dialog->GetEventHandler()->ProcessEvent(event);
103 }
104
105 static void gtk_filedialog_response_callback(GtkWidget *w,
106 int response,
107 wxFileDialog *dialog)
108 {
109 wxapp_install_idle_handler();
110
111 if (response == GTK_RESPONSE_CANCEL)
112 gtk_filedialog_cancel_callback(w, dialog);
113 else
114 gtk_filedialog_ok_callback(w, dialog);
115 }
116
117 //-----------------------------------------------------------------------------
118 // wxFileDialog
119 //-----------------------------------------------------------------------------
120
121 IMPLEMENT_DYNAMIC_CLASS(wxFileDialog,wxFileDialogBase)
122
123 wxFileDialog::wxFileDialog(wxWindow *parent, const wxString& message,
124 const wxString& defaultDir,
125 const wxString& defaultFileName,
126 const wxString& wildCard,
127 long style, const wxPoint& pos)
128 : wxFileDialogBase(parent, message, defaultDir, defaultFileName,
129 wildCard, style, pos)
130 {
131 m_needParent = FALSE;
132
133 if (!PreCreation(parent, pos, wxDefaultSize) ||
134 !CreateBase(parent, wxID_ANY, pos, wxDefaultSize, style,
135 wxDefaultValidator, wxT("filedialog")))
136 {
137 wxFAIL_MSG( wxT("wxFileDialog creation failed") );
138 return;
139 }
140
141 bool multiple = (style & wxMULTIPLE) == wxMULTIPLE;
142 GtkFileChooserAction gtk_action;
143 GtkWindow* gtk_parent = NULL;
144 if (parent)
145 gtk_parent = GTK_WINDOW(parent->m_widget);
146
147 gchar* ok_btn_stock;
148 if ((style & wxSAVE) == wxSAVE)
149 {
150 gtk_action = GTK_FILE_CHOOSER_ACTION_SAVE;
151 ok_btn_stock = GTK_STOCK_SAVE;
152 }
153 else
154 {
155 gtk_action = GTK_FILE_CHOOSER_ACTION_OPEN;
156 ok_btn_stock = GTK_STOCK_OPEN;
157 }
158 m_widget = gtk_file_chooser_dialog_new(
159 wxGTK_CONV(m_message),
160 gtk_parent,
161 gtk_action,
162 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
163 ok_btn_stock, GTK_RESPONSE_ACCEPT,
164 NULL);
165
166 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(m_widget), multiple);
167
168 gtk_signal_connect(GTK_OBJECT(m_widget),
169 "response",
170 GTK_SIGNAL_FUNC(gtk_filedialog_response_callback),
171 (gpointer*)this);
172
173 m_path = m_dir;
174 if (!m_path.empty() && m_path.Last() != wxT('/'))
175 m_path += wxT('/');
176 m_path += m_fileName;
177 SetPath(m_path);
178
179 SetWildcard(wildCard);
180 SetFilterIndex(0);
181 }
182
183 wxFileDialog::~wxFileDialog()
184 {
185 m_widget = NULL;
186 }
187
188 void wxFileDialog::GetFilenames(wxArrayString& files) const
189 {
190 GetPaths(files);
191 for (size_t n = 0; n < files.GetCount(); n++ )
192 {
193 wxString name,ext;
194 wxSplitPath(files[n], NULL, &name, &ext);
195 if (!ext.IsEmpty())
196 {
197 name += wxT(".");
198 name += ext;
199 }
200 files[n] = name;
201 }
202 }
203
204 void wxFileDialog::GetPaths(wxArrayString& paths) const
205 {
206 paths.Empty();
207 if (GetWindowStyle() & wxMULTIPLE)
208 {
209 GSList *gpathsi =
210 gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(m_widget));
211 GSList *gpaths = gpathsi;
212 while (gpathsi)
213 {
214 wxString file = wxGTK_CONV_BACK((gchar*) gpathsi->data);
215 paths.Add(file);
216 g_free(gpathsi->data);
217 gpathsi = gpathsi->next;
218 }
219 if (gpaths)
220 g_slist_free(gpaths);
221 }
222 else
223 {
224 paths.Add(m_fileName);
225 }
226 }
227
228 void wxFileDialog::SetMessage(const wxString& message)
229 {
230 m_message = message;
231 SetTitle(message);
232 }
233
234 void wxFileDialog::SetPath(const wxString& path)
235 {
236 if (path.empty()) return;
237
238 wxFileName fn(path);
239 m_path = fn.GetFullPath();
240 m_dir = fn.GetPath();
241 m_fileName = fn.GetFullName();
242
243 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(m_widget),
244 wxGTK_CONV(m_dir));
245
246 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(m_widget),
247 wxGTK_CONV(m_path));
248
249 // pre-fill the filename when saving, too (there's no text entry
250 // control when opening a file, so it doesn't make sense to
251 // do this in when opening files):
252 if (GetWindowStyle() & wxSAVE)
253 {
254 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(m_widget),
255 wxGTK_CONV(m_fileName));
256 }
257 }
258
259 void wxFileDialog::SetDirectory(const wxString& dir)
260 {
261 if (wxDirExists(dir))
262 {
263 m_dir = dir;
264 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(m_widget),
265 wxGTK_CONV(m_dir));
266 wxFileName fn(m_dir,m_fileName);
267 m_path = fn.GetFullPath();
268 }
269 }
270
271 void wxFileDialog::SetFilename(const wxString& name)
272 {
273 m_fileName = name;
274 wxFileName fn(m_dir,m_fileName);
275 m_path = fn.GetFullPath();
276
277 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(m_widget),
278 wxGTK_CONV(m_path));
279
280 // pre-fill the filename when saving, too (there's no text entry
281 // control when opening a file, so it doesn't make sense to
282 // do this in when opening files):
283 if (GetWindowStyle() & wxSAVE)
284 {
285 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(m_widget),
286 wxGTK_CONV(m_fileName));
287 }
288 }
289
290 void wxFileDialog::SetWildcard(const wxString& wildCard)
291 {
292 m_wildCard = wildCard;
293
294 GtkFileChooser* chooser = GTK_FILE_CHOOSER(m_widget);
295
296 // empty current filter list:
297 GSList* ifilters = gtk_file_chooser_list_filters(chooser);
298 GSList* filters = ifilters;
299 while (ifilters)
300 {
301 gtk_file_chooser_remove_filter(chooser,GTK_FILE_FILTER(ifilters->data));
302 ifilters = ifilters->next;
303 }
304 g_slist_free(filters);
305
306 // parse filters
307 wxArrayString wildDescriptions, wildFilters;
308 if (!wxParseCommonDialogsFilter(m_wildCard, wildDescriptions, wildFilters))
309 {
310 wxFAIL_MSG( wxT("Wrong file type description") );
311 }
312 else
313 {
314 // add parsed to GtkChooser
315 for (size_t n = 0; n < wildFilters.GetCount(); n++)
316 {
317 GtkFileFilter* filter = gtk_file_filter_new();
318 gtk_file_filter_set_name(filter,wxGTK_CONV(wildDescriptions[n]));
319 wxString after = wildFilters[n];
320 do
321 {
322 wxString ext = after.BeforeFirst(wxT(';'));
323 gtk_file_filter_add_pattern(filter,wxGTK_CONV(ext));
324 if (after.Find(wxT(';')) == wxNOT_FOUND)
325 break;
326 after = after.AfterLast(wxT(';'));
327 }
328 while (!after.empty());
329
330 gtk_file_chooser_add_filter(chooser, filter);
331 }
332 }
333 }
334
335 void wxFileDialog::SetFilterIndex(int filterIndex)
336 {
337 m_filterIndex = filterIndex;
338
339 GtkFileChooser *chooser = GTK_FILE_CHOOSER(m_widget);
340 GSList *fnode = gtk_file_chooser_list_filters(chooser);
341 GSList *filters = fnode;
342 int i = 0;
343 while (fnode)
344 {
345 if (i == filterIndex)
346 {
347 gtk_file_chooser_set_filter(chooser, GTK_FILE_FILTER(fnode->data));
348 m_filterIndex = i;
349 break;
350 }
351 i++;
352 fnode = fnode->next;
353 }
354 g_slist_free(filters);
355 }
356
357 void wxFileDialog::UpdateFromDialog()
358 {
359 // update filterIndex
360 GSList *fnode = gtk_file_chooser_list_filters(GTK_FILE_CHOOSER(m_widget));
361 GSList *filters = fnode;
362 GtkFileFilter *current =
363 gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(m_widget));
364
365 int i = 0;
366 m_filterIndex = 0;
367 while (fnode)
368 {
369 if (fnode->data == (gpointer)current)
370 {
371 m_filterIndex = i;
372 break;
373 }
374 i++;
375 fnode = fnode->next;
376 }
377 g_slist_free(filters);
378 }
379
380 #endif // wxUSE_FILEDLG && defined(__WXGTK24__)