Use GQ_EDITOR_GENERIC_SLOTS instead of hardcoded value.
[geeqie.git] / src / layout_util.c
1 /*
2  * Geeqie
3  * (C) 2004 John Ellis
4  * Copyright (C) 2008 The Geeqie Team
5  *
6  * Author: John Ellis
7  *
8  * This software is released under the GNU General Public License (GNU GPL).
9  * Please read the included file COPYING for more information.
10  * This software comes with no warranty of any kind, use at your own risk!
11  */
12
13
14 #include "main.h"
15 #include "layout_util.h"
16
17 #include "bar_info.h"
18 #include "bar_exif.h"
19 #include "bar_sort.h"
20 #include "cache_maint.h"
21 #include "collect.h"
22 #include "collect-dlg.h"
23 #include "compat.h"
24 #include "dupe.h"
25 #include "editors.h"
26 #include "filelist.h"
27 #include "image-overlay.h"
28 #include "img-view.h"
29 #include "info.h"
30 #include "layout_image.h"
31 #include "pan-view.h"
32 #include "pixbuf_util.h"
33 #include "preferences.h"
34 #include "print.h"
35 #include "search.h"
36 #include "utilops.h"
37 #include "ui_bookmark.h"
38 #include "ui_fileops.h"
39 #include "ui_menu.h"
40 #include "ui_misc.h"
41 #include "ui_tabcomp.h"
42 #include "view_dir.h"
43
44 #include <gdk/gdkkeysyms.h> /* for keyboard values */
45
46
47 #define MENU_EDIT_ACTION_OFFSET 16
48
49
50 /*
51  *-----------------------------------------------------------------------------
52  * keyboard handler
53  *-----------------------------------------------------------------------------
54  */
55
56 static guint tree_key_overrides[] = {
57         GDK_Page_Up,    GDK_KP_Page_Up,
58         GDK_Page_Down,  GDK_KP_Page_Down,
59         GDK_Home,       GDK_KP_Home,
60         GDK_End,        GDK_KP_End
61 };
62
63 static gint layout_key_match(guint keyval)
64 {
65         gint i;
66
67         for (i = 0; i < sizeof(tree_key_overrides) / sizeof(guint); i++)
68                 {
69                 if (keyval == tree_key_overrides[i]) return TRUE;
70                 }
71
72         return FALSE;
73 }
74
75 gint layout_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
76 {
77         LayoutWindow *lw = data;
78         gint stop_signal = FALSE;
79         gint x = 0;
80         gint y = 0;
81
82         if (lw->path_entry && GTK_WIDGET_HAS_FOCUS(lw->path_entry))
83                 {
84                 if (event->keyval == GDK_Escape && lw->path)
85                         {
86                         gtk_entry_set_text(GTK_ENTRY(lw->path_entry), lw->path);
87                         }
88
89                 /* the gtkaccelgroup of the window is stealing presses before they get to the entry (and more),
90                  * so when the some widgets have focus, give them priority (HACK)
91                  */
92                 if (gtk_widget_event(lw->path_entry, (GdkEvent *)event))
93                         {
94                         return TRUE;
95                         }
96                 }
97         if (lw->vd && lw->dir_view_type == DIRVIEW_TREE && GTK_WIDGET_HAS_FOCUS(lw->vd->view) &&
98             !layout_key_match(event->keyval) &&
99             gtk_widget_event(lw->vd->view, (GdkEvent *)event))
100                 {
101                 return TRUE;
102                 }
103         if (lw->bar_info &&
104             bar_info_event(lw->bar_info, (GdkEvent *)event))
105                 {
106                 return TRUE;
107                 }
108
109 /*
110         if (event->type == GDK_KEY_PRESS && lw->full_screen &&
111             gtk_accel_groups_activate(G_OBJECT(lw->window), event->keyval, event->state))
112                 return TRUE;
113 */
114
115         if (lw->image &&
116             (GTK_WIDGET_HAS_FOCUS(lw->image->widget) || (lw->tools && widget == lw->window) || lw->full_screen) )
117                 {
118                 stop_signal = TRUE;
119                 switch (event->keyval)
120                         {
121                         case GDK_Left: case GDK_KP_Left:
122                                 x -= 1;
123                                 break;
124                         case GDK_Right: case GDK_KP_Right:
125                                 x += 1;
126                                 break;
127                         case GDK_Up: case GDK_KP_Up:
128                                 y -= 1;
129                                 break;
130                         case GDK_Down: case GDK_KP_Down:
131                                 y += 1;
132                                 break;
133                         default:
134                                 stop_signal = FALSE;
135                                 break;
136                         }
137
138                 if (!stop_signal &&
139                     !(event->state & GDK_CONTROL_MASK))
140                         {
141                         stop_signal = TRUE;
142                         switch (event->keyval)
143                                 {
144                                 case GDK_Menu:
145                                         layout_image_menu_popup(lw);
146                                         break;
147                                 default:
148                                         stop_signal = FALSE;
149                                         break;
150                                 }
151                         }
152                 }
153
154         if (x != 0 || y!= 0)
155                 {
156                 if (event->state & GDK_SHIFT_MASK)
157                         {
158                         x *= 3;
159                         y *= 3;
160                         }
161
162                 keyboard_scroll_calc(&x, &y, event);
163                 layout_image_scroll(lw, x, y);
164                 }
165
166         return stop_signal;
167 }
168
169 void layout_keyboard_init(LayoutWindow *lw, GtkWidget *window)
170 {
171         g_signal_connect(G_OBJECT(window), "key_press_event",
172                          G_CALLBACK(layout_key_press_cb), lw);
173 }
174
175 /*
176  *-----------------------------------------------------------------------------
177  * menu callbacks
178  *-----------------------------------------------------------------------------
179  */
180
181
182 static GtkWidget *layout_window(LayoutWindow *lw)
183 {
184         return lw->full_screen ? lw->full_screen->window : lw->window;
185 }
186
187 static void layout_menu_new_window_cb(GtkAction *action, gpointer data)
188 {
189         LayoutWindow *lw = data;
190         LayoutWindow *nw;
191
192         if (lw->full_screen)
193                 layout_image_full_screen_stop(lw);
194
195         nw = layout_new(NULL, FALSE, FALSE);
196         layout_sort_set(nw, options->file_sort.method, options->file_sort.ascending);
197         layout_set_path(nw, layout_get_path(lw));
198 }
199
200 static void layout_menu_new_cb(GtkAction *action, gpointer data)
201 {
202         LayoutWindow *lw = data;
203         if (lw->full_screen)
204                 layout_image_full_screen_stop(lw);
205         collection_window_new(NULL);
206 }
207
208 static void layout_menu_open_cb(GtkAction *action, gpointer data)
209 {
210         LayoutWindow *lw = data;
211         if (lw->full_screen)
212                 layout_image_full_screen_stop(lw);
213         collection_dialog_load(NULL);
214 }
215
216 static void layout_menu_search_cb(GtkAction *action, gpointer data)
217 {
218         LayoutWindow *lw = data;
219         if (lw->full_screen)
220                 layout_image_full_screen_stop(lw);
221
222         search_new(lw->path, layout_image_get_path(lw));
223 }
224
225 static void layout_menu_dupes_cb(GtkAction *action, gpointer data)
226 {
227         LayoutWindow *lw = data;
228         if (lw->full_screen)
229                 layout_image_full_screen_stop(lw);
230
231         dupe_window_new(DUPE_MATCH_NAME);
232 }
233
234 static void layout_menu_pan_cb(GtkAction *action, gpointer data)
235 {
236         LayoutWindow *lw = data;
237         if (lw->full_screen)
238                 layout_image_full_screen_stop(lw);
239
240         pan_window_new(layout_get_path(lw));
241 }
242
243 static void layout_menu_print_cb(GtkAction *action, gpointer data)
244 {
245         LayoutWindow *lw = data;
246
247         print_window_new(layout_image_get_fd(lw), layout_selection_list(lw), layout_list(lw), layout_window(lw));
248 }
249
250 static void layout_menu_dir_cb(GtkAction *action, gpointer data)
251 {
252         LayoutWindow *lw = data;
253
254         file_util_create_dir(lw->path, layout_window(lw));
255 }
256
257 static void layout_menu_copy_cb(GtkAction *action, gpointer data)
258 {
259         LayoutWindow *lw = data;
260
261         file_util_copy(NULL, layout_selection_list(lw), NULL, layout_window(lw));
262 }
263
264 static void layout_menu_copy_path_cb(GtkAction *action, gpointer data)
265 {
266         LayoutWindow *lw = data;
267
268         file_util_copy_path_list_to_clipboard(layout_selection_list(lw));
269 }
270
271 static void layout_menu_move_cb(GtkAction *action, gpointer data)
272 {
273         LayoutWindow *lw = data;
274
275         file_util_move(NULL, layout_selection_list(lw), NULL, layout_window(lw));
276 }
277
278 static void layout_menu_rename_cb(GtkAction *action, gpointer data)
279 {
280         LayoutWindow *lw = data;
281
282         file_util_rename(NULL, layout_selection_list(lw), layout_window(lw));
283 }
284
285 static void layout_menu_delete_cb(GtkAction *action, gpointer data)
286 {
287         LayoutWindow *lw = data;
288
289         file_util_delete(NULL, layout_selection_list(lw), layout_window(lw));
290 }
291
292 static void layout_menu_close_cb(GtkAction *action, gpointer data)
293 {
294         LayoutWindow *lw = data;
295         if (lw->full_screen)
296                 layout_image_full_screen_stop(lw);
297
298         layout_close(lw);
299 }
300
301 static void layout_menu_exit_cb(GtkAction *action, gpointer data)
302 {
303         exit_program();
304 }
305
306 static void layout_menu_alter_90_cb(GtkAction *action, gpointer data)
307 {
308         LayoutWindow *lw = data;
309
310         layout_image_alter(lw, ALTER_ROTATE_90);
311 }
312
313 static void layout_menu_alter_90cc_cb(GtkAction *action, gpointer data)
314 {
315         LayoutWindow *lw = data;
316
317         layout_image_alter(lw, ALTER_ROTATE_90_CC);
318 }
319
320 static void layout_menu_alter_180_cb(GtkAction *action, gpointer data)
321 {
322         LayoutWindow *lw = data;
323
324         layout_image_alter(lw, ALTER_ROTATE_180);
325 }
326
327 static void layout_menu_alter_mirror_cb(GtkAction *action, gpointer data)
328 {
329         LayoutWindow *lw = data;
330
331         layout_image_alter(lw, ALTER_MIRROR);
332 }
333
334 static void layout_menu_alter_flip_cb(GtkAction *action, gpointer data)
335 {
336         LayoutWindow *lw = data;
337
338         layout_image_alter(lw, ALTER_FLIP);
339 }
340
341 static void layout_menu_alter_desaturate_cb(GtkAction *action, gpointer data)
342 {
343         LayoutWindow *lw = data;
344
345         layout_image_alter(lw, ALTER_DESATURATE);
346 }
347
348 static void layout_menu_alter_none_cb(GtkAction *action, gpointer data)
349 {
350         LayoutWindow *lw = data;
351
352         layout_image_alter(lw, ALTER_NONE);
353 }
354
355 static void layout_menu_info_cb(GtkAction *action, gpointer data)
356 {
357         LayoutWindow *lw = data;
358         GList *list;
359         FileData *fd = NULL;
360
361         list = layout_selection_list(lw);
362         if (!list) fd = layout_image_get_fd(lw);
363
364         info_window_new(fd, list, NULL);
365 }
366
367
368 static void layout_menu_config_cb(GtkAction *action, gpointer data)
369 {
370         LayoutWindow *lw = data;
371         if (lw->full_screen)
372                 layout_image_full_screen_stop(lw);
373
374         show_config_window();
375 }
376
377 static void layout_menu_remove_thumb_cb(GtkAction *action, gpointer data)
378 {
379         LayoutWindow *lw = data;
380         if (lw->full_screen)
381                 layout_image_full_screen_stop(lw);
382
383         cache_manager_show();
384 }
385
386 static void layout_menu_wallpaper_cb(GtkAction *action, gpointer data)
387 {
388         LayoutWindow *lw = data;
389
390         layout_image_to_root(lw);
391 }
392
393 static void layout_menu_zoom_in_cb(GtkAction *action, gpointer data)
394 {
395         LayoutWindow *lw = data;
396
397         layout_image_zoom_adjust(lw, get_zoom_increment());
398 }
399
400 static void layout_menu_zoom_out_cb(GtkAction *action, gpointer data)
401 {
402         LayoutWindow *lw = data;
403
404         layout_image_zoom_adjust(lw, -get_zoom_increment());
405 }
406
407 static void layout_menu_zoom_1_1_cb(GtkAction *action, gpointer data)
408 {
409         LayoutWindow *lw = data;
410
411         layout_image_zoom_set(lw, 1.0);
412 }
413
414 static void layout_menu_zoom_fit_cb(GtkAction *action, gpointer data)
415 {
416         LayoutWindow *lw = data;
417
418         layout_image_zoom_set(lw, 0.0);
419 }
420
421 static void layout_menu_zoom_fit_hor_cb(GtkAction *action, gpointer data)
422 {
423         LayoutWindow *lw = data;
424
425         layout_image_zoom_set_fill_geometry(lw, TRUE);
426 }
427
428 static void layout_menu_zoom_fit_vert_cb(GtkAction *action, gpointer data)
429 {
430         LayoutWindow *lw = data;
431
432         layout_image_zoom_set_fill_geometry(lw, FALSE);
433 }
434
435 static void layout_menu_zoom_2_1_cb(GtkAction *action, gpointer data)
436 {
437         LayoutWindow *lw = data;
438
439         layout_image_zoom_set(lw, 2.0);
440 }
441
442 static void layout_menu_zoom_3_1_cb(GtkAction *action, gpointer data)
443 {
444         LayoutWindow *lw = data;
445
446         layout_image_zoom_set(lw, 3.0);
447 }
448 static void layout_menu_zoom_4_1_cb(GtkAction *action, gpointer data)
449 {
450         LayoutWindow *lw = data;
451
452         layout_image_zoom_set(lw, 4.0);
453 }
454
455 static void layout_menu_zoom_1_2_cb(GtkAction *action, gpointer data)
456 {
457         LayoutWindow *lw = data;
458
459         layout_image_zoom_set(lw, -2.0);
460 }
461
462 static void layout_menu_zoom_1_3_cb(GtkAction *action, gpointer data)
463 {
464         LayoutWindow *lw = data;
465
466         layout_image_zoom_set(lw, -3.0);
467 }
468
469 static void layout_menu_zoom_1_4_cb(GtkAction *action, gpointer data)
470 {
471         LayoutWindow *lw = data;
472
473         layout_image_zoom_set(lw, -4.0);
474 }
475
476
477 static void layout_menu_split_cb(GtkRadioAction *action, GtkRadioAction *current, gpointer data)
478 {
479         LayoutWindow *lw = data;
480         if (lw->full_screen)
481                 layout_image_full_screen_stop(lw);
482
483         ImageSplitMode mode = gtk_radio_action_get_current_value(action);
484
485         if (mode == lw->split_mode) mode = 0; /* toggle back */
486
487         layout_split_change(lw, mode);
488 }
489
490 static void layout_menu_connect_scroll_cb(GtkToggleAction *action, gpointer data)
491 {
492         LayoutWindow *lw = data;
493         lw->connect_scroll = gtk_toggle_action_get_active(action);
494 }
495
496 static void layout_menu_connect_zoom_cb(GtkToggleAction *action, gpointer data)
497 {
498         LayoutWindow *lw = data;
499         lw->connect_zoom = gtk_toggle_action_get_active(action);
500 }
501
502
503 static void layout_menu_thumb_cb(GtkToggleAction *action, gpointer data)
504 {
505         LayoutWindow *lw = data;
506
507         layout_thumb_set(lw, gtk_toggle_action_get_active(action));
508 }
509
510
511 static void layout_menu_list_cb(GtkRadioAction *action, GtkRadioAction *current, gpointer data)
512 {
513         LayoutWindow *lw = data;
514         if (lw->full_screen)
515                 layout_image_full_screen_stop(lw);
516
517         layout_views_set(lw, lw->dir_view_type, (gtk_radio_action_get_current_value(action) == 1) ? FILEVIEW_ICON : FILEVIEW_LIST);
518 }
519
520 static void layout_menu_view_dir_as_cb(GtkRadioAction *action, GtkRadioAction *current, gpointer data)
521 {
522         LayoutWindow *lw = data;
523         if (lw->full_screen)
524                 layout_image_full_screen_stop(lw);
525
526         layout_views_set(lw, (DirViewType) gtk_radio_action_get_current_value(action), lw->file_view_type);
527 }
528
529 static void layout_menu_view_in_new_window_cb(GtkAction *action, gpointer data)
530 {
531         LayoutWindow *lw = data;
532
533         if (lw->full_screen)
534                 layout_image_full_screen_stop(lw);
535         view_window_new(layout_image_get_fd(lw));
536 }
537
538 static void layout_menu_fullscreen_cb(GtkAction *action, gpointer data)
539 {
540         LayoutWindow *lw = data;
541
542         layout_image_full_screen_toggle(lw);
543 }
544
545 static void layout_menu_escape_cb(GtkAction *action, gpointer data)
546 {
547         LayoutWindow *lw = data;
548
549         layout_image_full_screen_stop(lw);
550                                 /* FIXME:interrupting thumbs no longer allowed */
551 #if 0
552                                 interrupt_thumbs();
553 #endif
554 }
555
556 static void layout_menu_overlay_cb(GtkAction *action, gpointer data)
557 {
558         LayoutWindow *lw = data;
559
560         image_osd_toggle(lw->image);
561 }
562
563 static void layout_menu_histogram_chan_cb(GtkAction *action, gpointer data)
564 {
565         LayoutWindow *lw = data;
566
567         image_osd_histogram_chan_toggle(lw->image);
568 }
569
570 static void layout_menu_histogram_log_cb(GtkAction *action, gpointer data)
571 {
572         LayoutWindow *lw = data;
573
574         image_osd_histogram_log_toggle(lw->image);
575 }
576
577 static void layout_menu_refresh_cb(GtkAction *action, gpointer data)
578 {
579         LayoutWindow *lw = data;
580
581         layout_refresh(lw);
582 }
583
584 static void layout_menu_float_cb(GtkToggleAction *action, gpointer data)
585 {
586         LayoutWindow *lw = data;
587         if (lw->full_screen)
588                 layout_image_full_screen_stop(lw);
589
590         if (lw->tools_float != gtk_toggle_action_get_active(action))
591                 {
592                 layout_tools_float_toggle(lw);
593                 }
594 }
595
596 static void layout_menu_hide_cb(GtkAction *action, gpointer data)
597 {
598         LayoutWindow *lw = data;
599         if (lw->full_screen)
600                 layout_image_full_screen_stop(lw);
601
602         layout_tools_hide_toggle(lw);
603 }
604
605 static void layout_menu_toolbar_cb(GtkToggleAction *action, gpointer data)
606 {
607         LayoutWindow *lw = data;
608         if (lw->full_screen)
609                 layout_image_full_screen_stop(lw);
610
611         if (lw->toolbar_hidden != gtk_toggle_action_get_active(action))
612                 {
613                 layout_toolbar_toggle(lw);
614                 }
615 }
616
617 static void layout_menu_bar_info_cb(GtkToggleAction *action, gpointer data)
618 {
619         LayoutWindow *lw = data;
620         if (lw->full_screen)
621                 layout_image_full_screen_stop(lw);
622
623         if (lw->bar_info_enabled != gtk_toggle_action_get_active(action))
624                 {
625                 layout_bar_info_toggle(lw);
626                 }
627 }
628
629 static void layout_menu_bar_exif_cb(GtkToggleAction *action, gpointer data)
630 {
631         LayoutWindow *lw = data;
632         if (lw->full_screen)
633                 layout_image_full_screen_stop(lw);
634
635         if (lw->bar_exif_enabled != gtk_toggle_action_get_active(action))
636                 {
637                 layout_bar_exif_toggle(lw);
638                 }
639 }
640
641 static void layout_menu_bar_sort_cb(GtkToggleAction *action, gpointer data)
642 {
643         LayoutWindow *lw = data;
644         if (lw->full_screen)
645                 layout_image_full_screen_stop(lw);
646
647         if (lw->bar_sort_enabled != gtk_toggle_action_get_active(action))
648                 {
649                 layout_bar_sort_toggle(lw);
650                 }
651 }
652
653 static void layout_menu_slideshow_cb(GtkAction *action, gpointer data)
654 {
655         LayoutWindow *lw = data;
656
657         layout_image_slideshow_toggle(lw);
658 }
659
660 static void layout_menu_slideshow_pause_cb(GtkAction *action, gpointer data)
661 {
662         LayoutWindow *lw = data;
663
664         layout_image_slideshow_pause_toggle(lw);
665 }
666
667 static void layout_menu_help_cb(GtkAction *action, gpointer data)
668 {
669         LayoutWindow *lw = data;
670         if (lw->full_screen)
671                 layout_image_full_screen_stop(lw);
672         help_window_show("html_contents");
673 }
674
675 static void layout_menu_help_keys_cb(GtkAction *action, gpointer data)
676 {
677         LayoutWindow *lw = data;
678         if (lw->full_screen)
679                 layout_image_full_screen_stop(lw);
680         help_window_show("documentation");
681 }
682
683 static void layout_menu_notes_cb(GtkAction *action, gpointer data)
684 {
685         LayoutWindow *lw = data;
686         if (lw->full_screen)
687                 layout_image_full_screen_stop(lw);
688         help_window_show("release_notes");
689 }
690
691 static void layout_menu_about_cb(GtkAction *action, gpointer data)
692 {
693         LayoutWindow *lw = data;
694         if (lw->full_screen)
695                 layout_image_full_screen_stop(lw);
696         show_about_window();
697 }
698
699
700 /*
701  *-----------------------------------------------------------------------------
702  * select menu
703  *-----------------------------------------------------------------------------
704  */
705
706 static void layout_menu_select_all_cb(GtkAction *action, gpointer data)
707 {
708         LayoutWindow *lw = data;
709
710         layout_select_all(lw);
711 }
712
713 static void layout_menu_unselect_all_cb(GtkAction *action, gpointer data)
714 {
715         LayoutWindow *lw = data;
716
717         layout_select_none(lw);
718 }
719
720 static void layout_menu_marks_cb(GtkToggleAction *action, gpointer data)
721 {
722         LayoutWindow *lw = data;
723
724         layout_marks_set(lw, gtk_toggle_action_get_active(action));
725 }
726
727
728 static void layout_menu_set_mark_sel_cb(GtkAction *action, gpointer data)
729 {
730         LayoutWindow *lw = data;
731         gint mark = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(action), "mark_num"));
732         g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
733         mark--;
734
735         layout_selection_to_mark(lw, mark, STM_MODE_SET);
736 }
737
738 static void layout_menu_res_mark_sel_cb(GtkAction *action, gpointer data)
739 {
740         LayoutWindow *lw = data;
741         gint mark = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(action), "mark_num"));
742         g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
743         mark--;
744
745         layout_selection_to_mark(lw, mark, STM_MODE_RESET);
746 }
747
748 static void layout_menu_toggle_mark_sel_cb(GtkAction *action, gpointer data)
749 {
750         LayoutWindow *lw = data;
751         gint mark = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(action), "mark_num"));
752         g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
753         mark--;
754
755         layout_selection_to_mark(lw, mark, STM_MODE_TOGGLE);
756 }
757
758 static void layout_menu_sel_mark_cb(GtkAction *action, gpointer data)
759 {
760         LayoutWindow *lw = data;
761         gint mark = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(action), "mark_num"));
762         g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
763         mark--;
764
765         layout_mark_to_selection(lw, mark, MTS_MODE_SET);
766 }
767
768 static void layout_menu_sel_mark_or_cb(GtkAction *action, gpointer data)
769 {
770         LayoutWindow *lw = data;
771         gint mark = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(action), "mark_num"));
772         g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
773         mark--;
774
775         layout_mark_to_selection(lw, mark, MTS_MODE_OR);
776 }
777
778 static void layout_menu_sel_mark_and_cb(GtkAction *action, gpointer data)
779 {
780         LayoutWindow *lw = data;
781         gint mark = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(action), "mark_num"));
782         g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
783         mark--;
784
785         layout_mark_to_selection(lw, mark, MTS_MODE_AND);
786 }
787
788 static void layout_menu_sel_mark_minus_cb(GtkAction *action, gpointer data)
789 {
790         LayoutWindow *lw = data;
791         gint mark = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(action), "mark_num"));
792         g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
793         mark--;
794
795         layout_mark_to_selection(lw, mark, MTS_MODE_MINUS);
796 }
797
798
799 /*
800  *-----------------------------------------------------------------------------
801  * go menu
802  *-----------------------------------------------------------------------------
803  */
804
805 static void layout_menu_image_first_cb(GtkAction *action, gpointer data)
806 {
807         LayoutWindow *lw = data;
808         layout_image_first(lw);
809 }
810
811 static void layout_menu_image_prev_cb(GtkAction *action, gpointer data)
812 {
813         LayoutWindow *lw = data;
814         layout_image_prev(lw);
815 }
816
817 static void layout_menu_image_next_cb(GtkAction *action, gpointer data)
818 {
819         LayoutWindow *lw = data;
820         layout_image_next(lw);
821 }
822
823 static void layout_menu_image_last_cb(GtkAction *action, gpointer data)
824 {
825         LayoutWindow *lw = data;
826         layout_image_last(lw);
827 }
828
829
830 /*
831  *-----------------------------------------------------------------------------
832  * edit menu
833  *-----------------------------------------------------------------------------
834  */
835
836 static void layout_menu_edit_cb(GtkAction *action, gpointer data)
837 {
838         LayoutWindow *lw = data;
839         GList *list;
840         gint n;
841
842         n = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(action), "edit_index"));
843
844
845         if (lw->full_screen && !editor_window_flag_set(n))
846                 {
847                 layout_image_full_screen_stop(lw);
848                 }
849         list = layout_selection_list(lw);
850         start_editor_from_filelist(n, list);
851         filelist_free(list);
852 }
853
854 static void layout_menu_edit_update(LayoutWindow *lw)
855 {
856         gint i;
857
858         /* main edit menu */
859
860         if (!lw->action_group) return;
861
862         for (i = 0; i < GQ_EDITOR_GENERIC_SLOTS; i++)
863                 {
864                 gchar *key;
865                 GtkAction *action;
866
867                 key = g_strdup_printf("Editor%d", i);
868
869                 action = gtk_action_group_get_action(lw->action_group, key);
870                 g_object_set_data(G_OBJECT(action), "edit_index", GINT_TO_POINTER(i));
871
872                 if (options->editor_command[i] && strlen(options->editor_command[i]) > 0)
873                         {
874                         gchar *text;
875
876                         if (options->editor_name[i] && strlen(options->editor_name[i]) > 0)
877                                 {
878                                 text = g_strdup_printf(_("_%d in %s..."), i, options->editor_name[i]);
879                                 }
880                         else
881                                 {
882                                 text = g_strdup_printf(_("_%d in (unknown)..."), i);
883                                 }
884                         g_object_set(action, "label", text,
885                                              "sensitive", TRUE, NULL);
886                         g_free(text);
887                         }
888                 else
889                         {
890                         gchar *text;
891
892                         text = g_strdup_printf(_("_%d empty"), i);
893                         g_object_set(action, "label", text, "sensitive", FALSE, NULL);
894                         g_free(text);
895                         }
896
897                 g_free(key);
898                 }
899 }
900
901 void layout_edit_update_all(void)
902 {
903         GList *work;
904
905         work = layout_window_list;
906         while (work)
907                 {
908                 LayoutWindow *lw = work->data;
909                 work = work->next;
910
911                 layout_menu_edit_update(lw);
912                 }
913 }
914
915 /*
916  *-----------------------------------------------------------------------------
917  * recent menu
918  *-----------------------------------------------------------------------------
919  */
920
921 static void layout_menu_recent_cb(GtkWidget *widget, gpointer data)
922 {
923         gint n;
924         gchar *path;
925
926         n = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "recent_index"));
927
928         path = g_list_nth_data(history_list_get_by_key("recent"), n);
929
930         if (!path) return;
931
932         /* make a copy of it */
933         path = g_strdup(path);
934         collection_window_new(path);
935         g_free(path);
936 }
937
938 static void layout_menu_recent_update(LayoutWindow *lw)
939 {
940         GtkWidget *menu;
941         GtkWidget *recent;
942         GtkWidget *item;
943         GList *list;
944         gint n;
945
946         if (!lw->ui_manager) return;
947
948         list = history_list_get_by_key("recent");
949         n = 0;
950
951         menu = gtk_menu_new();
952
953         while (list)
954                 {
955                 item = menu_item_add_simple(menu, filename_from_path((gchar *)list->data),
956                                             G_CALLBACK(layout_menu_recent_cb), lw);
957                 g_object_set_data(G_OBJECT(item), "recent_index", GINT_TO_POINTER(n));
958                 list = list->next;
959                 n++;
960                 }
961
962         if (n == 0)
963                 {
964                 menu_item_add(menu, _("Empty"), NULL, NULL);
965                 }
966
967         recent = gtk_ui_manager_get_widget(lw->ui_manager, "/MainMenu/FileMenu/OpenRecent");
968         gtk_menu_item_set_submenu(GTK_MENU_ITEM(recent), menu);
969         gtk_widget_set_sensitive(recent, (n != 0));
970 }
971
972 void layout_recent_update_all(void)
973 {
974         GList *work;
975
976         work = layout_window_list;
977         while (work)
978                 {
979                 LayoutWindow *lw = work->data;
980                 work = work->next;
981
982                 layout_menu_recent_update(lw);
983                 }
984 }
985
986 void layout_recent_add_path(const gchar *path)
987 {
988         if (!path) return;
989
990         history_list_add_to_key("recent", path, options->open_recent_list_maxsize);
991
992         layout_recent_update_all();
993 }
994
995 /*
996  *-----------------------------------------------------------------------------
997  * copy path
998  *-----------------------------------------------------------------------------
999  */
1000
1001 static void layout_copy_path_update(LayoutWindow *lw)
1002 {
1003         GtkWidget *item = gtk_ui_manager_get_widget(lw->ui_manager, "/MainMenu/FileMenu/CopyPath");
1004
1005         if (!item) return;
1006         
1007         if (options->show_copy_path)
1008                 gtk_widget_show(item);
1009         else
1010                 gtk_widget_hide(item);
1011 }
1012
1013 void layout_copy_path_update_all(void)
1014 {
1015         GList *work;
1016
1017         work = layout_window_list;
1018         while (work)
1019                 {
1020                 LayoutWindow *lw = work->data;
1021                 work = work->next;
1022
1023                 layout_copy_path_update(lw);
1024                 }
1025 }
1026
1027 /*
1028  *-----------------------------------------------------------------------------
1029  * menu
1030  *-----------------------------------------------------------------------------
1031  */
1032
1033 #define CB G_CALLBACK
1034
1035 static GtkActionEntry menu_entries[] = {
1036   { "FileMenu",         NULL,           N_("_File") },
1037   { "GoMenu",           NULL,           N_("_Go") },
1038   { "EditMenu",         NULL,           N_("_Edit") },
1039   { "SelectMenu",       NULL,           N_("_Select") },
1040   { "AdjustMenu",       NULL,           N_("_Adjust") },
1041   { "ViewMenu",         NULL,           N_("_View") },
1042   { "DirMenu",          NULL,           N_("_View Directory as") },
1043   { "ZoomMenu",         NULL,           N_("_Zoom") },
1044   { "SplitMenu",        NULL,           N_("_Split") },
1045   { "HelpMenu",         NULL,           N_("_Help") },
1046
1047   { "FirstImage",       GTK_STOCK_GOTO_TOP,     N_("_First Image"),     "Home",         NULL,   CB(layout_menu_image_first_cb) },
1048   { "PrevImage",        GTK_STOCK_GO_UP,        N_("_Previous Image"),  "BackSpace",    NULL,   CB(layout_menu_image_prev_cb) },
1049   { "PrevImageAlt1",    GTK_STOCK_GO_UP,        N_("_Previous Image"),  "Page_Up",      NULL,   CB(layout_menu_image_prev_cb) },
1050   { "PrevImageAlt2",    GTK_STOCK_GO_UP,        N_("_Previous Image"),  "KP_Page_Up",   NULL,   CB(layout_menu_image_prev_cb) },
1051   { "NextImage",        GTK_STOCK_GO_DOWN,      N_("_Next Image"),      "space",        NULL,   CB(layout_menu_image_next_cb) },
1052   { "NextImageAlt1",    GTK_STOCK_GO_DOWN,      N_("_Next Image"),      "Page_Down",    NULL,   CB(layout_menu_image_next_cb) },
1053   { "NextImageAlt2",    GTK_STOCK_GO_DOWN,      N_("_Next Image"),      "KP_Page_Down", NULL,   CB(layout_menu_image_next_cb) },
1054   { "LastImage",        GTK_STOCK_GOTO_BOTTOM,  N_("_Last Image"),      "End",          NULL,   CB(layout_menu_image_last_cb) },
1055
1056
1057   { "NewWindow",        GTK_STOCK_NEW,  N_("New _window"),      NULL,           NULL,   CB(layout_menu_new_window_cb) },
1058   { "NewCollection",    GTK_STOCK_INDEX,N_("_New collection"),  "C",            NULL,   CB(layout_menu_new_cb) },
1059   { "OpenCollection",   GTK_STOCK_OPEN, N_("_Open collection..."),"O",          NULL,   CB(layout_menu_open_cb) },
1060   { "OpenRecent",       NULL,           N_("Open _recent") },
1061   { "Search",           GTK_STOCK_FIND, N_("_Search..."),       "F3",           NULL,   CB(layout_menu_search_cb) },
1062   { "FindDupes",        GTK_STOCK_FIND, N_("_Find duplicates..."),"D",          NULL,   CB(layout_menu_dupes_cb) },
1063   { "PanView",          NULL,           N_("Pan _view"),        "<control>J",   NULL,   CB(layout_menu_pan_cb) },
1064   { "Print",            GTK_STOCK_PRINT,N_("_Print..."),        "<shift>P",     NULL,   CB(layout_menu_print_cb) },
1065   { "NewFolder",        NULL,           N_("N_ew folder..."),   "<control>F",   NULL,   CB(layout_menu_dir_cb) },
1066   { "Copy",             NULL,           N_("_Copy..."),         "<control>C",   NULL,   CB(layout_menu_copy_cb) },
1067   { "Move",             NULL,           N_("_Move..."),         "<control>M",   NULL,   CB(layout_menu_move_cb) },
1068   { "Rename",           NULL,           N_("_Rename..."),       "<control>R",   NULL,   CB(layout_menu_rename_cb) },
1069   { "Delete",   GTK_STOCK_DELETE,       N_("_Delete..."),       "<control>D",   NULL,   CB(layout_menu_delete_cb) },
1070   { "DeleteAlt1",GTK_STOCK_DELETE,      N_("_Delete..."),       "Delete",       NULL,   CB(layout_menu_delete_cb) },
1071   { "DeleteAlt2",GTK_STOCK_DELETE,      N_("_Delete..."),       "KP_Delete",    NULL,   CB(layout_menu_delete_cb) },
1072   { "CopyPath",         NULL,           N_("_Copy path"),       NULL,           NULL,   CB(layout_menu_copy_path_cb) },
1073   { "CloseWindow",      GTK_STOCK_CLOSE,N_("C_lose window"),    "<control>W",   NULL,   CB(layout_menu_close_cb) },
1074   { "Quit",             GTK_STOCK_QUIT, N_("_Quit"),            "<control>Q",   NULL,   CB(layout_menu_exit_cb) },
1075
1076   { "Editor0",          NULL,           "editor0",              NULL,           NULL,   CB(layout_menu_edit_cb) },
1077   { "Editor1",          NULL,           "editor1",              NULL,           NULL,   CB(layout_menu_edit_cb) },
1078   { "Editor2",          NULL,           "editor2",              NULL,           NULL,   CB(layout_menu_edit_cb) },
1079   { "Editor3",          NULL,           "editor3",              NULL,           NULL,   CB(layout_menu_edit_cb) },
1080   { "Editor4",          NULL,           "editor4",              NULL,           NULL,   CB(layout_menu_edit_cb) },
1081   { "Editor5",          NULL,           "editor5",              NULL,           NULL,   CB(layout_menu_edit_cb) },
1082   { "Editor6",          NULL,           "editor6",              NULL,           NULL,   CB(layout_menu_edit_cb) },
1083   { "Editor7",          NULL,           "editor7",              NULL,           NULL,   CB(layout_menu_edit_cb) },
1084   { "Editor8",          NULL,           "editor8",              NULL,           NULL,   CB(layout_menu_edit_cb) },
1085   { "Editor9",          NULL,           "editor9",              NULL,           NULL,   CB(layout_menu_edit_cb) },
1086
1087   { "RotateCW",         NULL,   N_("_Rotate clockwise"),        "bracketright", NULL,   CB(layout_menu_alter_90_cb) },
1088   { "RotateCCW",        NULL,   N_("Rotate _counterclockwise"), "bracketleft",  NULL,   CB(layout_menu_alter_90cc_cb) },
1089   { "Rotate180",        NULL,           N_("Rotate 1_80"),      "<shift>R",     NULL,   CB(layout_menu_alter_180_cb) },
1090   { "Mirror",           NULL,           N_("_Mirror"),          "<shift>M",     NULL,   CB(layout_menu_alter_mirror_cb) },
1091   { "Flip",             NULL,           N_("_Flip"),            "<shift>F",     NULL,   CB(layout_menu_alter_flip_cb) },
1092   { "Grayscale",        NULL,           N_("Toggle _grayscale"),"<shift>G",     NULL,   CB(layout_menu_alter_desaturate_cb) },
1093   { "AlterNone",        NULL,           N_("_Original state"),  "<shift>O",     NULL,   CB(layout_menu_alter_none_cb) },
1094
1095   { "Properties",GTK_STOCK_PROPERTIES,  N_("_Properties"),      "<control>P",   NULL,   CB(layout_menu_info_cb) },
1096   { "SelectAll",        NULL,           N_("Select _all"),      "<control>A",   NULL,   CB(layout_menu_select_all_cb) },
1097   { "SelectNone",       NULL,           N_("Select _none"), "<control><shift>A",NULL,   CB(layout_menu_unselect_all_cb) },
1098   { "Preferences",GTK_STOCK_PREFERENCES,N_("P_references..."),  "<control>O",   NULL,   CB(layout_menu_config_cb) },
1099   { "Maintenance",      NULL,           N_("_Thumbnail maintenance..."),NULL,   NULL,   CB(layout_menu_remove_thumb_cb) },
1100   { "Wallpaper",        NULL,           N_("Set as _wallpaper"),NULL,           NULL,   CB(layout_menu_wallpaper_cb) },
1101
1102   { "ZoomIn",   GTK_STOCK_ZOOM_IN,      N_("Zoom _in"),         "equal",        NULL,   CB(layout_menu_zoom_in_cb) },
1103   { "ZoomInAlt1",GTK_STOCK_ZOOM_IN,     N_("Zoom _in"),         "plus",         NULL,   CB(layout_menu_zoom_in_cb) },
1104   { "ZoomInAlt2",GTK_STOCK_ZOOM_IN,     N_("Zoom _in"),         "KP_Add",       NULL,   CB(layout_menu_zoom_in_cb) },
1105   { "ZoomOut",  GTK_STOCK_ZOOM_OUT,     N_("Zoom _out"),        "minus",        NULL,   CB(layout_menu_zoom_out_cb) },
1106   { "ZoomOutAlt1",GTK_STOCK_ZOOM_OUT,   N_("Zoom _out"),        "KP_Subtract",  NULL,   CB(layout_menu_zoom_out_cb) },
1107   { "Zoom100",  GTK_STOCK_ZOOM_100,     N_("Zoom _1:1"),        "Z",            NULL,   CB(layout_menu_zoom_1_1_cb) },
1108   { "Zoom100Alt1",GTK_STOCK_ZOOM_100,   N_("Zoom _1:1"),        "KP_Divide",            NULL,   CB(layout_menu_zoom_1_1_cb) },
1109   { "ZoomFit",  GTK_STOCK_ZOOM_FIT,     N_("_Zoom to fit"),     "X",            NULL,   CB(layout_menu_zoom_fit_cb) },
1110   { "ZoomFitAlt1",GTK_STOCK_ZOOM_FIT,   N_("_Zoom to fit"),     "KP_Multiply",  NULL,   CB(layout_menu_zoom_fit_cb) },
1111   { "ZoomFillHor",      NULL,           N_("Fit _Horizontally"),"H",            NULL,   CB(layout_menu_zoom_fit_hor_cb) },
1112   { "ZoomFillVert",     NULL,           N_("Fit _Vorizontally"),"W",            NULL,   CB(layout_menu_zoom_fit_vert_cb) },
1113   { "Zoom200",          NULL,           N_("Zoom _2:1"),        NULL,           NULL,   CB(layout_menu_zoom_2_1_cb) },
1114   { "Zoom300",          NULL,           N_("Zoom _3:1"),        NULL,           NULL,   CB(layout_menu_zoom_3_1_cb) },
1115   { "Zoom400",          NULL,           N_("Zoom _4:1"),        NULL,           NULL,   CB(layout_menu_zoom_4_1_cb) },
1116   { "Zoom50",           NULL,           N_("Zoom 1:2"),         NULL,           NULL,   CB(layout_menu_zoom_1_2_cb) },
1117   { "Zoom33",           NULL,           N_("Zoom 1:3"),         NULL,           NULL,   CB(layout_menu_zoom_1_3_cb) },
1118   { "Zoom25",           NULL,           N_("Zoom 1:4"),         NULL,           NULL,   CB(layout_menu_zoom_1_4_cb) },
1119
1120
1121   { "ViewInNewWindow",  NULL,           N_("_View in new window"),      "<control>V",           NULL,   CB(layout_menu_view_in_new_window_cb) },
1122
1123   { "FullScreen",       NULL,           N_("F_ull screen"),     "F",            NULL,   CB(layout_menu_fullscreen_cb) },
1124   { "FullScreenAlt1",   NULL,           N_("F_ull screen"),     "V",            NULL,   CB(layout_menu_fullscreen_cb) },
1125   { "FullScreenAlt2",   NULL,           N_("F_ull screen"),     "F11",          NULL,   CB(layout_menu_fullscreen_cb) },
1126   { "Escape",           NULL,           N_("Escape"),           "Escape",       NULL,   CB(layout_menu_escape_cb) },
1127   { "EscapeAlt1",       NULL,           N_("Escape"),           "Q",            NULL,   CB(layout_menu_escape_cb) },
1128   { "ImageOverlay",     NULL,           N_("_Image Overlay"),   "I",            NULL,   CB(layout_menu_overlay_cb) },
1129   { "HistogramChan",    NULL,   N_("Histogram _channels"),      "K",            NULL,   CB(layout_menu_histogram_chan_cb) },
1130   { "HistogramLog",     NULL,   N_("Histogram _log mode"),      "J",            NULL,   CB(layout_menu_histogram_log_cb) },
1131   { "HideTools",        NULL,           N_("_Hide file list"),  "<control>H",   NULL,   CB(layout_menu_hide_cb) },
1132   { "SlideShowPause",   NULL,           N_("_Pause slideshow"), "P",            NULL,   CB(layout_menu_slideshow_pause_cb) },
1133   { "Refresh",  GTK_STOCK_REFRESH,      N_("_Refresh"),         "R",            NULL,   CB(layout_menu_refresh_cb) },
1134
1135   { "HelpContents",     GTK_STOCK_HELP, N_("_Contents"),        "F1",           NULL,   CB(layout_menu_help_cb) },
1136   { "HelpShortcuts",    NULL,           N_("_Keyboard shortcuts"),NULL,         NULL,   CB(layout_menu_help_keys_cb) },
1137   { "HelpNotes",        NULL,           N_("_Release notes"),   NULL,           NULL,   CB(layout_menu_notes_cb) },
1138   { "About",            NULL,           N_("_About"),           NULL,           NULL,   CB(layout_menu_about_cb) }
1139 };
1140
1141 static GtkToggleActionEntry menu_toggle_entries[] = {
1142   { "Thumbnails",       NULL,           N_("_Thumbnails"),      "T",            NULL,   CB(layout_menu_thumb_cb) },
1143   { "ShowMarks",        NULL,           N_("Show _Marks"),      "M",            NULL,   CB(layout_menu_marks_cb) },
1144   { "FloatTools",       NULL,           N_("_Float file list"), "L",            NULL,   CB(layout_menu_float_cb) },
1145   { "HideToolbar",      NULL,           N_("Hide tool_bar"),    NULL,           NULL,   CB(layout_menu_toolbar_cb) },
1146   { "SBarKeywords",     NULL,           N_("_Keywords"),        "<control>K",   NULL,   CB(layout_menu_bar_info_cb) },
1147   { "SBarExif",         NULL,           N_("E_xif data"),       "<control>E",   NULL,   CB(layout_menu_bar_exif_cb) },
1148   { "SBarSort",         NULL,           N_("Sort _manager"),    "<control>S",   NULL,   CB(layout_menu_bar_sort_cb) },
1149   { "ConnectScroll",    NULL,           N_("Co_nnected scroll"),        "<control>U",   NULL,   CB(layout_menu_connect_scroll_cb) },
1150   { "ConnectZoom",      NULL,           N_("C_onnected zoom"),  "<control>Y",   NULL,   CB(layout_menu_connect_zoom_cb) },
1151   { "SlideShow",        NULL,           N_("Toggle _slideshow"),"S",            NULL,   CB(layout_menu_slideshow_cb) },
1152 };
1153
1154 static GtkRadioActionEntry menu_radio_entries[] = {
1155   { "ViewList",         NULL,           N_("_List"),            "<control>L",   NULL,   0 },
1156   { "ViewIcons",        NULL,           N_("I_cons"),           "<control>I",   NULL,   1 }
1157 };
1158
1159 static GtkRadioActionEntry menu_split_radio_entries[] = {
1160   { "SplitHorizontal",  NULL,           N_("Horizontal"),       "E",            NULL,   SPLIT_HOR },
1161   { "SplitVertical",    NULL,           N_("Vertical"),         "U",            NULL,   SPLIT_VERT },
1162   { "SplitQuad",        NULL,           N_("Quad"),             NULL,           NULL,   SPLIT_QUAD },
1163   { "SplitSingle",      NULL,           N_("Single"),           "Y",            NULL,   SPLIT_NONE }
1164 };
1165
1166
1167 #undef CB
1168
1169 static const char *menu_ui_description =
1170 "<ui>"
1171 "  <menubar name='MainMenu'>"
1172 "    <menu action='FileMenu'>"
1173 "      <menuitem action='NewWindow'/>"
1174 "      <menuitem action='NewCollection'/>"
1175 "      <menuitem action='OpenCollection'/>"
1176 "      <menuitem action='OpenRecent'/>"
1177 "      <separator/>"
1178 "      <menuitem action='Search'/>"
1179 "      <menuitem action='FindDupes'/>"
1180 "      <menuitem action='PanView'/>"
1181 "      <separator/>"
1182 "      <menuitem action='Print'/>"
1183 "      <menuitem action='NewFolder'/>"
1184 "      <separator/>"
1185 "      <menuitem action='Copy'/>"
1186 "      <menuitem action='Move'/>"
1187 "      <menuitem action='Rename'/>"
1188 "      <menuitem action='Delete'/>"
1189 "      <menuitem action='CopyPath'/>"
1190 "      <separator/>"
1191 "      <menuitem action='CloseWindow'/>"
1192 "      <menuitem action='Quit'/>"
1193 "    </menu>"
1194 "    <menu action='GoMenu'>"
1195 "      <menuitem action='FirstImage'/>"
1196 "      <menuitem action='PrevImage'/>"
1197 "      <menuitem action='NextImage'/>"
1198 "      <menuitem action='LastImage'/>"
1199 "    </menu>"
1200 "    <menu action='SelectMenu'>"
1201 "      <menuitem action='SelectAll'/>"
1202 "      <menuitem action='SelectNone'/>"
1203 "      <separator/>"
1204 "      <menuitem action='ShowMarks'/>"
1205 "      <separator/>"
1206 "    </menu>"
1207 "    <menu action='EditMenu'>"
1208 "      <menuitem action='Editor0'/>"
1209 "      <menuitem action='Editor1'/>"
1210 "      <menuitem action='Editor2'/>"
1211 "      <menuitem action='Editor3'/>"
1212 "      <menuitem action='Editor4'/>"
1213 "      <menuitem action='Editor5'/>"
1214 "      <menuitem action='Editor6'/>"
1215 "      <menuitem action='Editor7'/>"
1216 "      <menuitem action='Editor8'/>"
1217 "      <menuitem action='Editor9'/>"
1218 "      <separator/>"
1219 "      <menu action='AdjustMenu'>"
1220 "        <menuitem action='RotateCW'/>"
1221 "        <menuitem action='RotateCCW'/>"
1222 "        <menuitem action='Rotate180'/>"
1223 "        <menuitem action='Mirror'/>"
1224 "        <menuitem action='Flip'/>"
1225 "        <menuitem action='Grayscale'/>"
1226 "        <menuitem action='AlterNone'/>"
1227 "      </menu>"
1228 "      <menuitem action='Properties'/>"
1229 "      <separator/>"
1230 "      <menuitem action='Preferences'/>"
1231 "      <menuitem action='Maintenance'/>"
1232 "      <separator/>"
1233 "      <menuitem action='Wallpaper'/>"
1234 "    </menu>"
1235 "    <menu action='ViewMenu'>"
1236 "      <menuitem action='ViewInNewWindow'/>"
1237 "      <separator/>"
1238 "      <menu action='ZoomMenu'>"
1239 "        <menuitem action='ZoomIn'/>"
1240 "        <menuitem action='ZoomOut'/>"
1241 "        <menuitem action='ZoomFit'/>"
1242 "        <menuitem action='ZoomFillHor'/>"
1243 "        <menuitem action='ZoomFillVert'/>"
1244 "        <menuitem action='Zoom100'/>"
1245 "        <menuitem action='Zoom200'/>"
1246 "        <menuitem action='Zoom300'/>"
1247 "        <menuitem action='Zoom400'/>"
1248 "        <menuitem action='Zoom50'/>"
1249 "        <menuitem action='Zoom33'/>"
1250 "        <menuitem action='Zoom25'/>"
1251 "      </menu>"
1252 "      <separator/>"
1253 "      <menu action='SplitMenu'>"
1254 "        <menuitem action='SplitHorizontal'/>"
1255 "        <menuitem action='SplitVertical'/>"
1256 "        <menuitem action='SplitQuad'/>"
1257 "        <menuitem action='SplitSingle'/>"
1258 "      </menu>"
1259 "      <menuitem action='ConnectScroll'/>"
1260 "      <menuitem action='ConnectZoom'/>"
1261 "      <separator/>"
1262 "      <menuitem action='Thumbnails'/>"
1263 "      <menuitem action='ViewList'/>"
1264 "      <menuitem action='ViewIcons'/>"
1265 "      <separator/>"
1266 "      <menu action='DirMenu'>"
1267 "        <menuitem action='FolderList'/>"
1268 "        <menuitem action='FolderTree'/>"
1269 "      </menu>"
1270 "      <separator/>"
1271 "      <menuitem action='ImageOverlay'/>"
1272 "      <menuitem action='HistogramChan'/>"
1273 "      <menuitem action='HistogramLog'/>"
1274 "      <menuitem action='FullScreen'/>"
1275 "      <separator/>"
1276 "      <menuitem action='FloatTools'/>"
1277 "      <menuitem action='HideTools'/>"
1278 "      <menuitem action='HideToolbar'/>"
1279 "      <separator/>"
1280 "      <menuitem action='SBarKeywords'/>"
1281 "      <menuitem action='SBarExif'/>"
1282 "      <menuitem action='SBarSort'/>"
1283 "      <separator/>"
1284 "      <menuitem action='SlideShow'/>"
1285 "      <menuitem action='SlideShowPause'/>"
1286 "      <menuitem action='Refresh'/>"
1287 "    </menu>"
1288 "    <menu action='HelpMenu'>"
1289 "      <separator/>"
1290 "      <menuitem action='HelpContents'/>"
1291 "      <menuitem action='HelpShortcuts'/>"
1292 "      <menuitem action='HelpNotes'/>"
1293 "      <separator/>"
1294 "      <menuitem action='About'/>"
1295 "    </menu>"
1296 "  </menubar>"
1297 "<accelerator action='PrevImageAlt1'/>"
1298 "<accelerator action='PrevImageAlt2'/>"
1299 "<accelerator action='NextImageAlt1'/>"
1300 "<accelerator action='NextImageAlt2'/>"
1301 "<accelerator action='DeleteAlt1'/>"
1302 "<accelerator action='DeleteAlt2'/>"
1303 "<accelerator action='ZoomInAlt1'/>"
1304 "<accelerator action='ZoomInAlt2'/>"
1305 "<accelerator action='ZoomOutAlt1'/>"
1306 "<accelerator action='Zoom100Alt1'/>"
1307 "<accelerator action='ZoomFitAlt1'/>"
1308 "<accelerator action='FullScreenAlt1'/>"
1309 "<accelerator action='FullScreenAlt2'/>"
1310 "<accelerator action='Escape'/>"
1311 "<accelerator action='EscapeAlt1'/>"
1312 "</ui>";
1313
1314
1315 static gchar *menu_translate(const gchar *path, gpointer data)
1316 {
1317         return _(path);
1318 }
1319
1320 static void layout_actions_setup_mark(LayoutWindow *lw, gint mark, char *name_tmpl, char *label_tmpl, char *accel_tmpl,  GCallback cb)
1321 {
1322         char name[50];
1323         char label[100];
1324         char accel[50];
1325         GtkActionEntry entry = { name, NULL, label, accel, NULL, cb };
1326         GtkAction *action;
1327
1328         g_snprintf(name, sizeof(name), name_tmpl, mark);
1329         g_snprintf(label, sizeof(label), label_tmpl, mark);
1330         if (accel_tmpl)
1331                 g_snprintf(accel, sizeof(accel), accel_tmpl, mark % 10);
1332         else
1333                 accel[0] = 0;
1334         gtk_action_group_add_actions(lw->action_group, &entry, 1, lw);
1335         action = gtk_action_group_get_action(lw->action_group, name);
1336         g_object_set_data(G_OBJECT(action), "mark_num", GINT_TO_POINTER(mark));
1337 }
1338
1339 static void layout_actions_setup_marks(LayoutWindow *lw)
1340 {
1341         int mark;
1342         GError *error;
1343         GString *desc = g_string_new(
1344                                 "<ui>"
1345                                 "  <menubar name='MainMenu'>"
1346                                 "    <menu action='SelectMenu'>");
1347
1348         for (mark = 1; mark <= FILEDATA_MARKS_SIZE; mark++)
1349                 {
1350                 layout_actions_setup_mark(lw, mark, "Mark%d",           _("Mark _%d"), NULL, NULL);
1351                 layout_actions_setup_mark(lw, mark, "SetMark%d",        _("_Set mark %d"),                      NULL, G_CALLBACK(layout_menu_set_mark_sel_cb));
1352                 layout_actions_setup_mark(lw, mark, "ResetMark%d",      _("_Reset mark %d"),                    NULL, G_CALLBACK(layout_menu_res_mark_sel_cb));
1353                 layout_actions_setup_mark(lw, mark, "ToggleMark%d",     _("_Toggle mark %d"),                   "%d", G_CALLBACK(layout_menu_toggle_mark_sel_cb));
1354                 layout_actions_setup_mark(lw, mark, "ToggleMark%dAlt1", _("_Toggle mark %d"),                   "KP_%d", G_CALLBACK(layout_menu_toggle_mark_sel_cb));
1355                 layout_actions_setup_mark(lw, mark, "SelectMark%d",     _("_Select mark %d"),                   "<control>%d", G_CALLBACK(layout_menu_sel_mark_cb));
1356                 layout_actions_setup_mark(lw, mark, "SelectMark%dAlt1", _("_Select mark %d"),                   "<control>KP_%d", G_CALLBACK(layout_menu_sel_mark_cb));
1357                 layout_actions_setup_mark(lw, mark, "AddMark%d",        _("_Add mark %d"),                      NULL, G_CALLBACK(layout_menu_sel_mark_or_cb));
1358                 layout_actions_setup_mark(lw, mark, "IntMark%d",        _("_Intersection with mark %d"),        NULL, G_CALLBACK(layout_menu_sel_mark_and_cb));
1359                 layout_actions_setup_mark(lw, mark, "UnselMark%d",      _("_Unselect mark %d"),                 NULL, G_CALLBACK(layout_menu_sel_mark_minus_cb));
1360
1361                 g_string_append_printf(desc,
1362                                 "      <menu action='Mark%d'>"
1363                                 "        <menuitem action='ToggleMark%d'/>"
1364                                 "        <menuitem action='SetMark%d'/>"
1365                                 "        <menuitem action='ResetMark%d'/>"
1366                                 "        <separator/>"
1367                                 "        <menuitem action='SelectMark%d'/>"
1368                                 "        <menuitem action='AddMark%d'/>"
1369                                 "        <menuitem action='IntMark%d'/>"
1370                                 "        <menuitem action='UnselMark%d'/>"
1371                                 "      </menu>",
1372                                 mark, mark, mark, mark, mark, mark, mark, mark);
1373                 }
1374
1375         g_string_append(desc,
1376                                 "    </menu>"
1377                                 "  </menubar>");
1378         for (mark = 1; mark <= FILEDATA_MARKS_SIZE; mark++)
1379                 {
1380                 g_string_append_printf(desc,
1381                                 "<accelerator action='ToggleMark%dAlt1'/>"
1382                                 "<accelerator action='SelectMark%dAlt1'/>",
1383                                 mark, mark);
1384                 }
1385         g_string_append(desc,   "</ui>" );
1386
1387         error = NULL;
1388         if (!gtk_ui_manager_add_ui_from_string(lw->ui_manager, desc->str, -1, &error))
1389                 {
1390                 g_message("building menus failed: %s", error->message);
1391                 g_error_free(error);
1392                 exit(EXIT_FAILURE);
1393                 }
1394         g_string_free(desc, TRUE);
1395 }
1396
1397 void layout_actions_setup(LayoutWindow *lw)
1398 {
1399         GError *error;
1400
1401         if (lw->ui_manager) return;
1402
1403         lw->action_group = gtk_action_group_new("MenuActions");
1404         gtk_action_group_set_translate_func(lw->action_group, menu_translate, NULL, NULL);
1405
1406         gtk_action_group_add_actions(lw->action_group,
1407                                      menu_entries, G_N_ELEMENTS(menu_entries), lw);
1408         gtk_action_group_add_toggle_actions(lw->action_group,
1409                                             menu_toggle_entries, G_N_ELEMENTS(menu_toggle_entries), lw);
1410         gtk_action_group_add_radio_actions(lw->action_group,
1411                                            menu_radio_entries, G_N_ELEMENTS(menu_radio_entries),
1412                                            0, G_CALLBACK(layout_menu_list_cb), lw);
1413         gtk_action_group_add_radio_actions(lw->action_group,
1414                                            menu_split_radio_entries, G_N_ELEMENTS(menu_split_radio_entries),
1415                                            0, G_CALLBACK(layout_menu_split_cb), lw);
1416         gtk_action_group_add_radio_actions(lw->action_group,
1417                                            menu_view_dir_radio_entries, VIEW_DIR_TYPES_COUNT,
1418                                            0, G_CALLBACK(layout_menu_view_dir_as_cb), lw);
1419
1420         lw->ui_manager = gtk_ui_manager_new();
1421         gtk_ui_manager_set_add_tearoffs(lw->ui_manager, TRUE);
1422         gtk_ui_manager_insert_action_group(lw->ui_manager, lw->action_group, 0);
1423
1424         error = NULL;
1425         if (!gtk_ui_manager_add_ui_from_string(lw->ui_manager, menu_ui_description, -1, &error))
1426                 {
1427                 g_message("building menus failed: %s", error->message);
1428                 g_error_free(error);
1429                 exit(EXIT_FAILURE);
1430                 }
1431         
1432         layout_actions_setup_marks(lw);
1433         layout_copy_path_update(lw);
1434 }
1435
1436 void layout_actions_add_window(LayoutWindow *lw, GtkWidget *window)
1437 {
1438         GtkAccelGroup *group;
1439
1440         if (!lw->ui_manager) return;
1441
1442         group = gtk_ui_manager_get_accel_group(lw->ui_manager);
1443         gtk_window_add_accel_group(GTK_WINDOW(window), group);
1444 }
1445
1446 GtkWidget *layout_actions_menu_bar(LayoutWindow *lw)
1447 {
1448         return gtk_ui_manager_get_widget(lw->ui_manager, "/MainMenu");
1449 }
1450
1451
1452 /*
1453  *-----------------------------------------------------------------------------
1454  * toolbar
1455  *-----------------------------------------------------------------------------
1456  */
1457
1458 static void layout_button_thumb_cb(GtkWidget *widget, gpointer data)
1459 {
1460         LayoutWindow *lw = data;
1461
1462         layout_thumb_set(lw, gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(widget)));
1463 }
1464
1465 static void layout_button_home_cb(GtkWidget *widget, gpointer data)
1466 {
1467         LayoutWindow *lw = data;
1468         const gchar *path = homedir();
1469
1470         if (path) layout_set_path(lw, path);
1471 }
1472
1473 static void layout_button_refresh_cb(GtkWidget *widget, gpointer data)
1474 {
1475         LayoutWindow *lw = data;
1476
1477         layout_refresh(lw);
1478 }
1479
1480 static void layout_button_zoom_in_cb(GtkWidget *widget, gpointer data)
1481 {
1482         LayoutWindow *lw = data;
1483
1484         layout_image_zoom_adjust(lw, get_zoom_increment());
1485 }
1486
1487 static void layout_button_zoom_out_cb(GtkWidget *widget, gpointer data)
1488 {
1489         LayoutWindow *lw = data;
1490
1491         layout_image_zoom_adjust(lw, -get_zoom_increment());
1492 }
1493
1494 static void layout_button_zoom_fit_cb(GtkWidget *widget, gpointer data)
1495 {
1496         LayoutWindow *lw = data;
1497
1498         layout_image_zoom_set(lw, 0.0);
1499 }
1500
1501 static void layout_button_zoom_1_1_cb(GtkWidget *widget, gpointer data)
1502 {
1503         LayoutWindow *lw = data;
1504
1505         layout_image_zoom_set(lw, 1.0);
1506 }
1507
1508 static void layout_button_config_cb(GtkWidget *widget, gpointer data)
1509 {
1510         show_config_window();
1511 }
1512
1513 static void layout_button_float_cb(GtkWidget *widget, gpointer data)
1514 {
1515         LayoutWindow *lw = data;
1516
1517         layout_tools_float_toggle(lw);
1518 }
1519
1520 static void layout_button_custom_icon(GtkWidget *button, const gchar *key)
1521 {
1522         GtkWidget *icon;
1523         GdkPixbuf *pixbuf;
1524
1525         pixbuf = pixbuf_inline(key);
1526         if (!pixbuf) return;
1527
1528         icon = gtk_image_new_from_pixbuf(pixbuf);
1529         g_object_unref(pixbuf);
1530
1531         pref_toolbar_button_set_icon(button, icon, NULL);
1532         gtk_widget_show(icon);
1533 }
1534
1535 GtkWidget *layout_button_bar(LayoutWindow *lw)
1536 {
1537         GtkWidget *box;
1538         GtkWidget *button;
1539
1540         box =  pref_toolbar_new(NULL, GTK_TOOLBAR_ICONS);
1541
1542         button = pref_toolbar_button(box, NULL, _("_Thumbnails"), TRUE,
1543                                      _("Show thumbnails"), G_CALLBACK(layout_button_thumb_cb), lw);
1544         layout_button_custom_icon(button, PIXBUF_INLINE_ICON_THUMB);
1545         lw->thumb_button = button;
1546
1547         pref_toolbar_button(box, GTK_STOCK_HOME, NULL, FALSE,
1548                             _("Change to home folder"), G_CALLBACK(layout_button_home_cb), lw);
1549         pref_toolbar_button(box, GTK_STOCK_REFRESH, NULL, FALSE,
1550                             _("Refresh file list"), G_CALLBACK(layout_button_refresh_cb), lw);
1551         pref_toolbar_button(box, GTK_STOCK_ZOOM_IN, NULL, FALSE,
1552                             _("Zoom in"), G_CALLBACK(layout_button_zoom_in_cb), lw);
1553         pref_toolbar_button(box, GTK_STOCK_ZOOM_OUT, NULL, FALSE,
1554                             _("Zoom out"), G_CALLBACK(layout_button_zoom_out_cb), lw);
1555         pref_toolbar_button(box, GTK_STOCK_ZOOM_FIT, NULL, FALSE,
1556                             _("Fit image to window"), G_CALLBACK(layout_button_zoom_fit_cb), lw);
1557         pref_toolbar_button(box, GTK_STOCK_ZOOM_100, NULL, FALSE,
1558                             _("Set zoom 1:1"), G_CALLBACK(layout_button_zoom_1_1_cb), lw);
1559         pref_toolbar_button(box, GTK_STOCK_PREFERENCES, NULL, FALSE,
1560                             _("Configure options"), G_CALLBACK(layout_button_config_cb), lw);
1561         button = pref_toolbar_button(box, NULL, _("_Float"), FALSE,
1562                                      _("Float Controls"), G_CALLBACK(layout_button_float_cb), lw);
1563         layout_button_custom_icon(button, PIXBUF_INLINE_ICON_FLOAT);
1564
1565         return box;
1566 }
1567
1568 /*
1569  *-----------------------------------------------------------------------------
1570  * misc
1571  *-----------------------------------------------------------------------------
1572  */
1573
1574 static void layout_util_sync_views(LayoutWindow *lw)
1575 {
1576         GtkAction *action;
1577
1578         if (!lw->action_group) return;
1579
1580         action = gtk_action_group_get_action(lw->action_group, "FolderTree");
1581         radio_action_set_current_value(GTK_RADIO_ACTION(action), lw->dir_view_type);
1582
1583         action = gtk_action_group_get_action(lw->action_group, "ViewIcons");
1584         gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->file_view_type);
1585
1586         action = gtk_action_group_get_action(lw->action_group, "FloatTools");
1587         gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->tools_float);
1588
1589         action = gtk_action_group_get_action(lw->action_group, "SBarKeywords");
1590         gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->bar_info_enabled);
1591
1592         action = gtk_action_group_get_action(lw->action_group, "SBarExif");
1593         gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->bar_exif_enabled);
1594
1595         action = gtk_action_group_get_action(lw->action_group, "SBarSort");
1596         gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->bar_sort_enabled);
1597
1598         action = gtk_action_group_get_action(lw->action_group, "HideToolbar");
1599         gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->toolbar_hidden);
1600
1601         action = gtk_action_group_get_action(lw->action_group, "ShowMarks");
1602         gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->marks_enabled);
1603
1604         action = gtk_action_group_get_action(lw->action_group, "SlideShow");
1605         gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), layout_image_slideshow_active(lw));
1606 }
1607
1608 void layout_util_sync_thumb(LayoutWindow *lw)
1609 {
1610         GtkAction *action;
1611
1612         if (!lw->action_group) return;
1613
1614         action = gtk_action_group_get_action(lw->action_group, "Thumbnails");
1615         gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->thumbs_enabled);
1616         g_object_set(action, "sensitive", (lw->file_view_type == FILEVIEW_LIST), NULL);
1617
1618         gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(lw->thumb_button), lw->thumbs_enabled);
1619         gtk_widget_set_sensitive(lw->thumb_button, (lw->file_view_type == FILEVIEW_LIST));
1620 }
1621
1622 void layout_util_sync(LayoutWindow *lw)
1623 {
1624         layout_util_sync_views(lw);
1625         layout_util_sync_thumb(lw);
1626         layout_menu_recent_update(lw);
1627         layout_menu_edit_update(lw);
1628 }
1629
1630 /*
1631  *-----------------------------------------------------------------------------
1632  * icons (since all the toolbar icons are included here, best place as any)
1633  *-----------------------------------------------------------------------------
1634  */
1635
1636 PixmapFolders *folder_icons_new(void)
1637 {
1638         PixmapFolders *pf;
1639
1640         pf = g_new0(PixmapFolders, 1);
1641
1642         pf->close = pixbuf_inline(PIXBUF_INLINE_FOLDER_CLOSED);
1643         pf->open = pixbuf_inline(PIXBUF_INLINE_FOLDER_OPEN);
1644         pf->deny = pixbuf_inline(PIXBUF_INLINE_FOLDER_LOCKED);
1645         pf->parent = pixbuf_inline(PIXBUF_INLINE_FOLDER_UP);
1646
1647         return pf;
1648 }
1649
1650 void folder_icons_free(PixmapFolders *pf)
1651 {
1652         if (!pf) return;
1653
1654         g_object_unref(pf->close);
1655         g_object_unref(pf->open);
1656         g_object_unref(pf->deny);
1657         g_object_unref(pf->parent);
1658
1659         g_free(pf);
1660 }
1661
1662 /*
1663  *-----------------------------------------------------------------------------
1664  * sidebars
1665  *-----------------------------------------------------------------------------
1666  */
1667
1668 static void layout_bar_info_destroyed(GtkWidget *widget, gpointer data)
1669 {
1670         LayoutWindow *lw = data;
1671
1672         lw->bar_info = NULL;
1673
1674         if (lw->utility_box)
1675                 {
1676                 /* destroyed from within itself */
1677                 lw->bar_info_enabled = FALSE;
1678                 layout_util_sync_views(lw);
1679                 }
1680 }
1681
1682 static GList *layout_bar_info_list_cb(gpointer data)
1683 {
1684         LayoutWindow *lw = data;
1685
1686         return layout_selection_list(lw);
1687 }
1688
1689 static void layout_bar_info_sized(GtkWidget *widget, GtkAllocation *allocation, gpointer data)
1690 {
1691         LayoutWindow *lw = data;
1692
1693         if (!lw->bar_info) return;
1694         
1695         options->panels.info.width = lw->bar_info_width = allocation->width;
1696 }
1697
1698 static void layout_bar_info_new(LayoutWindow *lw)
1699 {
1700         if (!lw->utility_box) return;
1701
1702         lw->bar_info = bar_info_new(layout_image_get_fd(lw), FALSE, lw->utility_box);
1703         bar_info_set_selection_func(lw->bar_info, layout_bar_info_list_cb, lw);
1704         bar_info_selection(lw->bar_info, layout_selection_count(lw, NULL) - 1);
1705         g_signal_connect(G_OBJECT(lw->bar_info), "destroy",
1706                          G_CALLBACK(layout_bar_info_destroyed), lw);
1707         g_signal_connect(G_OBJECT(lw->bar_info), "size_allocate",
1708                          G_CALLBACK(layout_bar_info_sized), lw);
1709
1710         options->panels.info.enabled = lw->bar_info_enabled = TRUE;
1711         gtk_widget_set_size_request(lw->bar_info, lw->bar_info_width, -1);
1712
1713         gtk_box_pack_start(GTK_BOX(lw->utility_box), lw->bar_info, FALSE, FALSE, 0);
1714         gtk_widget_show(lw->bar_info);
1715 }
1716
1717 static void layout_bar_info_close(LayoutWindow *lw)
1718 {
1719         if (lw->bar_info)
1720                 {
1721                 bar_info_close(lw->bar_info);
1722                 lw->bar_info = NULL;
1723                 }
1724         options->panels.info.enabled = lw->bar_info_enabled = FALSE;
1725 }
1726
1727 void layout_bar_info_toggle(LayoutWindow *lw)
1728 {
1729         if (lw->bar_info_enabled)
1730                 {
1731                 layout_bar_info_close(lw);
1732                 }
1733         else
1734                 {
1735                 layout_bar_info_new(lw);
1736                 }
1737 }
1738
1739 static void layout_bar_info_new_image(LayoutWindow *lw)
1740 {
1741         if (!lw->bar_info || !lw->bar_info_enabled) return;
1742
1743         bar_info_set(lw->bar_info, layout_image_get_fd(lw));
1744 }
1745
1746 static void layout_bar_info_new_selection(LayoutWindow *lw, gint count)
1747 {
1748         if (!lw->bar_info || !lw->bar_info_enabled) return;
1749
1750         bar_info_selection(lw->bar_info, count - 1);
1751 }
1752
1753 static void layout_bar_info_maint_renamed(LayoutWindow *lw)
1754 {
1755         if (!lw->bar_info || !lw->bar_info_enabled) return;
1756
1757         bar_info_maint_renamed(lw->bar_info, layout_image_get_fd(lw));
1758 }
1759
1760 static void layout_bar_exif_destroyed(GtkWidget *widget, gpointer data)
1761 {
1762         LayoutWindow *lw = data;
1763
1764         if (lw->bar_exif)
1765                 {
1766                 lw->bar_exif_advanced = bar_exif_is_advanced(lw->bar_exif);
1767                 }
1768
1769         lw->bar_exif = NULL;
1770         if (lw->utility_box)
1771                 {
1772                 /* destroyed from within itself */
1773                 lw->bar_exif_enabled = FALSE;
1774                 layout_util_sync_views(lw);
1775                 }
1776 }
1777
1778 static void layout_bar_exif_sized(GtkWidget *widget, GtkAllocation *allocation, gpointer data)
1779 {
1780         LayoutWindow *lw = data;
1781
1782         if (!lw->bar_exif) return;
1783         
1784         options->panels.exif.width = lw->bar_exif_width = allocation->width;
1785 }
1786
1787 static void layout_bar_exif_new(LayoutWindow *lw)
1788 {
1789         if (!lw->utility_box) return;
1790
1791         lw->bar_exif = bar_exif_new(TRUE, layout_image_get_fd(lw),
1792                                     lw->bar_exif_advanced, lw->utility_box);
1793         g_signal_connect(G_OBJECT(lw->bar_exif), "destroy",
1794                          G_CALLBACK(layout_bar_exif_destroyed), lw);
1795         g_signal_connect(G_OBJECT(lw->bar_exif), "size_allocate",
1796                          G_CALLBACK(layout_bar_exif_sized), lw);
1797
1798         options->panels.exif.enabled = lw->bar_exif_enabled = TRUE;
1799         gtk_widget_set_size_request(lw->bar_exif, lw->bar_exif_width, -1);
1800
1801         gtk_box_pack_start(GTK_BOX(lw->utility_box), lw->bar_exif, FALSE, FALSE, 0);
1802         if (lw->bar_info) gtk_box_reorder_child(GTK_BOX(lw->utility_box), lw->bar_exif, 1);
1803         gtk_widget_show(lw->bar_exif);
1804 }
1805
1806 static void layout_bar_exif_close(LayoutWindow *lw)
1807 {
1808         if (lw->bar_exif)
1809                 {
1810                 bar_exif_close(lw->bar_exif);
1811                 lw->bar_exif = NULL;
1812                 }
1813         options->panels.exif.enabled = lw->bar_exif_enabled = FALSE;
1814 }
1815
1816 void layout_bar_exif_toggle(LayoutWindow *lw)
1817 {
1818         if (lw->bar_exif_enabled)
1819                 {
1820                 layout_bar_exif_close(lw);
1821                 }
1822         else
1823                 {
1824                 layout_bar_exif_new(lw);
1825                 }
1826 }
1827
1828 static void layout_bar_exif_new_image(LayoutWindow *lw)
1829 {
1830         if (!lw->bar_exif || !lw->bar_exif_enabled) return;
1831
1832         bar_exif_set(lw->bar_exif, layout_image_get_fd(lw));
1833 }
1834
1835 static void layout_bar_sort_destroyed(GtkWidget *widget, gpointer data)
1836 {
1837         LayoutWindow *lw = data;
1838
1839         lw->bar_sort = NULL;
1840
1841         if (lw->utility_box)
1842                 {
1843                 /* destroyed from within itself */
1844                 lw->bar_sort_enabled = FALSE;
1845
1846                 layout_util_sync_views(lw);
1847                 }
1848 }
1849
1850 static void layout_bar_sort_new(LayoutWindow *lw)
1851 {
1852         if (!lw->utility_box) return;
1853
1854         lw->bar_sort = bar_sort_new(lw);
1855         g_signal_connect(G_OBJECT(lw->bar_sort), "destroy",
1856                          G_CALLBACK(layout_bar_sort_destroyed), lw);
1857         options->panels.sort.enabled = lw->bar_sort_enabled = TRUE;
1858
1859         gtk_box_pack_end(GTK_BOX(lw->utility_box), lw->bar_sort, FALSE, FALSE, 0);
1860         gtk_widget_show(lw->bar_sort);
1861 }
1862
1863 static void layout_bar_sort_close(LayoutWindow *lw)
1864 {
1865         if (lw->bar_sort)
1866                 {
1867                 bar_sort_close(lw->bar_sort);
1868                 lw->bar_sort = NULL;
1869                 }
1870         options->panels.sort.enabled = lw->bar_sort_enabled = FALSE;
1871 }
1872
1873 void layout_bar_sort_toggle(LayoutWindow *lw)
1874 {
1875         if (lw->bar_sort_enabled)
1876                 {
1877                 layout_bar_sort_close(lw);
1878                 }
1879         else
1880                 {
1881                 layout_bar_sort_new(lw);
1882                 }
1883 }
1884
1885 void layout_bars_new_image(LayoutWindow *lw)
1886 {
1887         layout_bar_info_new_image(lw);
1888         layout_bar_exif_new_image(lw);
1889 }
1890
1891 void layout_bars_new_selection(LayoutWindow *lw, gint count)
1892 {
1893         layout_bar_info_new_selection(lw, count);
1894 }
1895
1896 GtkWidget *layout_bars_prepare(LayoutWindow *lw, GtkWidget *image)
1897 {
1898         lw->utility_box = gtk_hbox_new(FALSE, PREF_PAD_GAP);
1899         gtk_box_pack_start(GTK_BOX(lw->utility_box), image, TRUE, TRUE, 0);
1900         gtk_widget_show(image);
1901
1902         if (lw->bar_sort_enabled)
1903                 {
1904                 layout_bar_sort_new(lw);
1905                 }
1906
1907         if (lw->bar_info_enabled)
1908                 {
1909                 layout_bar_info_new(lw);
1910                 }
1911
1912         if (lw->bar_exif_enabled)
1913                 {
1914                 layout_bar_exif_new(lw);
1915                 }
1916
1917         return lw->utility_box;
1918 }
1919
1920 void layout_bars_close(LayoutWindow *lw)
1921 {
1922         layout_bar_sort_close(lw);
1923         layout_bar_exif_close(lw);
1924         layout_bar_info_close(lw);
1925 }
1926
1927 void layout_bars_maint_renamed(LayoutWindow *lw)
1928 {
1929         layout_bar_info_maint_renamed(lw);
1930 }