using dia-manual.chm instead of dia.chm
[dia.git] / app / filedlg.c
blob2f39222c17ff2b3551bde0492f26366db41d1310
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 "display.h"
35 #include "message.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;
46 static int
47 file_dialog_hide (GtkWidget *filesel)
49 gtk_widget_hide (filesel);
51 #if 0
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);
60 #endif
62 return TRUE;
65 static void
66 set_true_callback(GtkWidget *w, int *data)
68 *data = TRUE;
71 static void
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
77 // intervenes.
78 prefs.new_diagram.compress_save =
79 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(compressbutton));
82 static void
83 open_set_extension(GtkObject *item)
85 DiaImportFilter *ifilter = gtk_object_get_user_data(item);
86 GString *s;
87 const gchar *text = gtk_entry_get_text(GTK_ENTRY(GTK_FILE_SELECTION(opendlg)
88 ->selection_entry));
89 const gchar *last_dot = strrchr(text, '.');
91 if (!ifilter || last_dot == text || text[0] == '\0' ||
92 ifilter->extensions[0] == NULL)
93 return;
95 s = g_string_new(text);
96 if (last_dot)
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),
101 s->str);
102 g_string_free (s, TRUE);
105 static GtkWidget *
106 create_open_menu(void)
108 GtkWidget *menu;
109 GtkWidget *item;
110 GList *tmp;
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;
124 if (!ifilter)
125 continue;
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);
134 return menu;
137 static void
138 file_open_ok_callback(GtkWidget *w, GtkFileSelection *fs)
140 const char *filename;
141 Diagram *diagram = NULL;
142 DiaImportFilter *ifilter;
143 DDisplay *ddisp;
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)
148 ->menu_item));
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);
161 void
162 file_open_callback(gpointer data, guint action, GtkWidget *widget)
164 if (!opendlg) {
165 DDisplay *ddisp;
166 Diagram *dia = NULL;
168 ddisp = ddisplay_active();
169 if (ddisp) {
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),
188 opendlg);
189 gtk_quit_add_destroy(1, GTK_OBJECT(opendlg));
190 } else {
191 gtk_widget_set_sensitive(opendlg, TRUE);
192 if (GTK_WIDGET_VISIBLE(opendlg))
193 return;
194 gtk_file_selection_set_filename(GTK_FILE_SELECTION(opendlg),
195 "." G_DIR_SEPARATOR_S);
197 if (!open_options) {
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);
226 static void
227 file_save_as_ok_callback(GtkWidget *w, GtkFileSelection *fs)
229 const char *filename;
230 Diagram *dia;
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;
239 char buffer[300];
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,
257 GTK_BUTTONS_YES_NO,
258 buffer);
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),
263 NULL);
265 if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_YES) {
266 gtk_widget_hide(savedlg);
267 return;
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);
281 void
282 file_save_as_callback(gpointer data, guint action, GtkWidget *widget)
284 DDisplay *ddisp;
285 Diagram *dia;
287 ddisp = ddisplay_active();
288 if (!ddisp) return;
289 dia = ddisp->diagram;
291 if (!savedlg) {
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),
302 compressbutton);
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),
320 savedlg);
321 gtk_quit_add_destroy(1, GTK_OBJECT(savedlg));
322 } else {
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))
329 return;
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);
338 void
339 file_save_callback(gpointer data, guint action, GtkWidget *widget)
341 DDisplay *ddisp;
343 ddisp = ddisplay_active();
345 if (ddisp->diagram->unsaved) {
346 file_save_as_callback(data, action, widget);
347 } else {
348 diagram_update_extents(ddisp->diagram);
349 diagram_save(ddisp->diagram, ddisp->diagram->filename);
353 static void
354 export_set_extension(GtkObject *item)
356 DiaExportFilter *ef = gtk_object_get_user_data(item);
357 GString *s;
358 const gchar *text = gtk_entry_get_text(GTK_ENTRY(GTK_FILE_SELECTION(exportdlg)
359 ->selection_entry));
360 const gchar *last_dot = strrchr(text, '.');
362 if (!ef || last_dot == text || text[0] == '\0' || ef->extensions[0] == NULL)
363 return;
365 s = g_string_new(text);
366 if (last_dot)
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),
371 s->str);
372 g_string_free (s, TRUE);
375 static GtkWidget *
376 create_export_menu(void)
378 GtkWidget *menu;
379 GtkWidget *item;
380 GList *tmp;
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;
394 if (!ef)
395 continue;
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);
403 return menu;
406 static void
407 file_export_ok_callback(GtkWidget *w, GtkFileSelection *fs)
409 const char *filename;
410 Diagram *dia;
411 DiaExportFilter *ef;
412 struct stat statbuf;
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;
421 char buffer[300];
422 int result;
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,
429 GTK_BUTTONS_YES_NO,
430 buffer);
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),
435 NULL);
437 if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_YES) {
438 gtk_widget_hide(exportdlg);
439 return;
443 ef = gtk_object_get_user_data(GTK_OBJECT(GTK_OPTION_MENU(export_omenu)
444 ->menu_item));
445 if (!ef)
446 ef = filter_guess_export_filter(filename);
447 if (ef)
448 ef->export(dia->data, filename, dia->filename, ef->user_data);
449 else
450 message_error(_("Could not determine which export filter\n"
451 "to use to save '%s'"), filename);
453 gtk_widget_hide(exportdlg);
456 void
457 file_export_callback(gpointer data, guint action, GtkWidget *widget)
459 DDisplay *ddisp;
460 Diagram *dia;
461 GtkWidget *export_menu, *export_item;
463 ddisp = ddisplay_active();
464 if (!ddisp) return;
465 dia = ddisp->diagram;
467 if (!exportdlg) {
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),
484 exportdlg);
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))
515 return;
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));
521 if (export_item)
522 export_set_extension(GTK_OBJECT(export_item));
523 gtk_widget_show(export_options);
524 gtk_widget_show(exportdlg);