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.
25 #include <sys/types.h>
36 #include "layer_dialog.h"
37 #include "load_save.h"
38 #include "preferences.h"
39 #include "interface.h"
41 static GtkWidget
*opendlg
= NULL
, *open_options
= NULL
, *open_omenu
= NULL
;
42 static GtkWidget
*savedlg
= NULL
;
43 static GtkWidget
*exportdlg
= NULL
, *export_options
= NULL
, *export_omenu
=NULL
;
44 static GtkWidget
*compressbutton
= NULL
;
47 file_dialog_hide (GtkWidget
*filesel
)
51 gtk_widget_hide (filesel
);
52 if ((user_data
= gtk_object_get_user_data(GTK_OBJECT(filesel
))) != NULL
) {
53 diagram_remove_related_dialog(user_data
, filesel
);
55 g_object_unref(G_OBJECT(user_data
));
56 gtk_object_set_user_data(GTK_OBJECT(filesel
), NULL
);
59 menus_set_sensitive ("<Toolbox>/File/Open...", TRUE
);
60 menus_set_sensitive ("<Image>/File/Open...", TRUE
);
62 if (gdisplay_active ())
64 menus_set_sensitive ("<Image>/File/Save", TRUE
);
65 menus_set_sensitive ("<Image>/File/Save as...", TRUE
);
73 set_true_callback(GtkWidget
*w
, int *data
)
79 toggle_compress_callback(GtkWidget
*w
, gpointer data
)
81 /* Changes prefs exactly when the user toggles the setting, i.e.
82 * the setting really remembers what the user chose last time, but
83 * lets diagrams of the opposite kind stay that way unless the user
86 prefs
.new_diagram
.compress_save
=
87 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(compressbutton
));
91 open_set_extension(GtkObject
*item
)
93 DiaImportFilter
*ifilter
= gtk_object_get_user_data(item
);
95 const gchar
*text
= gtk_entry_get_text(GTK_ENTRY(GTK_FILE_SELECTION(opendlg
)
97 const gchar
*last_dot
= strrchr(text
, '.');
99 if (!ifilter
|| last_dot
== text
|| text
[0] == '\0' ||
100 ifilter
->extensions
[0] == NULL
)
103 s
= g_string_new(text
);
105 g_string_truncate(s
, last_dot
-text
);
106 g_string_append(s
, ".");
107 g_string_append(s
, ifilter
->extensions
[0]);
108 gtk_entry_set_text(GTK_ENTRY(GTK_FILE_SELECTION(opendlg
)->selection_entry
),
110 g_string_free (s
, TRUE
);
114 create_open_menu(void)
121 menu
= gtk_menu_new();
122 item
= gtk_menu_item_new_with_label(_("By extension"));
123 gtk_container_add(GTK_CONTAINER(menu
), item
);
124 gtk_widget_show(item
);
125 item
= gtk_menu_item_new();
126 gtk_container_add(GTK_CONTAINER(menu
), item
);
127 gtk_widget_show(item
);
130 for (tmp
= filter_get_import_filters(); tmp
!= NULL
; tmp
= tmp
->next
) {
131 DiaImportFilter
*ifilter
= tmp
->data
;
136 filter_label
= filter_get_import_filter_label(ifilter
);
137 item
= gtk_menu_item_new_with_label(filter_label
);
138 g_free(filter_label
);
139 gtk_object_set_user_data(GTK_OBJECT(item
), ifilter
);
140 g_signal_connect(GTK_OBJECT(item
), "activate",
141 GTK_SIGNAL_FUNC(open_set_extension
), NULL
);
142 gtk_container_add(GTK_CONTAINER(menu
), item
);
143 gtk_widget_show(item
);
149 file_open_ok_callback(GtkWidget
*w
, GtkFileSelection
*fs
)
151 const char *filename
;
152 Diagram
*diagram
= NULL
;
153 DiaImportFilter
*ifilter
;
156 filename
= gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs
));
158 ifilter
= gtk_object_get_user_data(GTK_OBJECT(GTK_OPTION_MENU(open_omenu
)
160 diagram
= diagram_load(filename
, ifilter
);
162 if (diagram
!= NULL
) {
163 diagram_update_extents(diagram
);
164 layer_dialog_set_diagram(diagram
);
166 ddisp
= new_display(diagram
);
169 gtk_widget_hide(opendlg
);
173 file_open_callback(gpointer data
, guint action
, GtkWidget
*widget
)
179 ddisp
= ddisplay_active();
181 dia
= ddisp
->diagram
;
183 opendlg
= gtk_file_selection_new(_("Open Diagram"));
184 gtk_window_set_role(GTK_WINDOW(opendlg
), "open_diagram");
185 gtk_window_set_position(GTK_WINDOW(opendlg
), GTK_WIN_POS_MOUSE
);
186 gtk_file_selection_set_filename(GTK_FILE_SELECTION(opendlg
),
187 dia
&& dia
->filename
? dia
->filename
188 : "." G_DIR_SEPARATOR_S
);
189 g_signal_connect_swapped(
190 GTK_OBJECT(GTK_FILE_SELECTION(opendlg
)->cancel_button
),
191 "clicked", G_CALLBACK(file_dialog_hide
),
192 GTK_OBJECT(opendlg
));
193 g_signal_connect(GTK_OBJECT(opendlg
), "delete_event",
194 G_CALLBACK(file_dialog_hide
), NULL
);
195 g_signal_connect(GTK_OBJECT(opendlg
), "destroy",
196 G_CALLBACK(gtk_widget_destroyed
), &opendlg
);
197 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(opendlg
)->ok_button
),
198 "clicked", G_CALLBACK(file_open_ok_callback
),
200 gtk_quit_add_destroy(1, GTK_OBJECT(opendlg
));
202 gtk_widget_set_sensitive(opendlg
, TRUE
);
203 if (GTK_WIDGET_VISIBLE(opendlg
))
205 gtk_file_selection_set_filename(GTK_FILE_SELECTION(opendlg
),
206 "." G_DIR_SEPARATOR_S
);
209 GtkWidget
*hbox
, *label
, *omenu
;
211 open_options
= gtk_frame_new(_("Open Options"));
212 gtk_frame_set_shadow_type(GTK_FRAME(open_options
), GTK_SHADOW_ETCHED_IN
);
214 hbox
= gtk_hbox_new(FALSE
, 1);
215 gtk_container_set_border_width(GTK_CONTAINER(hbox
), 5);
216 gtk_container_add(GTK_CONTAINER(open_options
), hbox
);
217 gtk_widget_show(hbox
);
219 label
= gtk_label_new (_("Determine file type:"));
220 gtk_box_pack_start (GTK_BOX (hbox
), label
, FALSE
, TRUE
, 0);
221 gtk_widget_show (label
);
223 open_omenu
= omenu
= gtk_option_menu_new();
224 gtk_box_pack_start(GTK_BOX(hbox
), omenu
, TRUE
, TRUE
, 0);
225 gtk_widget_show(omenu
);
227 gtk_option_menu_set_menu(GTK_OPTION_MENU(omenu
), create_open_menu());
229 gtk_box_pack_end(GTK_BOX (GTK_FILE_SELECTION(opendlg
)->main_vbox
),
230 open_options
, FALSE
, FALSE
, 5);
233 gtk_widget_show(open_options
);
234 gtk_widget_show(opendlg
);
238 file_save_as_ok_callback(GtkWidget
*w
, GtkFileSelection
*fs
)
240 const char *filename
;
242 struct stat stat_struct
;
244 dia
= gtk_object_get_user_data(GTK_OBJECT(fs
));
246 filename
= gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs
));
248 if (stat(filename
, &stat_struct
) == 0) {
249 GtkWidget
*dialog
= NULL
;
251 char *utf8filename
= NULL
;
253 if (!g_utf8_validate(filename
, -1, NULL
)) {
254 utf8filename
= g_locale_to_utf8(filename
, -1, NULL
, NULL
, NULL
);
255 if (utf8filename
== NULL
) {
256 message_warning(_("Some characters in the filename are neither UTF-8 nor your local encoding.\nSome things will break."));
259 if (utf8filename
== NULL
) utf8filename
= g_strdup(filename
);
261 g_snprintf(buffer
, 300,
262 _("The file '%s' already exists.\n"
263 "Do you want to overwrite it?"), utf8filename
);
264 g_free(utf8filename
);
266 dialog
= gtk_message_dialog_new (GTK_WINDOW(fs
),
267 GTK_DIALOG_MODAL
, GTK_MESSAGE_QUESTION
,
270 gtk_window_set_title (GTK_WINDOW (dialog
), _("File already exists"));
271 gtk_dialog_set_default_response (GTK_DIALOG (dialog
), GTK_RESPONSE_YES
);
273 if (gtk_dialog_run (GTK_DIALOG (dialog
)) != GTK_RESPONSE_YES
) {
274 file_dialog_hide(savedlg
);
275 gtk_widget_destroy(dialog
);
278 gtk_widget_destroy(dialog
);
281 dia
->data
->is_compressed
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(compressbutton
));
283 diagram_update_extents(dia
);
285 diagram_set_filename(dia
, filename
);
286 diagram_save(dia
, filename
);
288 file_dialog_hide(savedlg
);
292 file_save_as_callback(gpointer data
, guint action
, GtkWidget
*widget
)
297 ddisp
= ddisplay_active();
299 dia
= ddisp
->diagram
;
302 savedlg
= gtk_file_selection_new(_("Save Diagram"));
303 gtk_window_set_role(GTK_WINDOW(savedlg
), "save_diagram");
304 gtk_window_set_position(GTK_WINDOW(savedlg
), GTK_WIN_POS_MOUSE
);
305 /* Need better way to make it a reasonable size. Isn't there some*/
306 /* standard look for them (or is that just Gnome?)*/
307 compressbutton
= gtk_check_button_new_with_label(_("Compress diagram files"));
308 gtk_box_pack_start_defaults(GTK_BOX(GTK_FILE_SELECTION(savedlg
)->main_vbox
),
310 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(compressbutton
),
311 dia
->data
->is_compressed
);
312 g_signal_connect(G_OBJECT(compressbutton
), "toggled",
313 toggle_compress_callback
, NULL
);
314 gtk_widget_show(compressbutton
);
315 gtk_tooltips_set_tip(tool_tips
, compressbutton
,
316 _("Compression reduces file size to less than 1/10th size and speeds up loading and saving. Some text programs cannot manipulate compressed files."), NULL
);
317 g_signal_connect_swapped(
318 GTK_OBJECT(GTK_FILE_SELECTION(savedlg
)->cancel_button
),
319 "clicked", G_CALLBACK(file_dialog_hide
),
320 GTK_OBJECT(savedlg
));
321 g_signal_connect(GTK_OBJECT(savedlg
), "delete_event",
322 G_CALLBACK(file_dialog_hide
), NULL
);
323 g_signal_connect(GTK_OBJECT(savedlg
), "destroy",
324 G_CALLBACK(gtk_widget_destroyed
), &savedlg
);
325 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(savedlg
)->ok_button
),
326 "clicked", G_CALLBACK(file_save_as_ok_callback
),
328 gtk_quit_add_destroy(1, GTK_OBJECT(savedlg
));
330 gtk_widget_set_sensitive(savedlg
, TRUE
);
331 g_signal_handlers_block_by_func(G_OBJECT(compressbutton
), toggle_compress_callback
, NULL
);
332 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(compressbutton
),
333 dia
->data
->is_compressed
);
334 g_signal_handlers_unblock_by_func(G_OBJECT(compressbutton
), toggle_compress_callback
, NULL
);
335 if (GTK_WIDGET_VISIBLE(savedlg
))
338 gtk_file_selection_set_filename(GTK_FILE_SELECTION(savedlg
),
339 dia
->filename
? dia
->filename
340 : "." G_DIR_SEPARATOR_S
);
341 gtk_object_set_user_data(GTK_OBJECT(savedlg
), dia
);
342 diagram_add_related_dialog(dia
, savedlg
);
344 gtk_widget_show(savedlg
);
348 file_save_callback(gpointer data
, guint action
, GtkWidget
*widget
)
352 diagram
= ddisplay_active_diagram();
353 if (!diagram
) return;
355 if (diagram
->unsaved
) {
356 file_save_as_callback(data
, action
, widget
);
358 diagram_update_extents(diagram
);
359 diagram_save(diagram
, diagram
->filename
);
364 export_set_extension(GtkObject
*item
)
366 DiaExportFilter
*ef
= gtk_object_get_user_data(item
);
368 const gchar
*text
= gtk_entry_get_text(GTK_ENTRY(GTK_FILE_SELECTION(exportdlg
)
370 const gchar
*last_dot
= strrchr(text
, '.');
372 if (!ef
|| last_dot
== text
|| text
[0] == '\0' || ef
->extensions
[0] == NULL
)
375 s
= g_string_new(text
);
377 g_string_truncate(s
, last_dot
-text
);
378 g_string_append(s
, ".");
379 g_string_append(s
, ef
->extensions
[0]);
380 gtk_entry_set_text(GTK_ENTRY(GTK_FILE_SELECTION(exportdlg
)->selection_entry
),
382 g_string_free (s
, TRUE
);
386 create_export_menu(void)
392 menu
= gtk_menu_new();
393 item
= gtk_menu_item_new_with_label(_("By extension"));
394 gtk_container_add(GTK_CONTAINER(menu
), item
);
395 gtk_widget_show(item
);
396 item
= gtk_menu_item_new();
397 gtk_container_add(GTK_CONTAINER(menu
), item
);
398 gtk_widget_show(item
);
401 for (tmp
= filter_get_export_filters(); tmp
!= NULL
; tmp
= tmp
->next
) {
402 DiaExportFilter
*ef
= tmp
->data
;
407 filter_label
= filter_get_export_filter_label(ef
);
408 item
= gtk_menu_item_new_with_label(filter_label
);
409 g_free(filter_label
);
410 gtk_object_set_user_data(GTK_OBJECT(item
), ef
);
411 g_signal_connect(GTK_OBJECT(item
), "activate",
412 G_CALLBACK(export_set_extension
), NULL
);
413 gtk_container_add(GTK_CONTAINER(menu
), item
);
414 gtk_widget_show(item
);
420 file_export_ok_callback(GtkWidget
*w
, GtkFileSelection
*fs
)
422 const char *filename
;
427 dia
= gtk_object_get_user_data(GTK_OBJECT(fs
));
428 diagram_update_extents(dia
);
430 filename
= gtk_file_selection_get_filename(fs
);
432 if (stat(filename
, &statbuf
) == 0) {
433 GtkWidget
*dialog
= NULL
;
436 g_snprintf(buffer
, 300,
437 _("The file '%s' already exists.\n"
438 "Do you want to overwrite it?"), filename
);
439 dialog
= gtk_message_dialog_new (GTK_WINDOW(fs
),
440 GTK_DIALOG_MODAL
| GTK_DIALOG_DESTROY_WITH_PARENT
,
441 GTK_MESSAGE_QUESTION
,
444 gtk_window_set_title (GTK_WINDOW (dialog
), _("File already exists"));
445 gtk_dialog_set_default_response (GTK_DIALOG (dialog
), GTK_RESPONSE_YES
);
447 if (gtk_dialog_run (GTK_DIALOG (dialog
)) != GTK_RESPONSE_YES
) {
448 file_dialog_hide(exportdlg
);
449 gtk_widget_destroy(dialog
);
452 gtk_widget_destroy(dialog
);
455 ef
= gtk_object_get_user_data(GTK_OBJECT(GTK_OPTION_MENU(export_omenu
)
458 ef
= filter_guess_export_filter(filename
);
460 g_object_ref(dia
->data
);
461 ef
->export_func(dia
->data
, filename
, dia
->filename
, ef
->user_data
);
463 message_error(_("Could not determine which export filter\n"
464 "to use to save '%s'"), filename
);
466 file_dialog_hide(exportdlg
);
470 file_export_callback(gpointer data
, guint action
, GtkWidget
*widget
)
474 GtkWidget
*export_menu
, *export_item
;
476 ddisp
= ddisplay_active();
478 dia
= ddisp
->diagram
;
481 exportdlg
= gtk_file_selection_new(_("Export Diagram"));
482 gtk_window_set_role(GTK_WINDOW(exportdlg
), "export_diagram");
483 gtk_window_set_position(GTK_WINDOW(exportdlg
), GTK_WIN_POS_MOUSE
);
484 gtk_file_selection_set_filename(GTK_FILE_SELECTION(exportdlg
),
485 dia
->filename
? dia
->filename
486 : "." G_DIR_SEPARATOR_S
);
487 g_signal_connect_swapped(
488 GTK_OBJECT(GTK_FILE_SELECTION(exportdlg
)->cancel_button
),
489 "clicked", G_CALLBACK(file_dialog_hide
),
490 GTK_OBJECT(exportdlg
));
491 g_signal_connect(GTK_OBJECT(exportdlg
), "delete_event",
492 G_CALLBACK(file_dialog_hide
), NULL
);
493 g_signal_connect(GTK_OBJECT(exportdlg
), "destroy",
494 G_CALLBACK(gtk_widget_destroyed
), &exportdlg
);
495 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(exportdlg
)->ok_button
),
496 "clicked", G_CALLBACK(file_export_ok_callback
),
498 gtk_quit_add_destroy(1, GTK_OBJECT(exportdlg
));
500 if (!export_options
) {
501 GtkWidget
*hbox
, *label
, *omenu
;
503 export_options
= gtk_frame_new(_("Export Options"));
504 gtk_frame_set_shadow_type(GTK_FRAME(export_options
), GTK_SHADOW_ETCHED_IN
);
506 hbox
= gtk_hbox_new(FALSE
, 1);
507 gtk_container_set_border_width(GTK_CONTAINER(hbox
), 5);
508 gtk_container_add(GTK_CONTAINER(export_options
), hbox
);
509 gtk_widget_show(hbox
);
511 label
= gtk_label_new (_("Determine file type:"));
512 gtk_box_pack_start (GTK_BOX (hbox
), label
, FALSE
, TRUE
, 0);
513 gtk_widget_show (label
);
515 export_omenu
= omenu
= gtk_option_menu_new();
516 gtk_box_pack_start(GTK_BOX(hbox
), omenu
, TRUE
, TRUE
, 0);
517 gtk_widget_show(omenu
);
519 gtk_option_menu_set_menu(GTK_OPTION_MENU(omenu
), create_export_menu());
521 gtk_box_pack_end(GTK_BOX (GTK_FILE_SELECTION(exportdlg
)->main_vbox
),
522 export_options
, FALSE
, FALSE
, 5);
525 gtk_object_set_user_data(GTK_OBJECT(exportdlg
), dia
);
527 gtk_widget_set_sensitive(exportdlg
, TRUE
);
528 if (GTK_WIDGET_VISIBLE(exportdlg
))
530 gtk_file_selection_set_filename(GTK_FILE_SELECTION(exportdlg
),
531 dia
->filename
? dia
->filename
532 : "." G_DIR_SEPARATOR_S
);
533 export_menu
= gtk_option_menu_get_menu(GTK_OPTION_MENU(export_omenu
));
534 export_item
= gtk_menu_get_active(GTK_MENU(export_menu
));
536 export_set_extension(GTK_OBJECT(export_item
));
537 gtk_widget_show(export_options
);
538 gtk_widget_show(exportdlg
);