8b1c083e7e1f95e38398ac7a17c954cd81e59be9
[geeqie.git] / src / preferences.c
1 /*
2  * GQview
3  * (C) 2004 John Ellis
4  *
5  * Author: John Ellis
6  *
7  * This software is released under the GNU General Public License (GNU GPL).
8  * Please read the included file COPYING for more information.
9  * This software comes with no warranty of any kind, use at your own risk!
10  */
11
12
13 #include "gqview.h"
14 #include "preferences.h"
15
16 #include "cache_maint.h"
17 #include "editors.h"
18 #include "filelist.h"
19 #include "fullscreen.h"
20 #include "img-view.h"
21 #include "layout_config.h"
22 #include "layout_util.h"
23 #include "pixbuf_util.h"
24 #include "slideshow.h"
25 #include "utilops.h"
26 #include "ui_fileops.h"
27 #include "ui_misc.h"
28 #include "ui_tabcomp.h"
29 #include "ui_utildlg.h"
30
31 #include "icons/config.xpm"
32
33 #include <math.h>
34
35
36 #define EDITOR_NAME_MAX_LENGTH 32
37 #define EDITOR_COMMAND_MAX_LENGTH 1024
38
39
40 typedef struct _ThumbSize ThumbSize;
41 struct _ThumbSize
42 {
43         gint w;
44         gint h;
45 };
46
47 static ThumbSize thumb_size_list[] =
48 {
49         { 24, 24 },
50         { 32, 32 },
51         { 48, 48 },
52         { 64, 64 },
53         { 96, 72 },
54         { 96, 96 },
55         { 128, 96 },
56         { 128, 128 },
57         { 160, 120 },
58         { 160, 160 },
59         { 192, 144 },
60         { 192, 192 },
61         { 256, 192 },
62         { 256, 256 }
63 };
64
65 enum {
66         FE_ENABLE,
67         FE_EXTENSION,
68         FE_DESCRIPTION
69 };
70
71 /* config memory values */
72 static gint startup_path_enable_c;
73 static gint confirm_delete_c;
74 static gint enable_delete_key_c;
75 static gint safe_delete_enable_c;
76 static gint safe_delete_size_c;
77 static gint restore_tool_c;
78 static gint save_window_positions_c;
79 static gint zoom_mode_c;
80 static gint two_pass_zoom_c;
81 static gint fit_window_c;
82 static gint limit_window_size_c;
83 static gint zoom_to_fit_expands_c;
84 static gint max_window_size_c;
85 static gint progressive_key_scrolling_c;
86 static gint thumb_max_width_c;
87 static gint thumb_max_height_c;
88 static gint enable_thumb_caching_c;
89 static gint enable_thumb_dirs_c;
90 static gint use_xvpics_thumbnails_c;
91 static gint thumbnail_spec_standard_c;
92 static gint enable_metadata_dirs_c;
93 static gint show_dot_files_c;
94 static gint file_filter_disable_c;
95 static gint file_sort_case_sensitive_c;
96 static gint slideshow_delay_c;
97 static gint slideshow_random_c;
98 static gint slideshow_repeat_c;
99
100 static gint mousewheel_scrolls_c;
101
102 static gint enable_in_place_rename_c;
103
104 static gint collection_rectangular_selection_c;
105
106 static gint tile_cache_max_c;
107
108 static gint thumbnail_quality_c;
109 static gint zoom_quality_c;
110
111 static gint zoom_increment_c;
112
113 static gint enable_read_ahead_c;
114
115 static gint black_window_background_c;
116
117 static gint fullscreen_screen_c;
118 static gint fullscreen_clean_flip_c;
119 static gint fullscreen_disable_saver_c;
120 static gint fullscreen_above_c;
121
122 static gint dupe_custom_threshold_c;
123
124 static GtkWidget *configwindow = NULL;
125 static GtkWidget *startup_path_entry;
126 static GtkListStore *filter_store = NULL;
127 static GtkWidget *editor_name_entry[GQVIEW_EDITOR_SLOTS];
128 static GtkWidget *editor_command_entry[GQVIEW_EDITOR_SLOTS];
129
130 static GtkWidget *layout_widget;
131
132 static GtkWidget *safe_delete_path_entry;
133
134 static gint tree_descend_subdirs_c;
135
136 static gint update_on_time_change_c;
137 static gint exif_rotate_enable_c;
138
139
140 /*
141  *-----------------------------------------------------------------------------
142  * option widget callbacks (private)
143  *-----------------------------------------------------------------------------
144  */ 
145
146 static void startup_path_set_current(GtkWidget *widget, gpointer data)
147 {
148         gtk_entry_set_text(GTK_ENTRY(startup_path_entry), layout_get_path(NULL));
149 }
150
151 static void zoom_mode_original_cb(GtkWidget *widget, gpointer data)
152 {
153         if (GTK_TOGGLE_BUTTON (widget)->active)
154                 zoom_mode_c = ZOOM_RESET_ORIGINAL;
155 }
156
157 static void zoom_mode_fit_cb(GtkWidget *widget, gpointer data)
158 {
159         if (GTK_TOGGLE_BUTTON (widget)->active)
160                 zoom_mode_c = ZOOM_RESET_FIT_WINDOW;
161 }
162
163 static void zoom_mode_none_cb(GtkWidget *widget, gpointer data)
164 {
165         if (GTK_TOGGLE_BUTTON (widget)->active)
166                 zoom_mode_c = ZOOM_RESET_NONE;
167 }
168
169 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
170 {
171         zoom_increment_c = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 10.0 + 0.01);
172 }
173
174 static void slideshow_delay_cb(GtkWidget *spin, gpointer data)
175 {
176         slideshow_delay_c = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
177                                    (double)SLIDESHOW_SUBSECOND_PRECISION + 0.01);
178 }
179
180 /*
181  *-----------------------------------------------------------------------------
182  * sync progam to config window routine (private)
183  *-----------------------------------------------------------------------------
184  */ 
185
186 static void config_window_apply(void)
187 {
188         const gchar *buf;
189         gchar *l_conf;
190         gint new_style;
191         gint i;
192         gint refresh = FALSE;
193
194         for(i = 0; i < GQVIEW_EDITOR_SLOTS; i++)
195                 {
196                 g_free(editor_name[i]);
197                 editor_name[i] = NULL;
198                 buf = gtk_entry_get_text(GTK_ENTRY(editor_name_entry[i]));
199                 if (buf && strlen(buf) > 0) editor_name[i] = g_strdup(buf);
200
201                 g_free(editor_command[i]);
202                 editor_command[i] = NULL;
203                 buf = gtk_entry_get_text(GTK_ENTRY(editor_command_entry[i]));
204                 if (buf && strlen(buf) > 0) editor_command[i] = g_strdup(buf);
205                 }
206         layout_edit_update_all();
207
208         g_free(startup_path);
209         startup_path = NULL;
210         buf = gtk_entry_get_text(GTK_ENTRY(startup_path_entry));
211         if (buf && strlen(buf) > 0) startup_path = remove_trailing_slash(buf);
212
213         g_free(safe_delete_path);
214         safe_delete_path = NULL;
215         buf = gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry));
216         if (buf && strlen(buf) > 0) safe_delete_path = remove_trailing_slash(buf);
217
218         if (show_dot_files != show_dot_files_c) refresh = TRUE;
219         if (file_sort_case_sensitive != file_sort_case_sensitive_c) refresh = TRUE;
220         if (file_filter_disable != file_filter_disable_c) refresh = TRUE;
221
222         startup_path_enable = startup_path_enable_c;
223         confirm_delete = confirm_delete_c;
224         enable_delete_key = enable_delete_key_c;
225         safe_delete_enable = safe_delete_enable_c;
226         safe_delete_size = safe_delete_size_c;
227         restore_tool = restore_tool_c;
228         save_window_positions = save_window_positions_c;
229         zoom_mode = zoom_mode_c;
230         two_pass_zoom = two_pass_zoom_c;
231         fit_window = fit_window_c;
232         limit_window_size = limit_window_size_c;
233         zoom_to_fit_expands = zoom_to_fit_expands_c;
234         max_window_size = max_window_size_c;
235         progressive_key_scrolling = progressive_key_scrolling_c;
236         thumb_max_width = thumb_max_width_c;
237         thumb_max_height = thumb_max_height_c;
238         enable_thumb_caching = enable_thumb_caching_c;
239         enable_thumb_dirs = enable_thumb_dirs_c;
240         use_xvpics_thumbnails = use_xvpics_thumbnails_c;
241         thumbnail_spec_standard = thumbnail_spec_standard_c;
242         enable_metadata_dirs = enable_metadata_dirs_c;
243         show_dot_files = show_dot_files_c;
244         file_sort_case_sensitive = file_sort_case_sensitive_c;
245         file_filter_disable = file_filter_disable_c;
246
247         slideshow_random = slideshow_random_c;
248         slideshow_repeat = slideshow_repeat_c;
249         slideshow_delay = slideshow_delay_c;
250
251         mousewheel_scrolls = mousewheel_scrolls_c;
252
253         enable_in_place_rename = enable_in_place_rename_c;
254
255         collection_rectangular_selection = collection_rectangular_selection_c;
256
257         tile_cache_max = tile_cache_max_c;
258
259         thumbnail_quality = thumbnail_quality_c;
260         zoom_quality = zoom_quality_c;
261
262         zoom_increment = zoom_increment_c;
263
264         enable_read_ahead = enable_read_ahead_c;
265
266         if (black_window_background != black_window_background_c)
267                 {
268                 black_window_background = black_window_background_c;
269
270                 layout_colors_update();
271                 view_window_colors_update();
272                 }
273
274         fullscreen_screen = fullscreen_screen_c;
275         fullscreen_clean_flip = fullscreen_clean_flip_c;
276         fullscreen_disable_saver = fullscreen_disable_saver_c;
277         fullscreen_above = fullscreen_above_c;
278
279         update_on_time_change = update_on_time_change_c;
280         exif_rotate_enable = exif_rotate_enable_c;
281
282         dupe_custom_threshold = dupe_custom_threshold_c;
283
284         tree_descend_subdirs = tree_descend_subdirs_c;
285
286         l_conf = layout_config_get(layout_widget, &new_style);
287
288         if (new_style != layout_style ||
289             (l_conf == NULL) != (layout_order == NULL) ||
290             !layout_order ||
291             strcmp(buf, layout_order) != 0)
292                 {
293                 if (refresh) filter_rebuild();
294                 refresh = FALSE;
295
296                 g_free(layout_order);
297                 layout_order = l_conf;
298                 l_conf = NULL;
299
300                 layout_style = new_style;
301
302                 layout_styles_update();
303                 }
304
305         g_free(l_conf);
306
307         if (refresh)
308                 {
309                 filter_rebuild();
310                 layout_refresh(NULL);
311                 }
312 }
313
314 /*
315  *-----------------------------------------------------------------------------
316  * config window main button callbacks (private)
317  *-----------------------------------------------------------------------------
318  */ 
319
320 static void config_window_close_cb(GtkWidget *widget, gpointer data)
321 {
322         gtk_widget_destroy(configwindow);
323         configwindow = NULL;
324         filter_store = NULL;
325 }
326
327 static gint config_window_delete(GtkWidget *w, GdkEventAny *event, gpointer data)
328 {
329         config_window_close_cb(NULL, NULL);
330         return TRUE;
331 }
332
333 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
334 {
335         config_window_apply();
336         config_window_close_cb(NULL, NULL);
337 }
338
339 static void config_window_apply_cb(GtkWidget *widget, gpointer data)
340 {
341         config_window_apply();
342 }
343
344 /*
345  *-----------------------------------------------------------------------------
346  * config window setup (private)
347  *-----------------------------------------------------------------------------
348  */ 
349
350 static void quality_menu_cb(GtkWidget *combo, gpointer data)
351 {
352         gint *option = data;
353
354         switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
355                 {
356                 case 0:
357                 default:
358                         *option = GDK_INTERP_NEAREST;
359                         break;
360                 case 1:
361                         *option = GDK_INTERP_TILES;
362                         break;
363                 case 2:
364                         *option = GDK_INTERP_BILINEAR;
365                         break;
366                 case 3:
367                         *option = GDK_INTERP_HYPER;
368                         break;
369                 }
370 }
371
372 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
373                              gint option, gint *option_c)
374 {
375         GtkWidget *combo;
376         gint current = 0;
377
378         *option_c = option;
379
380         pref_table_label(table, column, row, text, 0.0);
381
382         combo = gtk_combo_box_new_text();
383
384         gtk_combo_box_append_text(GTK_COMBO_BOX(combo), _("Nearest (worst, but fastest)"));
385         if (option == GDK_INTERP_NEAREST) current = 0;
386         gtk_combo_box_append_text(GTK_COMBO_BOX(combo), _("Tiles"));
387         if (option == GDK_INTERP_TILES) current = 1;
388         gtk_combo_box_append_text(GTK_COMBO_BOX(combo), _("Bilinear"));
389         if (option == GDK_INTERP_BILINEAR) current = 2;
390         gtk_combo_box_append_text(GTK_COMBO_BOX(combo), _("Hyper (best, but slowest)"));
391         if (option == GDK_INTERP_HYPER) current = 3;
392
393         gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
394
395         g_signal_connect(G_OBJECT(combo), "changed",
396                          G_CALLBACK(quality_menu_cb), option_c);
397
398         gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
399                          GTK_EXPAND | GTK_FILL, FALSE, 0, 0);
400         gtk_widget_show(combo);
401 }
402
403 #if 0
404 static void add_dither_menu(gint option, gint *option_c, gchar *text, GtkWidget *box)
405 {
406         GtkWidget *hbox;
407         GtkWidget *omenu;
408         GtkWidget *menu;
409
410         *option_c = option;
411
412         hbox = pref_box_new(box, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
413         pref_label_new(hbox, text);
414
415         omenu = gtk_option_menu_new();
416         menu = gtk_menu_new();
417
418         add_menu_item(menu, _("None"), option_c, (gint)GDK_RGB_DITHER_NONE);
419         add_menu_item(menu, _("Normal"), option_c, (gint)GDK_RGB_DITHER_NORMAL);
420         add_menu_item(menu, _("Best"), option_c, (gint)GDK_RGB_DITHER_MAX);
421
422         gtk_option_menu_set_menu(GTK_OPTION_MENU(omenu), menu);
423         gtk_option_menu_set_history(GTK_OPTION_MENU(omenu), *option_c);
424
425         gtk_box_pack_start(GTK_BOX(hbox), omenu, FALSE, FALSE, 0);
426         gtk_widget_show(omenu);
427 }
428 #endif
429
430 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
431 {
432         gint n;
433
434         n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
435
436         if (n >= 0 && n < sizeof(thumb_size_list) / sizeof(ThumbSize))
437                 {
438                 thumb_max_width_c = thumb_size_list[n].w;
439                 thumb_max_height_c = thumb_size_list[n].h;
440                 }
441         else if (n > 0)
442                 {
443                 thumb_max_width_c = thumb_max_width;
444                 thumb_max_height_c = thumb_max_height;
445                 }
446 }
447
448 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
449 {
450         GtkWidget *combo;
451         gint current;
452         gint last_w, last_h;
453         gint i;
454         gint c;
455
456         thumb_max_width_c = thumb_max_width;
457         thumb_max_height_c = thumb_max_height;
458
459         pref_table_label(table, column, row, text, 0.0);
460
461         combo = gtk_combo_box_new_text();
462
463         last_w = last_h = 0;
464         current = -1;
465         i = 0;
466         c = TRUE;
467         while (c)
468                 {
469                 gint w, h;
470
471                 w = thumb_size_list[i].w;
472                 h = thumb_size_list[i].h;
473
474                 if ( w > 0 && h > 0)
475                         {
476                         gchar *buf;
477
478                         buf = g_strdup_printf("%d x %d", w, h);
479                         gtk_combo_box_append_text(GTK_COMBO_BOX(combo), buf);
480                         g_free(buf);
481
482                         if (w == thumb_max_width && h == thumb_max_height) current = i;
483
484                         last_w = w;
485                         last_h = h;
486                         }
487                 else
488                         {
489                         c = FALSE;
490                         }
491                 i++;
492                 }
493
494         if (current == -1)
495                 {
496                 gchar *buf;
497
498                 buf = g_strdup_printf("%s %d x %d", _("Custom"), thumb_max_width, thumb_max_height);
499                 gtk_combo_box_append_text(GTK_COMBO_BOX(combo), buf);
500                 g_free(buf);
501
502                 current = i - 1;
503                 }
504
505         gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
506         g_signal_connect(G_OBJECT(combo), "changed",
507                          G_CALLBACK(thumb_size_menu_cb), NULL);
508
509         gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
510                          GTK_EXPAND | GTK_FILL, FALSE, 0, 0);
511         gtk_widget_show(combo);
512 }
513
514 static void filter_store_populate(void)
515 {
516         GList *work;
517
518         if (!filter_store) return;
519
520         gtk_list_store_clear(filter_store);
521
522         work = filter_get_list();
523         while (work)
524                 {
525                 FilterEntry *fe;
526                 GtkTreeIter iter;
527
528                 fe = work->data;
529                 work = work->next;
530
531                 gtk_list_store_append(filter_store, &iter);
532                 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
533                 }
534 }
535
536 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
537                                      gchar *new_text, gpointer data)
538 {
539         GtkWidget *model = data;
540         FilterEntry *fe = data;
541         GtkTreePath *tpath;
542         GtkTreeIter iter;
543
544         if (!new_text || strlen(new_text) < 1) return;
545
546         tpath = gtk_tree_path_new_from_string(path_str);
547         gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
548         gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
549
550         g_free(fe->extensions);
551         fe->extensions = g_strdup(new_text);
552
553         gtk_tree_path_free(tpath);
554         filter_rebuild();
555 }
556
557 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
558                                       gchar *new_text, gpointer data)
559 {
560         GtkWidget *model = data;
561         FilterEntry *fe;
562         GtkTreePath *tpath;
563         GtkTreeIter iter;
564
565         if (!new_text || strlen(new_text) < 1) return;
566
567         tpath = gtk_tree_path_new_from_string(path_str);
568         gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
569         gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
570
571         g_free(fe->description);
572         fe->description = g_strdup(new_text);
573
574         gtk_tree_path_free(tpath);
575 }
576
577 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
578                                    gchar *path_str, gpointer data)
579 {
580         GtkWidget *model = data;
581         FilterEntry *fe;
582         GtkTreePath *tpath;
583         GtkTreeIter iter;
584
585         tpath = gtk_tree_path_new_from_string(path_str);
586         gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
587         gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
588
589         fe->enabled = !fe->enabled;
590
591         gtk_tree_path_free(tpath);
592         filter_rebuild();
593 }
594
595 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
596                             GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
597 {
598         FilterEntry *fe;
599
600         gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
601
602         switch(GPOINTER_TO_INT(data))
603                 {
604                 case FE_ENABLE:
605                         g_object_set(GTK_CELL_RENDERER(cell),
606                                      "active", fe->enabled, NULL);
607                         break;
608                 case FE_EXTENSION:
609                         g_object_set(GTK_CELL_RENDERER(cell),
610                                      "text", fe->extensions, NULL);
611                         break;
612                 case FE_DESCRIPTION:
613                         g_object_set(GTK_CELL_RENDERER(cell),
614                                      "text", fe->description, NULL);
615                         break;
616                 }
617 }
618
619 static void filter_add_cb(GtkWidget *widget, gpointer data)
620 {
621         filter_add_unique("description", ".new", TRUE);
622         filter_store_populate();
623
624         /* FIXME: implement the scroll to/select row stuff for tree view */
625 }
626
627 static void filter_remove_cb(GtkWidget *widget, gpointer data)
628 {
629         GtkWidget *filter_view = data;
630         GtkTreeSelection *selection;
631         GtkTreeIter iter;
632         FilterEntry *fe;
633
634         if (!filter_store) return;
635         selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
636         if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
637         gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
638         if (!fe) return;
639
640         filter_remove_entry(fe);
641         filter_rebuild();
642         filter_store_populate();
643 }
644
645 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
646 {
647         filter_reset();
648         filter_add_defaults();
649         filter_rebuild();
650         filter_store_populate();
651 }
652
653 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
654 {
655         /* no op, only so cancel button appears */
656 }
657
658 static void filter_default_cb(GtkWidget *widget, gpointer data)
659 {
660         GenericDialog *gd;
661
662         gd = generic_dialog_new(_("Reset filters"),
663                                 "GQview", "reset_filter", widget, TRUE,
664                                 dummy_cancel_cb, NULL);
665         generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
666                                    _("This will reset the file filters to the defaults.\nContinue?"));
667         generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
668         gtk_widget_show(gd->dialog);
669 }
670
671 static void filter_disable_cb(GtkWidget* widget, gpointer data)
672 {
673         GtkWidget *frame = data;
674
675         gtk_widget_set_sensitive(frame,
676                                  !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
677 }
678
679 static void editor_default_ok_cb(GenericDialog *gd, gpointer data)
680 {
681         gint i;
682
683         editor_reset_defaults();
684         if (!configwindow) return;
685
686         for (i = 0; i < GQVIEW_EDITOR_SLOTS; i++)
687                 {
688                 gtk_entry_set_text(GTK_ENTRY(editor_name_entry[i]),
689                                    (editor_name[i]) ? editor_name[i] : "");
690                 gtk_entry_set_text(GTK_ENTRY(editor_command_entry[i]),
691                                    (editor_command[i]) ? editor_command[i] : "");
692                 }
693 }
694
695 static void editor_default_cb(GtkWidget *widget, gpointer data)
696 {
697         GenericDialog *gd;
698
699         gd = generic_dialog_new(_("Reset editors"),
700                                 "GQview", "reset_filter", widget, TRUE,
701                                 dummy_cancel_cb, NULL);
702         generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset editors"),
703                                    _("This will reset the edit commands to the defaults.\nContinue?"));
704         generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, editor_default_ok_cb, TRUE);
705         gtk_widget_show(gd->dialog);
706 }
707
708 static void editor_help_cb(GtkWidget *widget, gpointer data)
709 {
710         help_window_show("editors");
711 }
712
713 static void safe_delete_view_cb(GtkWidget* widget, gpointer data)
714 {
715         layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
716 }
717
718 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
719 {
720         file_util_trash_clear();
721 }
722
723 static void safe_delete_clear_cb(GtkWidget* widget, gpointer data)
724 {
725         GenericDialog *gd;
726         GtkWidget *entry;
727         gd = generic_dialog_new(_("Clear trash"),
728                                 "GQview", "clear_trash", widget, TRUE,
729                                 dummy_cancel_cb, NULL);
730         generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
731                                     _("This will remove the trash contents."));
732         generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
733         entry = gtk_entry_new();
734         GTK_WIDGET_UNSET_FLAGS(entry, GTK_CAN_FOCUS);
735         gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
736         if (safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), safe_delete_path);
737         gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
738         gtk_widget_show(entry);
739         gtk_widget_show(gd->dialog);
740 }
741
742 static void config_window_create(void)
743 {
744         GtkWidget *win_vbox;
745         GtkWidget *hbox;
746         GtkWidget *notebook;
747         GtkWidget *frame;
748         GtkWidget *label;
749         GtkWidget *vbox;
750         GtkWidget *group;
751         GtkWidget *subgroup;
752         GtkWidget *button;
753         GtkWidget *tabcomp;
754         GtkWidget *ct_button;
755         GtkWidget *table;
756         GtkWidget *spin;
757         GtkWidget *scrolled;
758         GtkWidget *viewport;
759         GtkWidget *filter_view;
760         GtkCellRenderer *renderer;
761         GtkTreeSelection *selection;
762         GtkTreeViewColumn *column;
763         gint i;
764
765         configwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
766         gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
767         g_signal_connect(G_OBJECT (configwindow), "delete_event",
768                          G_CALLBACK(config_window_delete), NULL);
769         gtk_window_set_resizable(GTK_WINDOW(configwindow), FALSE);
770         gtk_window_set_title(GTK_WINDOW(configwindow), _("GQview Preferences"));
771         gtk_window_set_wmclass(GTK_WINDOW(configwindow), "config", "GQview");
772         gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
773
774         window_set_icon(configwindow, (const gchar **)config_xpm, NULL);
775
776         win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
777         gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
778         gtk_widget_show(win_vbox);
779
780         hbox = gtk_hbutton_box_new();
781         gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
782         gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
783         gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
784         gtk_widget_show(hbox);
785
786         button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
787                                  G_CALLBACK(config_window_ok_cb), NULL);
788         gtk_container_add(GTK_CONTAINER(hbox), button);
789         GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
790         gtk_widget_grab_default(button);
791         gtk_widget_show(button);
792
793         ct_button = button;
794
795         button = pref_button_new(NULL, GTK_STOCK_APPLY, NULL, FALSE,
796                                  G_CALLBACK(config_window_apply_cb), NULL);
797         gtk_container_add(GTK_CONTAINER(hbox), button);
798         GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
799         gtk_widget_show(button);
800
801         button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
802                                  G_CALLBACK(config_window_close_cb), NULL);
803         gtk_container_add(GTK_CONTAINER(hbox), button);
804         GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
805         gtk_widget_show(button);
806
807         if (!generic_dialog_get_alternative_button_order(configwindow))
808                 {
809                 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
810                 }
811
812         notebook = gtk_notebook_new();
813         gtk_notebook_set_tab_pos (GTK_NOTEBOOK(notebook), GTK_POS_TOP);
814         gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
815
816         /* general options tab */
817
818         vbox = gtk_vbox_new(FALSE, 0);
819         gtk_container_set_border_width(GTK_CONTAINER(vbox), PREF_PAD_BORDER);
820         gtk_widget_show(vbox);
821         label = gtk_label_new(_("General"));
822         gtk_notebook_append_page (GTK_NOTEBOOK(notebook), vbox, label);
823
824         group = pref_group_new(vbox, FALSE, _("Startup"), GTK_ORIENTATION_VERTICAL);
825
826         button = pref_checkbox_new_int(group, _("Change to folder:"),
827                                        startup_path_enable, &startup_path_enable_c);
828
829         hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
830         pref_checkbox_link_sensitivity(button, hbox);
831
832         tabcomp = tab_completion_new(&startup_path_entry, startup_path, NULL, NULL);
833         tab_completion_add_select_button(startup_path_entry, NULL, TRUE);
834         gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
835         gtk_widget_show(tabcomp);
836
837         button = pref_button_new(hbox, NULL, _("Use current"), FALSE,
838                                  G_CALLBACK(startup_path_set_current), NULL);
839
840         group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
841
842         table = pref_table_new(group, 2, 2, FALSE, FALSE);
843         add_thumb_size_menu(table, 0, 0, _("Size:"));
844         add_quality_menu(table, 0, 1, _("Quality:"), thumbnail_quality, &thumbnail_quality_c);
845
846         ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
847                                           enable_thumb_caching, &enable_thumb_caching_c);
848
849         subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
850         pref_checkbox_link_sensitivity(ct_button, subgroup);
851
852         button = pref_checkbox_new_int(subgroup, _("Use shared thumbnail cache"),
853                                        thumbnail_spec_standard, &thumbnail_spec_standard_c);
854
855         subgroup = pref_box_new(subgroup, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
856         pref_checkbox_link_sensitivity_swap(button, subgroup);
857
858         button = pref_checkbox_new_int(subgroup, _("Cache thumbnails into .thumbnails"),
859                                        enable_thumb_dirs, &enable_thumb_dirs_c);
860
861         button = pref_checkbox_new_int(subgroup, _("Use xvpics thumbnails when found (read only)"),
862                                        use_xvpics_thumbnails, &use_xvpics_thumbnails_c);
863
864         group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
865
866         slideshow_delay_c = slideshow_delay;
867         spin = pref_spin_new(group, _("Delay between image change:"), _("seconds"),
868                              SLIDESHOW_MIN_SECONDS, SLIDESHOW_MAX_SECONDS, 1.0, 1,
869                              slideshow_delay ? (double)slideshow_delay / SLIDESHOW_SUBSECOND_PRECISION : 10.0,
870                              G_CALLBACK(slideshow_delay_cb), NULL);
871         gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
872
873         pref_checkbox_new_int(group, _("Random"), slideshow_random, &slideshow_random_c);
874         pref_checkbox_new_int(group, _("Repeat"), slideshow_repeat, &slideshow_repeat_c);
875
876         /* image tab */
877
878         vbox = gtk_vbox_new(FALSE, 0);
879         gtk_container_set_border_width(GTK_CONTAINER(vbox), PREF_PAD_BORDER);
880         gtk_widget_show(vbox);
881         label = gtk_label_new(_("Image"));
882         gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox, label);
883
884         group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
885
886 #if 0
887         add_dither_menu(dither_quality, &dither_quality_c, _("Dithering method:"), group);
888 #endif
889         table = pref_table_new(group, 2, 1, FALSE, FALSE);
890         add_quality_menu(table, 0, 0, _("Quality:"), zoom_quality, &zoom_quality_c);
891
892         pref_checkbox_new_int(group, _("Two pass zooming"),
893                               two_pass_zoom, &two_pass_zoom_c);
894
895         pref_checkbox_new_int(group, _("Allow enlargement of image for zoom to fit."),
896                               zoom_to_fit_expands, &zoom_to_fit_expands_c);
897
898         zoom_increment_c = zoom_increment;
899         spin = pref_spin_new(group, _("Zoom increment:"), NULL,
900                              0.1, 4.0, 1.0, 1, (float)zoom_increment / 10.0,
901                              G_CALLBACK(zoom_increment_cb), NULL);
902         gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
903
904         group = pref_group_new(vbox, FALSE, _("When new image is selected:"), GTK_ORIENTATION_VERTICAL);
905
906         zoom_mode_c = zoom_mode;
907         button = pref_radiobutton_new(group, NULL, _("Zoom to original size"),
908                                       (zoom_mode == ZOOM_RESET_ORIGINAL),
909                                       G_CALLBACK(zoom_mode_original_cb), NULL);
910         button = pref_radiobutton_new(group, button, _("Fit image to window"),
911                                       (zoom_mode == ZOOM_RESET_FIT_WINDOW),
912                                       G_CALLBACK(zoom_mode_fit_cb), NULL);
913         button = pref_radiobutton_new(group, button, _("Leave Zoom at previous setting"),
914                                       (zoom_mode == ZOOM_RESET_NONE),
915                                       G_CALLBACK(zoom_mode_none_cb), NULL);
916
917         group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
918
919         pref_checkbox_new_int(group, _("Black background"),
920                               black_window_background, &black_window_background_c);
921
922         group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
923
924         pref_checkbox_new_int(group, _("Refresh on file change"),
925                               update_on_time_change, &update_on_time_change_c);
926         pref_checkbox_new_int(group, _("Preload next image"),
927                               enable_read_ahead, &enable_read_ahead_c);
928         pref_checkbox_new_int(group, _("Auto rotate image using Exif information"),
929                               exif_rotate_enable, &exif_rotate_enable_c);
930
931
932         /* window tab */
933
934         vbox = gtk_vbox_new(FALSE, 0);
935         gtk_container_set_border_width(GTK_CONTAINER(vbox), PREF_PAD_BORDER);
936         gtk_widget_show(vbox);
937         label = gtk_label_new(_("Windows"));
938         gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label);
939
940         group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
941
942         pref_checkbox_new_int(group, _("Remember window positions"),
943                               save_window_positions, &save_window_positions_c);
944         pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
945                               restore_tool, &restore_tool_c);
946
947         group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
948
949         pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
950                               fit_window, &fit_window_c);
951
952         hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
953         ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
954                                           limit_window_size, &limit_window_size_c);
955         spin = pref_spin_new_int(hbox, NULL, NULL,
956                                  10, 150, 1,
957                                  max_window_size, &max_window_size_c);
958         pref_checkbox_link_sensitivity(ct_button, spin);
959
960         group = pref_group_new(vbox, FALSE, _("Layout"), GTK_ORIENTATION_VERTICAL);
961
962         layout_widget = layout_config_new();
963         layout_config_set(layout_widget, layout_style, layout_order);
964         gtk_box_pack_start(GTK_BOX(group), layout_widget, FALSE, FALSE, 0);
965         gtk_widget_show(layout_widget);
966
967
968         /* filtering tab */
969
970         vbox = gtk_vbox_new(FALSE, 0);
971         gtk_container_set_border_width(GTK_CONTAINER (vbox), PREF_PAD_BORDER);
972         gtk_widget_show(vbox);
973         label = gtk_label_new(_("Filtering"));
974         gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label);
975
976         group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
977
978         pref_checkbox_new_int(group, _("Show entries that begin with a dot"),
979                               show_dot_files, &show_dot_files_c);
980         pref_checkbox_new_int(group, _("Case sensitive sort"),
981                               file_sort_case_sensitive, &file_sort_case_sensitive_c);
982
983         ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
984                                           file_filter_disable, &file_filter_disable_c);
985
986         group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
987
988         frame = pref_group_parent(group);
989         g_signal_connect(G_OBJECT(ct_button), "toggled",
990                          G_CALLBACK(filter_disable_cb), frame);
991         gtk_widget_set_sensitive(frame, !file_filter_disable);
992
993         scrolled = gtk_scrolled_window_new(NULL, NULL);
994         gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
995         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
996         gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
997         gtk_widget_show(scrolled);
998
999         filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
1000         filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
1001         g_object_unref(filter_store);
1002         selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1003         gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
1004
1005         gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
1006
1007         column = gtk_tree_view_column_new();
1008         gtk_tree_view_column_set_title(column, _("Filter"));
1009         gtk_tree_view_column_set_resizable(column, TRUE);
1010
1011         renderer = gtk_cell_renderer_toggle_new();
1012         g_signal_connect(G_OBJECT(renderer), "toggled",
1013                          G_CALLBACK(filter_store_enable_cb), filter_store);
1014         gtk_tree_view_column_pack_start(column, renderer, FALSE);
1015         gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
1016                                                 GINT_TO_POINTER(FE_ENABLE), NULL);
1017         
1018         renderer = gtk_cell_renderer_text_new();
1019         g_signal_connect(G_OBJECT(renderer), "edited",
1020                          G_CALLBACK(filter_store_ext_edit_cb), filter_store);
1021         gtk_tree_view_column_pack_start(column, renderer, TRUE);
1022         g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
1023         gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
1024                                                 GINT_TO_POINTER(FE_EXTENSION), NULL);
1025         gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
1026
1027         column = gtk_tree_view_column_new();
1028         gtk_tree_view_column_set_title(column, _("Description"));
1029         gtk_tree_view_column_set_resizable(column, TRUE);
1030         renderer = gtk_cell_renderer_text_new();
1031         g_signal_connect(G_OBJECT(renderer), "edited",
1032                          G_CALLBACK(filter_store_desc_edit_cb), filter_store);
1033         g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
1034         gtk_tree_view_column_pack_start(column, renderer, FALSE);
1035         gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
1036                                                 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
1037         gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
1038
1039         filter_store_populate();
1040         gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
1041         gtk_widget_show(filter_view);
1042
1043         hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
1044
1045         button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
1046                                  G_CALLBACK(filter_default_cb), NULL);
1047         gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1048         gtk_widget_show(button);
1049
1050         button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
1051                                  G_CALLBACK(filter_remove_cb), filter_view);
1052         gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1053         gtk_widget_show(button);
1054
1055         button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
1056                                  G_CALLBACK(filter_add_cb), NULL);
1057         gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1058         gtk_widget_show(button);
1059
1060
1061         /* editor entry tab */
1062
1063         vbox = gtk_vbox_new(FALSE, PREF_PAD_GAP);
1064         gtk_container_set_border_width(GTK_CONTAINER(vbox), PREF_PAD_BORDER);
1065         gtk_widget_show(vbox);
1066         label = gtk_label_new(_("Editors"));
1067         gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label);
1068
1069         table = pref_table_new(vbox, 3, 9, FALSE, FALSE);
1070         gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
1071
1072         label = pref_table_label(table, 0, 0, _("#"), 1.0);
1073         pref_label_bold(label, TRUE, FALSE);
1074
1075         label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
1076         pref_label_bold(label, TRUE, FALSE);
1077
1078         label = pref_table_label(table, 2, 0, ("Command Line"), 0.0);
1079         pref_label_bold(label, TRUE, FALSE);
1080
1081         for (i = 0; i < GQVIEW_EDITOR_SLOTS; i++)
1082                 {
1083                 gchar *buf;
1084
1085                 buf = g_strdup_printf("%d", i+1);
1086                 pref_table_label(table, 0, i+1, buf, 1.0);
1087                 g_free(buf);
1088
1089                 editor_name_entry[i] = gtk_entry_new();
1090                 gtk_entry_set_max_length(GTK_ENTRY(editor_name_entry[i]), EDITOR_NAME_MAX_LENGTH);
1091                 gtk_widget_set_size_request(editor_name_entry[i],80,-1);
1092                 if (editor_name[i]) gtk_entry_set_text(GTK_ENTRY(editor_name_entry[i]),editor_name[i]);
1093                 gtk_table_attach(GTK_TABLE (table),editor_name_entry[i],1,2,i+1,i+2,
1094                                  GTK_FILL | GTK_EXPAND, FALSE, 0, 0);
1095                 gtk_widget_show(editor_name_entry[i]);
1096
1097                 editor_command_entry[i] = gtk_entry_new();
1098                 gtk_entry_set_max_length(GTK_ENTRY(editor_command_entry[i]), EDITOR_COMMAND_MAX_LENGTH);
1099                 gtk_widget_set_size_request(editor_command_entry[i],160,-1);
1100                 tab_completion_add_to_entry(editor_command_entry[i], NULL, NULL);
1101                 if (editor_command[i]) gtk_entry_set_text(GTK_ENTRY(editor_command_entry[i]), editor_command[i]);
1102                 gtk_table_attach(GTK_TABLE (table),editor_command_entry[i],2,3,i+1,i+2,
1103                                  GTK_FILL | GTK_EXPAND, FALSE, 0, 0);
1104                 gtk_widget_show(editor_command_entry[i]);
1105                 }
1106
1107         hbox = pref_box_new(vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
1108
1109         button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
1110                                  G_CALLBACK(editor_default_cb), NULL);
1111         gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1112         gtk_widget_show(button);
1113
1114         button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
1115                                  G_CALLBACK(editor_help_cb), NULL);
1116         gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1117         gtk_widget_show(button);
1118
1119         /* advanced entry tab */
1120
1121         scrolled = gtk_scrolled_window_new(NULL, NULL);
1122         gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1123         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1124                                        GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1125         label = gtk_label_new(_("Advanced"));
1126         gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1127         gtk_widget_show(scrolled);
1128
1129         viewport = gtk_viewport_new(NULL, NULL);
1130         gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1131         gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1132         gtk_widget_show(viewport);
1133
1134         vbox = gtk_vbox_new(FALSE, 0);
1135         gtk_container_add(GTK_CONTAINER(viewport), vbox);
1136         gtk_widget_show(vbox);
1137
1138         group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
1139
1140         fullscreen_screen_c = fullscreen_screen;
1141         fullscreen_above_c = fullscreen_above;
1142         hbox = fullscreen_prefs_selection_new(_("Location:"), &fullscreen_screen_c, &fullscreen_above_c);
1143         gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
1144         gtk_widget_show(hbox);
1145
1146         pref_checkbox_new_int(group, _("Smooth image flip"),
1147                               fullscreen_clean_flip, &fullscreen_clean_flip_c);
1148         pref_checkbox_new_int(group, _("Disable screen saver"),
1149                               fullscreen_disable_saver, &fullscreen_disable_saver_c);
1150
1151         group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
1152
1153         pref_checkbox_new_int(group, _("Confirm file delete"),
1154                               confirm_delete, &confirm_delete_c);
1155         pref_checkbox_new_int(group, _("Enable Delete key"),
1156                               enable_delete_key, &enable_delete_key_c);
1157
1158         ct_button = pref_checkbox_new_int(group, _("Safe delete"),
1159                                           safe_delete_enable, &safe_delete_enable_c);
1160
1161         hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1162         pref_checkbox_link_sensitivity(ct_button, hbox);
1163
1164         pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
1165         pref_label_new(hbox, _("Folder:"));
1166
1167         tabcomp = tab_completion_new(&safe_delete_path_entry, safe_delete_path, NULL, NULL);
1168         tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
1169         gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
1170         gtk_widget_show(tabcomp);
1171
1172         hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
1173         pref_checkbox_link_sensitivity(ct_button, hbox);
1174
1175         pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
1176         pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
1177                           1, 500, 1, safe_delete_size, &safe_delete_size_c);
1178
1179         button = pref_button_new(NULL, NULL, _("View"), FALSE,
1180                                  G_CALLBACK(safe_delete_view_cb), NULL);
1181         gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1182         gtk_widget_show(button);
1183
1184         button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
1185                                  G_CALLBACK(safe_delete_clear_cb), NULL);
1186         gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1187         gtk_widget_show(button);
1188
1189         group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
1190
1191         pref_checkbox_new_int(group, _("Rectangular selection in icon view"),
1192                               collection_rectangular_selection, &collection_rectangular_selection_c);
1193
1194         pref_checkbox_new_int(group, _("Descend folders in tree view"),
1195                               tree_descend_subdirs, &tree_descend_subdirs_c);
1196
1197         pref_checkbox_new_int(group, _("In place renaming"),
1198                               enable_in_place_rename, &enable_in_place_rename_c);
1199
1200         group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
1201
1202         pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
1203                               progressive_key_scrolling, &progressive_key_scrolling_c);
1204         pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
1205                               mousewheel_scrolls, &mousewheel_scrolls_c);
1206
1207         group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
1208
1209         pref_checkbox_new_int(group, _("Store keywords and comments local to source images"),
1210                               enable_metadata_dirs, &enable_metadata_dirs_c);
1211
1212         pref_spin_new_int(group, _("Custom similarity threshold:"), NULL,
1213                           0, 100, 1, dupe_custom_threshold, &dupe_custom_threshold_c);
1214
1215         pref_spin_new_int(group, _("Offscreen cache size (Mb per image):"), NULL,
1216                           0, 128, 1, tile_cache_max, &tile_cache_max_c);
1217
1218         gtk_widget_show(notebook);
1219
1220         gtk_widget_show(configwindow);
1221 }
1222
1223 /*
1224  *-----------------------------------------------------------------------------
1225  * config window show (public)
1226  *-----------------------------------------------------------------------------
1227  */ 
1228
1229 void show_config_window(void)
1230 {
1231         if (configwindow)
1232                 {
1233                 gtk_window_present(GTK_WINDOW(configwindow));
1234                 return;
1235                 }
1236
1237         config_window_create();
1238 }
1239
1240 /*
1241  *-----------------
1242  * about window
1243  *-----------------
1244  */
1245
1246 static GtkWidget *about = NULL;
1247
1248 static gint about_delete_cb(GtkWidget *widget, GdkEventAny *event, gpointer data)
1249 {
1250         gtk_widget_destroy(about);
1251         about = NULL;
1252
1253         return TRUE;
1254 }
1255
1256 static void about_window_close(GtkWidget *widget, gpointer data)
1257 {
1258         if (!about) return;
1259
1260         gtk_widget_destroy(about);
1261         about = NULL;
1262 }
1263
1264 static void about_credits_cb(GtkWidget *widget, gpointer data)
1265 {
1266         help_window_show("credits");
1267 }
1268
1269 void show_about_window(void)
1270 {
1271         GtkWidget *vbox;
1272         GtkWidget *hbox;
1273         GtkWidget *label;
1274         GtkWidget *button;
1275         GdkPixbuf *pixbuf;
1276
1277         gchar *buf;
1278
1279         if (about)
1280                 {
1281                 gtk_window_present(GTK_WINDOW(about));
1282                 return;
1283                 }
1284
1285         about = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1286         gtk_window_set_type_hint(GTK_WINDOW(about), GDK_WINDOW_TYPE_HINT_DIALOG);
1287         gtk_window_set_wmclass(GTK_WINDOW(about), "about", "GQview");
1288         g_signal_connect(G_OBJECT(about), "delete_event",
1289                          G_CALLBACK(about_delete_cb), NULL);
1290
1291         gtk_window_set_title(GTK_WINDOW(about), _("About - GQview"));
1292         gtk_container_set_border_width(GTK_CONTAINER(about), PREF_PAD_BORDER);
1293
1294         vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
1295         gtk_container_add(GTK_CONTAINER(about), vbox);
1296         gtk_widget_show(vbox);
1297
1298         pixbuf = pixbuf_inline(PIXBUF_INLINE_LOGO);
1299         button = gtk_image_new_from_pixbuf(pixbuf);
1300         g_object_unref(pixbuf);
1301         gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);
1302         gtk_widget_show(button);
1303
1304         buf = g_strdup_printf(_("GQview %s\n\nCopyright (c) %s John Ellis\nwebsite: %s\nemail: %s\n\nReleased under the GNU General Public License"),
1305                               VERSION,
1306                               "2005",
1307                               "gqview.sourceforge.net",
1308                               "gqview@users.sourceforge.net");
1309         label = gtk_label_new(buf);
1310         g_free(buf);
1311
1312         gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
1313         gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
1314         gtk_widget_show(label);
1315
1316         hbox = gtk_hbutton_box_new();
1317         gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
1318         gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
1319         gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1320         gtk_widget_show(hbox);
1321
1322         button = pref_button_new(NULL, NULL, _("Credits..."), FALSE,
1323                                  G_CALLBACK(about_credits_cb), NULL);
1324         gtk_container_add(GTK_CONTAINER(hbox), button);
1325         GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1326         gtk_widget_show(button);
1327
1328         button = pref_button_new(NULL, GTK_STOCK_CLOSE, NULL, FALSE,
1329                                  G_CALLBACK(about_window_close), NULL);
1330         gtk_container_add(GTK_CONTAINER(hbox), button);
1331         GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1332         gtk_widget_grab_default(button);
1333         gtk_widget_show(button);
1334
1335         window_set_icon(about, NULL, NULL);
1336         gtk_widget_show(about);
1337 }
1338