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
)
49 gtk_widget_hide (filesel
);
52 menus_set_sensitive ("<Toolbox>/File/Open...", TRUE
);
53 menus_set_sensitive ("<Image>/File/Open...", TRUE
);
55 if (gdisplay_active ())
57 menus_set_sensitive ("<Image>/File/Save", TRUE
);
58 menus_set_sensitive ("<Image>/File/Save as...", TRUE
);
66 set_true_callback(GtkWidget
*w
, int *data
)
72 toggle_compress_callback(GtkWidget
*w
, gpointer data
)
74 // Changes prefs exactly when the user toggles the setting, i.e.
75 // the setting really remembers what the user chose last time, but
76 // lets diagrams of the opposite kind stay that way unless the user
78 prefs
.new_diagram
.compress_save
=
79 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(compressbutton
));
83 open_set_extension(GtkObject
*item
)
85 DiaImportFilter
*ifilter
= gtk_object_get_user_data(item
);
87 const gchar
*text
= gtk_entry_get_text(GTK_ENTRY(GTK_FILE_SELECTION(opendlg
)
89 const gchar
*last_dot
= strrchr(text
, '.');
91 if (!ifilter
|| last_dot
== text
|| text
[0] == '\0' ||
92 ifilter
->extensions
[0] == NULL
)
95 s
= g_string_new(text
);
97 g_string_truncate(s
, last_dot
-text
);
98 g_string_append(s
, ".");
99 g_string_append(s
, ifilter
->extensions
[0]);
100 gtk_entry_set_text(GTK_ENTRY(GTK_FILE_SELECTION(opendlg
)->selection_entry
),
102 g_string_free (s
, TRUE
);
106 create_open_menu(void)
112 menu
= gtk_menu_new();
113 item
= gtk_menu_item_new_with_label(_("By extension"));
114 gtk_container_add(GTK_CONTAINER(menu
), item
);
115 gtk_widget_show(item
);
116 item
= gtk_menu_item_new();
117 gtk_container_add(GTK_CONTAINER(menu
), item
);
118 gtk_widget_show(item
);
121 for (tmp
= filter_get_import_filters(); tmp
!= NULL
; tmp
= tmp
->next
) {
122 DiaImportFilter
*ifilter
= tmp
->data
;
126 item
= gtk_menu_item_new_with_label(
127 filter_get_import_filter_label(ifilter
));
128 gtk_object_set_user_data(GTK_OBJECT(item
), ifilter
);
129 gtk_signal_connect(GTK_OBJECT(item
), "activate",
130 GTK_SIGNAL_FUNC(open_set_extension
), NULL
);
131 gtk_container_add(GTK_CONTAINER(menu
), item
);
132 gtk_widget_show(item
);
138 file_open_ok_callback(GtkWidget
*w
, GtkFileSelection
*fs
)
140 const char *filename
;
141 Diagram
*diagram
= NULL
;
142 DiaImportFilter
*ifilter
;
145 filename
= gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs
));
147 ifilter
= gtk_object_get_user_data(GTK_OBJECT(GTK_OPTION_MENU(open_omenu
)
149 diagram
= diagram_load(filename
, ifilter
);
151 if (diagram
!= NULL
) {
152 diagram_update_extents(diagram
);
153 layer_dialog_set_diagram(diagram
);
155 ddisp
= new_display(diagram
);
158 gtk_widget_hide(opendlg
);
162 file_open_callback(gpointer data
, guint action
, GtkWidget
*widget
)
168 ddisp
= ddisplay_active();
170 dia
= ddisp
->diagram
;
172 opendlg
= gtk_file_selection_new(_("Open Diagram"));
173 gtk_window_set_role(GTK_WINDOW(opendlg
), "open_diagram");
174 gtk_window_set_position(GTK_WINDOW(opendlg
), GTK_WIN_POS_MOUSE
);
175 gtk_file_selection_set_filename(GTK_FILE_SELECTION(opendlg
),
176 dia
&& dia
->filename
? dia
->filename
177 : "." G_DIR_SEPARATOR_S
);
178 gtk_signal_connect_object(
179 GTK_OBJECT(GTK_FILE_SELECTION(opendlg
)->cancel_button
),
180 "clicked", GTK_SIGNAL_FUNC(file_dialog_hide
),
181 GTK_OBJECT(opendlg
));
182 gtk_signal_connect(GTK_OBJECT(opendlg
), "delete_event",
183 GTK_SIGNAL_FUNC(file_dialog_hide
), NULL
);
184 gtk_signal_connect(GTK_OBJECT(opendlg
), "destroy",
185 GTK_SIGNAL_FUNC(gtk_widget_destroyed
), &opendlg
);
186 gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(opendlg
)->ok_button
),
187 "clicked", GTK_SIGNAL_FUNC(file_open_ok_callback
),
189 gtk_quit_add_destroy(1, GTK_OBJECT(opendlg
));
191 gtk_widget_set_sensitive(opendlg
, TRUE
);
192 if (GTK_WIDGET_VISIBLE(opendlg
))
194 gtk_file_selection_set_filename(GTK_FILE_SELECTION(opendlg
),
195 "." G_DIR_SEPARATOR_S
);
198 GtkWidget
*hbox
, *label
, *omenu
;
200 open_options
= gtk_frame_new(_("Open Options"));
201 gtk_frame_set_shadow_type(GTK_FRAME(open_options
), GTK_SHADOW_ETCHED_IN
);
203 hbox
= gtk_hbox_new(FALSE
, 1);
204 gtk_container_set_border_width(GTK_CONTAINER(hbox
), 5);
205 gtk_container_add(GTK_CONTAINER(open_options
), hbox
);
206 gtk_widget_show(hbox
);
208 label
= gtk_label_new (_("Determine file type:"));
209 gtk_box_pack_start (GTK_BOX (hbox
), label
, FALSE
, TRUE
, 0);
210 gtk_widget_show (label
);
212 open_omenu
= omenu
= gtk_option_menu_new();
213 gtk_box_pack_start(GTK_BOX(hbox
), omenu
, TRUE
, TRUE
, 0);
214 gtk_widget_show(omenu
);
216 gtk_option_menu_set_menu(GTK_OPTION_MENU(omenu
), create_open_menu());
218 gtk_box_pack_end(GTK_BOX (GTK_FILE_SELECTION(opendlg
)->main_vbox
),
219 open_options
, FALSE
, FALSE
, 5);
222 gtk_widget_show(open_options
);
223 gtk_widget_show(opendlg
);
227 file_save_as_ok_callback(GtkWidget
*w
, GtkFileSelection
*fs
)
229 const char *filename
;
231 struct stat stat_struct
;
233 dia
= gtk_object_get_user_data(GTK_OBJECT(fs
));
235 filename
= gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs
));
237 if (stat(filename
, &stat_struct
) == 0) {
238 GtkWidget
*dialog
= NULL
;
240 char *utf8filename
= NULL
;
242 if (!g_utf8_validate(filename
, -1, NULL
)) {
243 utf8filename
= g_locale_to_utf8(filename
, -1, NULL
, NULL
, NULL
);
244 if (utf8filename
== NULL
) {
245 message_warning(_("Some characters in the filename are neither UTF-8 nor your local encoding.\nSome things will break."));
248 if (utf8filename
== NULL
) utf8filename
= g_strdup(filename
);
250 g_snprintf(buffer
, 300,
251 _("The file '%s' already exists.\n"
252 "Do you want to overwrite it?"), utf8filename
);
253 g_free(utf8filename
);
255 dialog
= gtk_message_dialog_new (GTK_WINDOW(fs
),
256 GTK_DIALOG_MODAL
, GTK_MESSAGE_QUESTION
,
259 gtk_window_set_title (GTK_WINDOW (dialog
), _("File already exists"));
260 gtk_dialog_set_default_response (GTK_DIALOG (dialog
), GTK_RESPONSE_YES
);
261 g_signal_connect_after (G_OBJECT (dialog
), "response",
262 G_CALLBACK(gtk_widget_destroy
),
265 if (gtk_dialog_run (GTK_DIALOG (dialog
)) != GTK_RESPONSE_YES
) {
266 gtk_widget_hide(savedlg
);
271 dia
->data
->is_compressed
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(compressbutton
));
273 diagram_update_extents(dia
);
275 diagram_set_filename(dia
, filename
);
276 diagram_save(dia
, filename
);
278 gtk_widget_hide(savedlg
);
282 file_save_as_callback(gpointer data
, guint action
, GtkWidget
*widget
)
287 ddisp
= ddisplay_active();
289 dia
= ddisp
->diagram
;
292 savedlg
= gtk_file_selection_new(_("Save Diagram"));
293 gtk_window_set_role(GTK_WINDOW(savedlg
), "save_diagram");
294 gtk_window_set_position(GTK_WINDOW(savedlg
), GTK_WIN_POS_MOUSE
);
295 gtk_file_selection_set_filename(GTK_FILE_SELECTION(savedlg
),
296 dia
->filename
? dia
->filename
297 : "." G_DIR_SEPARATOR_S
);
298 /* Need better way to make it a reasonable size. Isn't there some*/
299 /* standard look for them (or is that just Gnome?)*/
300 compressbutton
= gtk_check_button_new_with_label(_("Compress diagram files"));
301 gtk_box_pack_start_defaults(GTK_BOX(GTK_FILE_SELECTION(savedlg
)->main_vbox
),
303 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(compressbutton
),
304 dia
->data
->is_compressed
);
305 g_signal_connect(G_OBJECT(compressbutton
), "toggled",
306 toggle_compress_callback
, NULL
);
307 gtk_widget_show(compressbutton
);
308 gtk_tooltips_set_tip(tool_tips
, compressbutton
,
309 _("Compression reduces file size to less than 1/10th size and speeds up loading and saving. Some text programs cannot manipulate compressed files."), NULL
);
310 gtk_signal_connect_object(
311 GTK_OBJECT(GTK_FILE_SELECTION(savedlg
)->cancel_button
),
312 "clicked", GTK_SIGNAL_FUNC(file_dialog_hide
),
313 GTK_OBJECT(savedlg
));
314 gtk_signal_connect(GTK_OBJECT(savedlg
), "delete_event",
315 GTK_SIGNAL_FUNC(file_dialog_hide
), NULL
);
316 gtk_signal_connect(GTK_OBJECT(savedlg
), "destroy",
317 GTK_SIGNAL_FUNC(gtk_widget_destroyed
), &savedlg
);
318 gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(savedlg
)->ok_button
),
319 "clicked", GTK_SIGNAL_FUNC(file_save_as_ok_callback
),
321 gtk_quit_add_destroy(1, GTK_OBJECT(savedlg
));
323 gtk_widget_set_sensitive(savedlg
, TRUE
);
324 g_signal_handlers_block_by_func(G_OBJECT(compressbutton
), toggle_compress_callback
, NULL
);
325 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(compressbutton
),
326 dia
->data
->is_compressed
);
327 g_signal_handlers_unblock_by_func(G_OBJECT(compressbutton
), toggle_compress_callback
, NULL
);
328 if (GTK_WIDGET_VISIBLE(savedlg
))
330 gtk_file_selection_set_filename(GTK_FILE_SELECTION(savedlg
),
331 dia
->filename
? dia
->filename
332 : "." G_DIR_SEPARATOR_S
);
334 gtk_object_set_user_data(GTK_OBJECT(savedlg
), dia
);
335 gtk_widget_show(savedlg
);
339 file_save_callback(gpointer data
, guint action
, GtkWidget
*widget
)
343 ddisp
= ddisplay_active();
345 if (ddisp
->diagram
->unsaved
) {
346 file_save_as_callback(data
, action
, widget
);
348 diagram_update_extents(ddisp
->diagram
);
349 diagram_save(ddisp
->diagram
, ddisp
->diagram
->filename
);
354 export_set_extension(GtkObject
*item
)
356 DiaExportFilter
*ef
= gtk_object_get_user_data(item
);
358 const gchar
*text
= gtk_entry_get_text(GTK_ENTRY(GTK_FILE_SELECTION(exportdlg
)
360 const gchar
*last_dot
= strrchr(text
, '.');
362 if (!ef
|| last_dot
== text
|| text
[0] == '\0' || ef
->extensions
[0] == NULL
)
365 s
= g_string_new(text
);
367 g_string_truncate(s
, last_dot
-text
);
368 g_string_append(s
, ".");
369 g_string_append(s
, ef
->extensions
[0]);
370 gtk_entry_set_text(GTK_ENTRY(GTK_FILE_SELECTION(exportdlg
)->selection_entry
),
372 g_string_free (s
, TRUE
);
376 create_export_menu(void)
382 menu
= gtk_menu_new();
383 item
= gtk_menu_item_new_with_label(_("By extension"));
384 gtk_container_add(GTK_CONTAINER(menu
), item
);
385 gtk_widget_show(item
);
386 item
= gtk_menu_item_new();
387 gtk_container_add(GTK_CONTAINER(menu
), item
);
388 gtk_widget_show(item
);
391 for (tmp
= filter_get_export_filters(); tmp
!= NULL
; tmp
= tmp
->next
) {
392 DiaExportFilter
*ef
= tmp
->data
;
396 item
= gtk_menu_item_new_with_label(filter_get_export_filter_label(ef
));
397 gtk_object_set_user_data(GTK_OBJECT(item
), ef
);
398 gtk_signal_connect(GTK_OBJECT(item
), "activate",
399 GTK_SIGNAL_FUNC(export_set_extension
), NULL
);
400 gtk_container_add(GTK_CONTAINER(menu
), item
);
401 gtk_widget_show(item
);
407 file_export_ok_callback(GtkWidget
*w
, GtkFileSelection
*fs
)
409 const char *filename
;
414 dia
= gtk_object_get_user_data(GTK_OBJECT(fs
));
415 diagram_update_extents(dia
);
417 filename
= gtk_file_selection_get_filename(fs
);
419 if (stat(filename
, &statbuf
) == 0) {
420 GtkWidget
*dialog
= NULL
;
424 g_snprintf(buffer
, 300,
425 _("The file '%s' already exists.\n"
426 "Do you want to overwrite it?"), filename
);
427 dialog
= gtk_message_dialog_new (GTK_WINDOW(fs
),
428 GTK_DIALOG_MODAL
, GTK_MESSAGE_QUESTION
,
431 gtk_window_set_title (GTK_WINDOW (dialog
), _("File already exists"));
432 gtk_dialog_set_default_response (GTK_DIALOG (dialog
), GTK_RESPONSE_YES
);
433 g_signal_connect_after (G_OBJECT (dialog
), "response",
434 G_CALLBACK(gtk_widget_destroy
),
437 if (gtk_dialog_run (GTK_DIALOG (dialog
)) != GTK_RESPONSE_YES
) {
438 gtk_widget_hide(exportdlg
);
443 ef
= gtk_object_get_user_data(GTK_OBJECT(GTK_OPTION_MENU(export_omenu
)
446 ef
= filter_guess_export_filter(filename
);
448 ef
->export(dia
->data
, filename
, dia
->filename
, ef
->user_data
);
450 message_error(_("Could not determine which export filter\n"
451 "to use to save '%s'"), filename
);
453 gtk_widget_hide(exportdlg
);
457 file_export_callback(gpointer data
, guint action
, GtkWidget
*widget
)
461 GtkWidget
*export_menu
, *export_item
;
463 ddisp
= ddisplay_active();
465 dia
= ddisp
->diagram
;
468 exportdlg
= gtk_file_selection_new(_("Export Diagram"));
469 gtk_window_set_role(GTK_WINDOW(exportdlg
), "export_diagram");
470 gtk_window_set_position(GTK_WINDOW(exportdlg
), GTK_WIN_POS_MOUSE
);
471 gtk_file_selection_set_filename(GTK_FILE_SELECTION(exportdlg
),
472 dia
->filename
? dia
->filename
473 : "." G_DIR_SEPARATOR_S
);
474 gtk_signal_connect_object(
475 GTK_OBJECT(GTK_FILE_SELECTION(exportdlg
)->cancel_button
),
476 "clicked", GTK_SIGNAL_FUNC(file_dialog_hide
),
477 GTK_OBJECT(exportdlg
));
478 gtk_signal_connect(GTK_OBJECT(exportdlg
), "delete_event",
479 GTK_SIGNAL_FUNC(file_dialog_hide
), NULL
);
480 gtk_signal_connect(GTK_OBJECT(exportdlg
), "destroy",
481 GTK_SIGNAL_FUNC(gtk_widget_destroyed
), &exportdlg
);
482 gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(exportdlg
)->ok_button
),
483 "clicked", GTK_SIGNAL_FUNC(file_export_ok_callback
),
485 gtk_quit_add_destroy(1, GTK_OBJECT(exportdlg
));
487 if (!export_options
) {
488 GtkWidget
*hbox
, *label
, *omenu
;
490 export_options
= gtk_frame_new(_("Export Options"));
491 gtk_frame_set_shadow_type(GTK_FRAME(export_options
), GTK_SHADOW_ETCHED_IN
);
493 hbox
= gtk_hbox_new(FALSE
, 1);
494 gtk_container_set_border_width(GTK_CONTAINER(hbox
), 5);
495 gtk_container_add(GTK_CONTAINER(export_options
), hbox
);
496 gtk_widget_show(hbox
);
498 label
= gtk_label_new (_("Determine file type:"));
499 gtk_box_pack_start (GTK_BOX (hbox
), label
, FALSE
, TRUE
, 0);
500 gtk_widget_show (label
);
502 export_omenu
= omenu
= gtk_option_menu_new();
503 gtk_box_pack_start(GTK_BOX(hbox
), omenu
, TRUE
, TRUE
, 0);
504 gtk_widget_show(omenu
);
506 gtk_option_menu_set_menu(GTK_OPTION_MENU(omenu
), create_export_menu());
508 gtk_box_pack_end(GTK_BOX (GTK_FILE_SELECTION(exportdlg
)->main_vbox
),
509 export_options
, FALSE
, FALSE
, 5);
512 gtk_object_set_user_data(GTK_OBJECT(exportdlg
), dia
);
513 gtk_widget_set_sensitive(exportdlg
, TRUE
);
514 if (GTK_WIDGET_VISIBLE(exportdlg
))
516 gtk_file_selection_set_filename(GTK_FILE_SELECTION(exportdlg
),
517 dia
->filename
? dia
->filename
518 : "." G_DIR_SEPARATOR_S
);
519 export_menu
= gtk_option_menu_get_menu(GTK_OPTION_MENU(export_omenu
));
520 export_item
= gtk_menu_get_active(GTK_MENU(export_menu
));
522 export_set_extension(GTK_OBJECT(export_item
));
523 gtk_widget_show(export_options
);
524 gtk_widget_show(exportdlg
);