linewidth is now working for PS_SOLID
[dia.git] / app / filedlg.c
blob77c3159f3ded64491ab1072d3630bc2d369c62b0
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 gpointer user_data;
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);
58 #if 0
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);
67 #endif
69 return TRUE;
72 static void
73 set_true_callback(GtkWidget *w, int *data)
75 *data = TRUE;
78 static void
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
84 * intervenes.
86 prefs.new_diagram.compress_save =
87 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(compressbutton));
90 static void
91 open_set_extension(GtkObject *item)
93 DiaImportFilter *ifilter = gtk_object_get_user_data(item);
94 GString *s;
95 const gchar *text = gtk_entry_get_text(GTK_ENTRY(GTK_FILE_SELECTION(opendlg)
96 ->selection_entry));
97 const gchar *last_dot = strrchr(text, '.');
99 if (!ifilter || last_dot == text || text[0] == '\0' ||
100 ifilter->extensions[0] == NULL)
101 return;
103 s = g_string_new(text);
104 if (last_dot)
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),
109 s->str);
110 g_string_free (s, TRUE);
113 static GtkWidget *
114 create_open_menu(void)
116 GtkWidget *menu;
117 GtkWidget *item;
118 GList *tmp;
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;
132 gchar *filter_label;
134 if (!ifilter)
135 continue;
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);
145 return menu;
148 static void
149 file_open_ok_callback(GtkWidget *w, GtkFileSelection *fs)
151 const char *filename;
152 Diagram *diagram = NULL;
153 DiaImportFilter *ifilter;
154 DDisplay *ddisp;
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)
159 ->menu_item));
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);
172 void
173 file_open_callback(gpointer data, guint action, GtkWidget *widget)
175 if (!opendlg) {
176 DDisplay *ddisp;
177 Diagram *dia = NULL;
179 ddisp = ddisplay_active();
180 if (ddisp) {
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),
199 opendlg);
200 gtk_quit_add_destroy(1, GTK_OBJECT(opendlg));
201 } else {
202 gtk_widget_set_sensitive(opendlg, TRUE);
203 if (GTK_WIDGET_VISIBLE(opendlg))
204 return;
205 gtk_file_selection_set_filename(GTK_FILE_SELECTION(opendlg),
206 "." G_DIR_SEPARATOR_S);
208 if (!open_options) {
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);
237 static void
238 file_save_as_ok_callback(GtkWidget *w, GtkFileSelection *fs)
240 const char *filename;
241 Diagram *dia;
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;
250 char buffer[300];
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,
268 GTK_BUTTONS_YES_NO,
269 buffer);
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);
276 return;
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);
291 void
292 file_save_as_callback(gpointer data, guint action, GtkWidget *widget)
294 DDisplay *ddisp;
295 Diagram *dia;
297 ddisp = ddisplay_active();
298 if (!ddisp) return;
299 dia = ddisp->diagram;
301 if (!savedlg) {
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),
309 compressbutton);
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),
327 savedlg);
328 gtk_quit_add_destroy(1, GTK_OBJECT(savedlg));
329 } else {
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))
336 return;
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);
343 g_object_ref(dia);
344 gtk_widget_show(savedlg);
347 void
348 file_save_callback(gpointer data, guint action, GtkWidget *widget)
350 Diagram *diagram;
352 diagram = ddisplay_active_diagram();
353 if (!diagram) return;
355 if (diagram->unsaved) {
356 file_save_as_callback(data, action, widget);
357 } else {
358 diagram_update_extents(diagram);
359 diagram_save(diagram, diagram->filename);
363 static void
364 export_set_extension(GtkObject *item)
366 DiaExportFilter *ef = gtk_object_get_user_data(item);
367 GString *s;
368 const gchar *text = gtk_entry_get_text(GTK_ENTRY(GTK_FILE_SELECTION(exportdlg)
369 ->selection_entry));
370 const gchar *last_dot = strrchr(text, '.');
372 if (!ef || last_dot == text || text[0] == '\0' || ef->extensions[0] == NULL)
373 return;
375 s = g_string_new(text);
376 if (last_dot)
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),
381 s->str);
382 g_string_free (s, TRUE);
385 static GtkWidget *
386 create_export_menu(void)
388 GtkWidget *menu;
389 GtkWidget *item;
390 GList *tmp;
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;
403 gchar *filter_label;
405 if (!ef)
406 continue;
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);
416 return menu;
419 static void
420 file_export_ok_callback(GtkWidget *w, GtkFileSelection *fs)
422 const char *filename;
423 Diagram *dia;
424 DiaExportFilter *ef;
425 struct stat statbuf;
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;
434 char buffer[300];
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,
442 GTK_BUTTONS_YES_NO,
443 buffer);
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);
450 return;
452 gtk_widget_destroy(dialog);
455 ef = gtk_object_get_user_data(GTK_OBJECT(GTK_OPTION_MENU(export_omenu)
456 ->menu_item));
457 if (!ef)
458 ef = filter_guess_export_filter(filename);
459 if (ef) {
460 g_object_ref(dia->data);
461 ef->export_func(dia->data, filename, dia->filename, ef->user_data);
462 } else
463 message_error(_("Could not determine which export filter\n"
464 "to use to save '%s'"), filename);
466 file_dialog_hide(exportdlg);
469 void
470 file_export_callback(gpointer data, guint action, GtkWidget *widget)
472 DDisplay *ddisp;
473 Diagram *dia;
474 GtkWidget *export_menu, *export_item;
476 ddisp = ddisplay_active();
477 if (!ddisp) return;
478 dia = ddisp->diagram;
480 if (!exportdlg) {
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),
497 exportdlg);
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);
526 g_object_ref(dia);
527 gtk_widget_set_sensitive(exportdlg, TRUE);
528 if (GTK_WIDGET_VISIBLE(exportdlg))
529 return;
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));
535 if (export_item)
536 export_set_extension(GTK_OBJECT(export_item));
537 gtk_widget_show(export_options);
538 gtk_widget_show(exportdlg);