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