.cvsignores added.
[dia.git] / app / filedlg.c
blob44912639ab2754a65db09d533643563520cb398c
1 /* Dia -- a diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * filedlg.c: some dialogs for saving/loading/exporting files.
5 * Copyright (C) 1999 James Henstridge
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #include <config.h>
24 #include "filedlg.h"
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <string.h>
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31 #include <gtk/gtk.h>
32 #include "intl.h"
33 #include "filter.h"
34 #include "dia_dirs.h"
35 #include "persistence.h"
36 #include "display.h"
37 #include "message.h"
38 #include "layer_dialog.h"
39 #include "load_save.h"
40 #include "preferences.h"
41 #include "interface.h"
43 static GtkWidget *opendlg = NULL;
44 static GtkWidget *savedlg = NULL;
45 static GtkWidget *exportdlg = NULL;
47 static void
48 toggle_compress_callback(GtkWidget *widget)
50 /* Changes prefs exactly when the user toggles the setting, i.e.
51 * the setting really remembers what the user chose last time, but
52 * lets diagrams of the opposite kind stay that way unless the user
53 * intervenes.
55 prefs.new_diagram.compress_save =
56 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
59 /**
60 * Given an import filter index and optionally a filename for fallback
61 * return the import filter to use
63 static DiaImportFilter *
64 ifilter_by_index (int index, const char* filename)
66 DiaImportFilter *ifilter = NULL;
68 if (index >= 0)
69 ifilter = g_list_nth_data (filter_get_import_filters(), index);
70 else if (filename) /* fallback, should not happen */
71 ifilter = filter_guess_import_filter(filename);
73 return ifilter;
76 typedef void* (* FilterGuessFunc) (const gchar* filename);
78 /**
79 * Respond to the file chooser filter facility, that is match
80 * the extension of a given filename to the selected filter
82 static gboolean
83 matching_extensions_filter (const GtkFileFilterInfo* fi,
84 gpointer data)
86 FilterGuessFunc guess_func = (FilterGuessFunc)data;
88 g_assert (guess_func);
90 if (!fi->filename)
91 return 0; /* filter it, IMO should not happen --hb */
93 if (guess_func (fi->filename))
94 return 1;
96 return 0;
99 /**
100 * React on the diagram::removed signal by destroying the dialog
102 * This function isn't used cause it conflicts with the pattern introduced:
103 * instead of destroying the dialog with the diagram, the dialog is keeping
104 * a refernce to it. As a result we could access the diagram even when the
105 * display of it is gone ...
107 #if 0
108 static void
109 diagram_removed (Diagram* dia, GtkWidget* dialog)
111 g_return_if_fail (DIA_IS_DIAGRAM (dia));
112 g_return_if_fail (GTK_IS_WIDGET (dialog));
114 gtk_widget_destroy (dialog);
116 #endif
119 * Create the combobox menu to select Import Filter options
121 static GtkWidget *
122 create_open_menu(void)
124 GtkWidget *menu;
125 GList *tmp;
128 menu = gtk_combo_box_new_text ();
129 gtk_combo_box_append_text(GTK_COMBO_BOX(menu), _("By extension"));
131 for (tmp = filter_get_import_filters(); tmp != NULL; tmp = tmp->next) {
132 DiaImportFilter *ifilter = tmp->data;
133 gchar *filter_label;
135 if (!ifilter)
136 continue;
137 filter_label = filter_get_import_filter_label(ifilter);
138 gtk_combo_box_append_text (GTK_COMBO_BOX(menu), filter_label);
139 g_free(filter_label);
141 return menu;
145 * Respond to the user finishing the Save Dialog either accept or cancel/destroy
147 static void
148 file_open_response_callback(GtkWidget *fs,
149 gint response,
150 gpointer user_data)
152 const char *filename;
153 Diagram *diagram = NULL;
155 if (response == GTK_RESPONSE_ACCEPT) {
156 gint index = gtk_combo_box_get_active (GTK_COMBO_BOX(user_data));
158 if (index >= 0) /* remember it */
159 persistence_set_integer ("import-filter", index);
160 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs));
162 diagram = diagram_load(filename, ifilter_by_index (index - 1, filename));
164 if (diagram != NULL) {
165 diagram_update_extents(diagram);
166 layer_dialog_set_diagram(diagram);
168 if (diagram->displays != NULL) {
169 GSList *displays = diagram->displays;
170 GSList *displays_head = displays;
171 diagram->displays = NULL;
172 for (; displays != NULL; displays = g_slist_next(displays)) {
173 DDisplay *loaded_display = (DDisplay *)displays->data;
174 copy_display(loaded_display);
175 g_free(loaded_display);
177 g_slist_free(displays_head);
178 } else {
179 new_display(diagram);
183 gtk_widget_destroy(opendlg);
187 * Handle menu click File/Open
189 * This is either with or without diagram
191 void
192 file_open_callback(gpointer data, guint action, GtkWidget *widget)
194 if (!opendlg) {
195 DDisplay *ddisp;
196 Diagram *dia = NULL;
197 GtkWindow *parent_window;
198 gchar *filename = NULL;
200 /* FIXME: we should not use ddisp_active but instead get the current diagram
201 * from caller. Thus we could offer the option to "load into" if invoked by
202 * <Display/File/Open. It wouldn't make any sense if invoked by
203 * <Toolbox>/File/Open ...
205 ddisp = ddisplay_active();
206 if (ddisp) {
207 dia = ddisp->diagram;
208 parent_window = GTK_WINDOW(ddisp->shell);
209 } else {
210 parent_window = GTK_WINDOW(interface_get_toolbox_shell());
212 persistence_register_integer ("import-filter", 0);
213 opendlg = gtk_file_chooser_dialog_new_with_backend(_("Open Diagram"), parent_window,
214 GTK_FILE_CHOOSER_ACTION_OPEN,
215 "default", /* default, not gnome-vfs */
216 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
217 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
218 NULL);
219 gtk_dialog_set_default_response(GTK_DIALOG(opendlg), GTK_RESPONSE_ACCEPT);
220 gtk_window_set_role(GTK_WINDOW(opendlg), "open_diagram");
221 gtk_window_set_position(GTK_WINDOW(opendlg), GTK_WIN_POS_MOUSE);
222 if (dia && dia->filename)
223 filename = g_filename_from_utf8(dia->filename, -1, NULL, NULL, NULL);
224 if (filename != NULL) {
225 char* fnabs = dia_get_absolute_filename (filename);
226 if (fnabs)
227 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(opendlg), fnabs);
228 g_free(fnabs);
229 g_free(filename);
231 g_signal_connect(GTK_OBJECT(opendlg), "destroy",
232 G_CALLBACK(gtk_widget_destroyed), &opendlg);
233 } else {
234 gtk_widget_set_sensitive(opendlg, TRUE);
235 if (GTK_WIDGET_VISIBLE(opendlg))
236 return;
238 if (!gtk_file_chooser_get_extra_widget(GTK_FILE_CHOOSER(opendlg))) {
239 GtkWidget *hbox, *label, *omenu, *options;
240 GtkFileFilter* filter;
242 options = gtk_frame_new(_("Open Options"));
243 gtk_frame_set_shadow_type(GTK_FRAME(options), GTK_SHADOW_ETCHED_IN);
245 hbox = gtk_hbox_new(FALSE, 1);
246 gtk_container_set_border_width(GTK_CONTAINER(hbox), 5);
247 gtk_container_add(GTK_CONTAINER(options), hbox);
248 gtk_widget_show(hbox);
250 label = gtk_label_new (_("Determine file type:"));
251 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
252 gtk_widget_show (label);
254 omenu = create_open_menu();
255 gtk_box_pack_start(GTK_BOX(hbox), omenu, TRUE, TRUE, 0);
256 gtk_widget_show(omenu);
258 gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(opendlg),
259 options);
261 gtk_widget_show(options);
262 g_signal_connect(GTK_OBJECT(opendlg), "response",
263 G_CALLBACK(file_open_response_callback), omenu);
264 /* set up file filters */
265 filter = gtk_file_filter_new ();
266 gtk_file_filter_set_name (filter, _("All Files"));
267 gtk_file_filter_add_pattern (filter, "*");
268 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (opendlg), filter);
269 /* match the other selections extension */
270 filter = gtk_file_filter_new ();
271 gtk_file_filter_set_name (filter, _("Supported Formats"));
272 gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_FILENAME,
273 matching_extensions_filter, filter_guess_import_filter, NULL);
274 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (opendlg), filter);
276 /* candidate for user prefs */
277 gtk_combo_box_set_active (GTK_COMBO_BOX (omenu), persistence_get_integer ("import-filter"));
280 gtk_widget_show(opendlg);
284 * Respond to a button press (also destroy) in the save as dialog.
286 static void
287 file_save_as_response_callback(GtkWidget *fs,
288 gint response,
289 gpointer user_data)
291 const char *filename;
292 Diagram *dia;
293 struct stat stat_struct;
295 if (response == GTK_RESPONSE_ACCEPT) {
296 dia = gtk_object_get_user_data(GTK_OBJECT(fs));
298 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs));
300 if (stat(filename, &stat_struct) == 0) {
301 GtkWidget *dialog = NULL;
302 char *utf8filename = NULL;
303 if (!g_utf8_validate(filename, -1, NULL)) {
304 utf8filename = g_filename_to_utf8(filename, -1, NULL, NULL, NULL);
305 if (utf8filename == NULL) {
306 message_warning(_("Some characters in the filename are neither UTF-8\n"
307 "nor your local encoding.\nSome things will break."));
310 if (utf8filename == NULL) utf8filename = g_strdup(filename);
313 dialog = gtk_message_dialog_new (GTK_WINDOW(fs),
314 GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION,
315 GTK_BUTTONS_YES_NO,
316 _("File already exists"));
317 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
318 _("The file '%s' already exists.\n"
319 "Do you want to overwrite it?"), utf8filename);
320 g_free(utf8filename);
321 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES);
323 if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_YES) {
324 /* don't hide/destroy the dialog, but simply go back to it */
325 gtk_window_present (GTK_WINDOW (fs));
326 gtk_widget_destroy(dialog);
327 return;
329 gtk_widget_destroy(dialog);
332 dia->data->is_compressed = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(user_data));
334 diagram_update_extents(dia);
336 diagram_set_filename(dia, filename);
337 diagram_save(dia, filename);
339 /* if we have our own reference, drop it before destroy */
340 if ((dia = gtk_object_get_user_data(GTK_OBJECT(fs))) != NULL) {
341 gtk_object_set_user_data(GTK_OBJECT(fs), NULL);
342 g_object_unref (dia);
344 gtk_widget_destroy(GTK_WIDGET(fs));
348 * Respond to the File/Save As.. menu
350 * We have only one file save dialog at a time. So if the dialog alread exists
351 * and the user tries to Save as once more only the diagram refernced will
352 * change. Maybe we should also indicate the refernced diagram in the dialog.
354 void
355 file_save_as_callback(gpointer data, guint action, GtkWidget *widget)
357 DDisplay *ddisp;
358 Diagram *dia;
359 gchar *filename = NULL;
361 ddisp = ddisplay_active();
362 if (!ddisp) return;
363 dia = ddisp->diagram;
365 if (!savedlg) {
366 GtkWidget *compressbutton;
368 savedlg = gtk_file_chooser_dialog_new_with_backend(_("Save Diagram"),
369 GTK_WINDOW(ddisp->shell),
370 GTK_FILE_CHOOSER_ACTION_SAVE,
371 "gtk+", /* default, not gnome-vfs */
372 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
373 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
374 NULL);
375 gtk_dialog_set_default_response(GTK_DIALOG(savedlg), GTK_RESPONSE_ACCEPT);
376 gtk_window_set_role(GTK_WINDOW(savedlg), "save_diagram");
377 gtk_window_set_position(GTK_WINDOW(savedlg), GTK_WIN_POS_MOUSE);
378 /* Need better way to make it a reasonable size. Isn't there some*/
379 /* standard look for them (or is that just Gnome?)*/
380 compressbutton = gtk_check_button_new_with_label(_("Compress diagram files"));
381 gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(savedlg),
382 compressbutton);
383 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(compressbutton),
384 dia->data->is_compressed);
385 g_signal_connect(G_OBJECT(compressbutton), "toggled",
386 G_CALLBACK(toggle_compress_callback), NULL);
387 gtk_widget_show(compressbutton);
388 gtk_tooltips_set_tip(tool_tips, compressbutton,
389 _("Compression reduces file size to less than 1/10th "
390 "size and speeds up loading and saving. Some text "
391 "programs cannot manipulate compressed files."), NULL);
392 g_signal_connect (GTK_FILE_CHOOSER(savedlg),
393 "response", G_CALLBACK(file_save_as_response_callback), compressbutton);
394 g_signal_connect(GTK_OBJECT(savedlg), "destroy",
395 G_CALLBACK(gtk_widget_destroyed), &savedlg);
396 } else {
397 GtkWidget *compressbutton = gtk_file_chooser_get_extra_widget(GTK_FILE_CHOOSER(savedlg));
398 gtk_widget_set_sensitive(savedlg, TRUE);
399 g_signal_handlers_block_by_func(G_OBJECT(compressbutton), toggle_compress_callback, NULL);
400 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(compressbutton),
401 dia->data->is_compressed);
402 g_signal_handlers_unblock_by_func(G_OBJECT(compressbutton), toggle_compress_callback, NULL);
403 if (gtk_object_get_user_data(GTK_OBJECT(savedlg)) != NULL)
404 g_object_unref(gtk_object_get_user_data(GTK_OBJECT(savedlg)));
405 if (GTK_WIDGET_VISIBLE(savedlg)) {
406 /* keep a refernce to the diagram */
407 g_object_ref(dia);
408 gtk_object_set_user_data(GTK_OBJECT(savedlg), dia);
409 gtk_window_present (GTK_WINDOW(savedlg));
410 return;
413 if (dia && dia->filename)
414 filename = g_filename_from_utf8(dia->filename, -1, NULL, NULL, NULL);
415 if (filename != NULL) {
416 char* fnabs = dia_get_absolute_filename (filename);
417 if (fnabs) {
418 gchar *base = g_path_get_basename(fnabs);
419 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(savedlg), fnabs);
420 /* FileChooser api insist on exiting files for set_filename */
421 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(savedlg), base);
422 g_free(base);
424 g_free(fnabs);
425 g_free(filename);
427 g_object_ref(dia);
428 gtk_object_set_user_data(GTK_OBJECT(savedlg), dia);
430 gtk_widget_show(savedlg);
434 * Respond to the File/Save menu entry.
436 * Delegates to Save As if there is no filename set yet.
438 void
439 file_save_callback(gpointer data, guint action, GtkWidget *widget)
441 Diagram *diagram;
443 diagram = ddisplay_active_diagram();
444 if (!diagram) return;
446 if (diagram->unsaved) {
447 file_save_as_callback(data, action, widget);
448 } else {
449 gchar *filename = g_filename_from_utf8(diagram->filename, -1, NULL, NULL, NULL);
450 diagram_update_extents(diagram);
451 diagram_save(diagram, filename);
452 g_free (filename);
457 * Given an export filter index and optionally a filename for fallback
458 * return the export filter to use
460 static DiaExportFilter *
461 efilter_by_index (int index, const char* filename)
463 DiaExportFilter *efilter = NULL;
465 if (index >= 0)
466 efilter = g_list_nth_data (filter_get_export_filters(), index);
467 else if (filename) /* fallback, should not happen */
468 efilter = filter_guess_export_filter(filename);
470 return efilter;
474 * Adapt the filename to the export filter selection
476 static void
477 export_set_extension(GtkWidget *widget)
479 int index = gtk_combo_box_get_active (GTK_COMBO_BOX(widget)) - 1; /* Ignore "By Extension" */
480 DiaExportFilter *efilter = efilter_by_index (index, NULL);
481 GString *s;
482 const gchar *text = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(exportdlg));
483 const gchar *last_dot = text ? strrchr(text, '.') : NULL;
484 gchar *basename = NULL;
486 if (!efilter || last_dot == text || text[0] == '\0' ||
487 efilter->extensions[0] == NULL)
488 return;
489 basename = g_path_get_basename (text);
490 last_dot = strrchr(basename, '.');
491 s = g_string_new(basename);
492 if (last_dot)
493 g_string_truncate(s, last_dot-basename);
494 g_string_append(s, ".");
495 g_string_append(s, efilter->extensions[0]);
496 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(exportdlg), s->str);
497 g_string_free (s, TRUE);
498 g_free (basename);
502 * Create a new "option menu" for the export options
504 static GtkWidget *
505 create_export_menu(void)
507 GtkWidget *menu;
508 GList *tmp;
510 menu = gtk_combo_box_new_text ();
511 gtk_combo_box_append_text(GTK_COMBO_BOX(menu), _("By extension"));
513 for (tmp = filter_get_export_filters(); tmp != NULL; tmp = tmp->next) {
514 DiaExportFilter *ef = tmp->data;
515 gchar *filter_label;
517 if (!ef)
518 continue;
519 filter_label = filter_get_export_filter_label(ef);
520 gtk_combo_box_append_text (GTK_COMBO_BOX(menu), filter_label);
521 g_free(filter_label);
523 g_signal_connect(GTK_OBJECT(menu), "changed",
524 G_CALLBACK(export_set_extension), NULL);
525 return menu;
529 * A button hit in the Export Dialog
531 static void
532 file_export_response_callback(GtkWidget *fs,
533 gint response,
534 gpointer user_data)
536 const char *filename;
537 Diagram *dia;
538 DiaExportFilter *ef;
539 struct stat statbuf;
541 dia = gtk_object_get_user_data(GTK_OBJECT(fs));
542 g_assert (dia);
544 if (response == GTK_RESPONSE_ACCEPT) {
545 gint index;
547 diagram_update_extents(dia);
549 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs));
551 if (stat(filename, &statbuf) == 0) {
552 GtkWidget *dialog = NULL;
554 dialog = gtk_message_dialog_new (GTK_WINDOW(fs),
555 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
556 GTK_MESSAGE_QUESTION,
557 GTK_BUTTONS_YES_NO,
558 _("File already exists"));
559 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
560 _("The file '%s' already exists.\n"
561 "Do you want to overwrite it?"), dia_message_filename(filename));
562 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES);
564 if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_YES) {
565 /* if not overwrite allow to select another filename */
566 gtk_widget_destroy(dialog);
567 return;
569 gtk_widget_destroy(dialog);
572 index = gtk_combo_box_get_active (GTK_COMBO_BOX(user_data));
573 if (index >= 0)
574 persistence_set_integer ("export-filter", index);
575 ef = efilter_by_index (index - 1, filename);
576 if (!ef)
577 ef = filter_guess_export_filter(filename);
578 if (ef) {
579 g_object_ref(dia->data);
580 ef->export_func(dia->data, filename, dia->filename, ef->user_data);
581 g_object_unref(dia->data);
582 } else
583 message_error(_("Could not determine which export filter\n"
584 "to use to save '%s'"), dia_message_filename(filename));
586 g_object_unref (dia); /* drop our diagram reference */
587 gtk_widget_destroy(exportdlg);
591 * React to <Display>/File/Export
593 void
594 file_export_callback(gpointer data, guint action, GtkWidget *widget)
596 DDisplay *ddisp;
597 Diagram *dia;
598 gchar *filename = NULL;
600 ddisp = ddisplay_active();
601 if (!ddisp) return;
602 dia = ddisp->diagram;
604 if (!exportdlg) {
605 persistence_register_integer ("export-filter", 0);
606 exportdlg = gtk_file_chooser_dialog_new_with_backend(_("Export Diagram"),
607 GTK_WINDOW(ddisp->shell),
608 GTK_FILE_CHOOSER_ACTION_SAVE,
609 "gtk+", /* default, not gnome-vfs */
610 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
611 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
612 NULL);
613 gtk_dialog_set_default_response(GTK_DIALOG(exportdlg), GTK_RESPONSE_ACCEPT);
614 gtk_window_set_role(GTK_WINDOW(exportdlg), "export_diagram");
615 gtk_window_set_position(GTK_WINDOW(exportdlg), GTK_WIN_POS_MOUSE);
616 g_signal_connect(GTK_OBJECT(exportdlg), "destroy",
617 G_CALLBACK(gtk_widget_destroyed), &exportdlg);
619 if (!gtk_file_chooser_get_extra_widget(GTK_FILE_CHOOSER(exportdlg))) {
620 GtkWidget *hbox, *label, *omenu, *options;
621 GtkFileFilter* filter;
623 options = gtk_frame_new(_("Export Options"));
624 gtk_frame_set_shadow_type(GTK_FRAME(options), GTK_SHADOW_ETCHED_IN);
626 hbox = gtk_hbox_new(FALSE, 1);
627 gtk_container_set_border_width(GTK_CONTAINER(hbox), 5);
628 gtk_container_add(GTK_CONTAINER(options), hbox);
629 gtk_widget_show(hbox);
631 label = gtk_label_new (_("Determine file type:"));
632 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
633 gtk_widget_show (label);
635 omenu = create_export_menu();
636 gtk_box_pack_start(GTK_BOX(hbox), omenu, TRUE, TRUE, 0);
637 gtk_widget_show(omenu);
638 g_object_set_data(G_OBJECT(exportdlg), "export-menu", omenu);
640 gtk_widget_show(options);
641 gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(exportdlg), options);
642 /* set up file filters */
643 filter = gtk_file_filter_new ();
644 gtk_file_filter_set_name (filter, _("All Files"));
645 gtk_file_filter_add_pattern (filter, "*");
646 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (exportdlg), filter);
647 /* match the other selections extension */
648 filter = gtk_file_filter_new ();
649 gtk_file_filter_set_name (filter, _("Supported Formats"));
650 gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_FILENAME,
651 matching_extensions_filter, filter_guess_export_filter, NULL);
652 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (exportdlg), filter);
654 gtk_combo_box_set_active (GTK_COMBO_BOX (omenu), persistence_get_integer ("export-filter"));
656 g_signal_connect(GTK_FILE_CHOOSER(exportdlg),
657 "response", G_CALLBACK(file_export_response_callback), omenu);
659 if (gtk_object_get_user_data(GTK_OBJECT(exportdlg)))
660 g_object_unref (gtk_object_get_user_data(GTK_OBJECT(exportdlg)));
661 g_object_ref(dia);
662 gtk_object_set_user_data(GTK_OBJECT(exportdlg), dia);
663 gtk_widget_set_sensitive(exportdlg, TRUE);
665 if (dia && dia->filename)
666 filename = g_filename_from_utf8(dia->filename, -1, NULL, NULL, NULL);
667 if (filename != NULL) {
668 char* fnabs = dia_get_absolute_filename (filename);
669 if (fnabs) {
670 char *folder = g_path_get_dirname (fnabs);
671 char *basename = g_path_get_basename (fnabs);
672 /* can't use gtk_file_chooser_set_filename for various reasons, see e.g. bug #305850 */
673 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER(exportdlg), folder);
674 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER(exportdlg), basename);
675 g_free (folder);
676 g_free (basename);
678 g_free(fnabs);
679 g_free(filename);
681 export_set_extension(GTK_WIDGET(g_object_get_data(G_OBJECT(exportdlg),
682 "export-menu")));
684 gtk_widget_show(exportdlg);