X-Git-Url: http://geeqie.org/cgi-bin/gitweb.cgi?p=geeqie.git;a=blobdiff_plain;f=src%2Flayout_util.c;h=fc431c899a42335a60afbe03c442fa0a672ceead;hp=4f6e4d2e7787980c79aac240047e9fec3da15662;hb=f6a87c016ecead37f8232bea58de4f0b0d3e3680;hpb=b514d250a6bf056da22f144876fb3a367c35e943 diff --git a/src/layout_util.c b/src/layout_util.c index 4f6e4d2e..fc431c89 100644 --- a/src/layout_util.c +++ b/src/layout_util.c @@ -1,16 +1,24 @@ /* - * Geeqie - * (C) 2004 John Ellis - * Copyright (C) 2008 - 2009 The Geeqie Team + * Copyright (C) 2004 John Ellis + * Copyright (C) 2008 - 2016 The Geeqie Team * * Author: John Ellis * - * This software is released under the GNU General Public License (GNU GPL). - * Please read the included file COPYING for more information. - * This software comes with no warranty of any kind, use at your own risk! + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "main.h" #include "layout_util.h" @@ -43,18 +51,20 @@ #include "ui_tabcomp.h" #include "utilops.h" #include "view_dir.h" +#include "view_file.h" #include "window.h" #include "metadata.h" -#include "rcfile.h" #include "desktop_file.h" #include /* for keyboard values */ - +#include "keymap_template.c" #define MENU_EDIT_ACTION_OFFSET 16 +#define FILE_COLUMN_POINTER 0 static gboolean layout_bar_enabled(LayoutWindow *lw); static gboolean layout_bar_sort_enabled(LayoutWindow *lw); +static void layout_bars_hide_toggle(LayoutWindow *lw); static void layout_util_sync_views(LayoutWindow *lw); /* @@ -64,10 +74,10 @@ static void layout_util_sync_views(LayoutWindow *lw); */ static guint tree_key_overrides[] = { - GDK_Page_Up, GDK_KP_Page_Up, - GDK_Page_Down, GDK_KP_Page_Down, - GDK_Home, GDK_KP_Home, - GDK_End, GDK_KP_End + GDK_KEY_Page_Up, GDK_KEY_KP_Page_Up, + GDK_KEY_Page_Down, GDK_KEY_KP_Page_Down, + GDK_KEY_Home, GDK_KEY_KP_Home, + GDK_KEY_End, GDK_KEY_KP_End }; static gboolean layout_key_match(guint keyval) @@ -85,13 +95,14 @@ static gboolean layout_key_match(guint keyval) gboolean layout_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer data) { LayoutWindow *lw = data; + GtkWidget *focused; gboolean stop_signal = FALSE; gint x = 0; gint y = 0; - if (lw->path_entry && GTK_WIDGET_HAS_FOCUS(lw->path_entry)) + if (lw->path_entry && gtk_widget_has_focus(lw->path_entry)) { - if (event->keyval == GDK_Escape && lw->dir_fd) + if (event->keyval == GDK_KEY_Escape && lw->dir_fd) { gtk_entry_set_text(GTK_ENTRY(lw->path_entry), lw->dir_fd->path); } @@ -104,7 +115,7 @@ gboolean layout_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer dat return TRUE; } } - if (lw->vd && lw->options.dir_view_type == DIRVIEW_TREE && GTK_WIDGET_HAS_FOCUS(lw->vd->view) && + if (lw->vd && lw->options.dir_view_type == DIRVIEW_TREE && gtk_widget_has_focus(lw->vd->view) && !layout_key_match(event->keyval) && gtk_widget_event(lw->vd->view, (GdkEvent *)event)) { @@ -116,28 +127,23 @@ gboolean layout_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer dat return TRUE; } -/* - if (event->type == GDK_KEY_PRESS && lw->full_screen && - gtk_accel_groups_activate(G_OBJECT(lw->window), event->keyval, event->state)) - return TRUE; -*/ - + focused = gtk_container_get_focus_child(GTK_CONTAINER(lw->image->widget)); if (lw->image && - (GTK_WIDGET_HAS_FOCUS(lw->image->widget) || (lw->tools && widget == lw->window) || lw->full_screen) ) + ((focused && gtk_widget_has_focus(focused)) || (lw->tools && widget == lw->window) || lw->full_screen) ) { stop_signal = TRUE; switch (event->keyval) { - case GDK_Left: case GDK_KP_Left: + case GDK_KEY_Left: case GDK_KEY_KP_Left: x -= 1; break; - case GDK_Right: case GDK_KP_Right: + case GDK_KEY_Right: case GDK_KEY_KP_Right: x += 1; break; - case GDK_Up: case GDK_KP_Up: + case GDK_KEY_Up: case GDK_KEY_KP_Up: y -= 1; break; - case GDK_Down: case GDK_KP_Down: + case GDK_KEY_Down: case GDK_KEY_KP_Down: y += 1; break; default: @@ -151,7 +157,7 @@ gboolean layout_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer dat stop_signal = TRUE; switch (event->keyval) { - case GDK_Menu: + case GDK_KEY_Menu: layout_image_menu_popup(lw); break; default: @@ -200,7 +206,9 @@ static void layout_menu_new_window_cb(GtkAction *action, gpointer data) LayoutWindow *nw; LayoutOptions lop; gboolean tmp = options->save_window_positions; - options->save_window_positions = FALSE; /* let the windowmanager decide for the first time */ + + if (!options->use_saved_window_positions_for_new_windows) + options->save_window_positions = FALSE; /* let the windowmanager decide for the first time */ layout_exit_fullscreen(lw); @@ -243,7 +251,7 @@ static void layout_menu_dupes_cb(GtkAction *action, gpointer data) LayoutWindow *lw = data; layout_exit_fullscreen(lw); - dupe_window_new(DUPE_MATCH_NAME); + dupe_window_new(); } static void layout_menu_pan_cb(GtkAction *action, gpointer data) @@ -303,6 +311,16 @@ static void layout_menu_delete_cb(GtkAction *action, gpointer data) file_util_delete(NULL, layout_selection_list(lw), layout_window(lw)); } +static void layout_menu_delete_key_cb(GtkAction *action, gpointer data) +{ + LayoutWindow *lw = data; + + if (options->file_ops.enable_delete_key) + { + file_util_delete(NULL, layout_selection_list(lw), layout_window(lw)); + } +} + static void layout_menu_disable_grouping_cb(GtkAction *action, gpointer data) { LayoutWindow *lw = data; @@ -337,6 +355,55 @@ static void layout_menu_alter_90_cb(GtkAction *action, gpointer data) layout_image_alter_orientation(lw, ALTER_ROTATE_90); } +static void layout_menu_rating_0_cb(GtkAction *action, gpointer data) +{ + LayoutWindow *lw = data; + + layout_image_rating(lw, "0"); +} + +static void layout_menu_rating_1_cb(GtkAction *action, gpointer data) +{ + LayoutWindow *lw = data; + + layout_image_rating(lw, "1"); +} + +static void layout_menu_rating_2_cb(GtkAction *action, gpointer data) +{ + LayoutWindow *lw = data; + + layout_image_rating(lw, "2"); +} + +static void layout_menu_rating_3_cb(GtkAction *action, gpointer data) +{ + LayoutWindow *lw = data; + + layout_image_rating(lw, "3"); +} + +static void layout_menu_rating_4_cb(GtkAction *action, gpointer data) +{ + LayoutWindow *lw = data; + + layout_image_rating(lw, "4"); +} + +static void layout_menu_rating_5_cb(GtkAction *action, gpointer data) +{ + LayoutWindow *lw = data; + + layout_image_rating(lw, "5"); +} + +static void layout_menu_rating_m1_cb(GtkAction *action, gpointer data) +{ + LayoutWindow *lw = data; + + layout_image_rating(lw, "-1"); +} + static void layout_menu_alter_90cc_cb(GtkAction *action, gpointer data) { LayoutWindow *lw = data; @@ -379,6 +446,109 @@ static void layout_menu_alter_none_cb(GtkAction *action, gpointer data) layout_image_alter_orientation(lw, ALTER_NONE); } +static void layout_menu_exif_rotate_cb(GtkToggleAction *action, gpointer data) +{ + LayoutWindow *lw = data; + + options->image.exif_rotate_enable = gtk_toggle_action_get_active(action); + layout_image_reset_orientation(lw); +} + +static void layout_menu_write_rotate(GtkToggleAction *action, gpointer data, gboolean keep_date) +{ + LayoutWindow *lw = data; + GtkTreeModel *store; + GList *work; + GtkTreeSelection *selection; + GtkTreePath *tpath; + FileData *fd_n; + GtkTreeIter iter; + IconData *id; + gchar *rotation; + gchar *command; + gint run_result; + GenericDialog *gd; + GString *message; + + if (!layout_valid(&lw)) return; + + if (!lw || !lw->vf) return; + + if (lw->vf->type == FILEVIEW_ICON) + { + if (!VFICON(lw->vf)->selection) return; + work = VFICON(lw->vf)->selection; + } + else + { + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(lw->vf->listview)); + work = gtk_tree_selection_get_selected_rows(selection, &store); + } + + while (work) + { + if (lw->vf->type == FILEVIEW_ICON) + { + id = work->data; + fd_n = id->fd; + work = work->next; + } + else + { + tpath = work->data; + gtk_tree_model_get_iter(store, &iter, tpath); + gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd_n, -1); + work = work->next; + } + + rotation = g_strdup_printf("%d", fd_n->user_orientation); + command = g_strconcat(GQ_BIN_DIR, "/geeqie-rotate -r ", rotation, + keep_date ? " -t " : " ", fd_n->path, NULL); + + run_result = WEXITSTATUS(runcmd(command)); + if (!run_result) + { + fd_n->user_orientation = 0; + } + else + { + message = g_string_new(""); + message = g_string_append(message, _("Operation failed:\n")); + + if (run_result == 3) + message = g_string_append(message, _("Cannot create tmp file")); + else + { + message = g_string_append(message, _("File: ")); + message = g_string_append(message, fd_n->name); + } + + gd = generic_dialog_new(_("Image orientation"), + "Image orientation", NULL, TRUE, NULL, NULL); + generic_dialog_add_message(gd, GTK_STOCK_DIALOG_ERROR, + "Image orientation", message->str); + generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, NULL, TRUE); + + gtk_widget_show(gd->dialog); + + g_string_free(message, TRUE); + } + + g_free(rotation); + g_free(command); + } +} + +static void layout_menu_write_rotate_keep_date_cb(GtkToggleAction *action, gpointer data) +{ + layout_menu_write_rotate(action, data, TRUE); +} + +static void layout_menu_write_rotate_cb(GtkToggleAction *action, gpointer data) +{ + layout_menu_write_rotate(action, data, FALSE); +} + static void layout_menu_config_cb(GtkAction *action, gpointer data) { LayoutWindow *lw = data; @@ -609,17 +779,25 @@ static void layout_menu_thumb_cb(GtkToggleAction *action, gpointer data) static void layout_menu_list_cb(GtkRadioAction *action, GtkRadioAction *current, gpointer data) { LayoutWindow *lw = data; - + layout_exit_fullscreen(lw); layout_views_set(lw, lw->options.dir_view_type, (FileViewType) gtk_radio_action_get_current_value(action)); } -static void layout_menu_view_dir_as_cb(GtkRadioAction *action, GtkRadioAction *current, gpointer data) +static void layout_menu_view_dir_as_cb(GtkToggleAction *action, gpointer data) { LayoutWindow *lw = data; layout_exit_fullscreen(lw); - layout_views_set(lw, (DirViewType) gtk_radio_action_get_current_value(action), lw->options.file_view_type); + + if (gtk_toggle_action_get_active(action)) + { + layout_views_set(lw, DIRVIEW_TREE, lw->options.file_view_type); + } + else + { + layout_views_set(lw, DIRVIEW_LIST, lw->options.file_view_type); + } } static void layout_menu_view_in_new_window_cb(GtkAction *action, gpointer data) @@ -642,11 +820,6 @@ static void layout_menu_escape_cb(GtkAction *action, gpointer data) LayoutWindow *lw = data; layout_exit_fullscreen(lw); - - /* FIXME:interrupting thumbs no longer allowed */ -#if 0 - interrupt_thumbs(); -#endif } static void layout_menu_overlay_toggle_cb(GtkAction *action, gpointer data) @@ -661,17 +834,18 @@ static void layout_menu_overlay_toggle_cb(GtkAction *action, gpointer data) static void layout_menu_overlay_cb(GtkToggleAction *action, gpointer data) { LayoutWindow *lw = data; - GtkToggleAction *histogram_action = GTK_TOGGLE_ACTION(gtk_action_group_get_action(lw->action_group, "ImageHistogram")); if (gtk_toggle_action_get_active(action)) { OsdShowFlags flags = image_osd_get(lw->image); - + if ((flags | OSD_SHOW_INFO | OSD_SHOW_STATUS) != flags) image_osd_set(lw->image, flags | OSD_SHOW_INFO | OSD_SHOW_STATUS); } else { + GtkToggleAction *histogram_action = GTK_TOGGLE_ACTION(gtk_action_group_get_action(lw->action_group, "ImageHistogram")); + image_osd_set(lw->image, OSD_SHOW_NOTHING); gtk_toggle_action_set_active(histogram_action, FALSE); /* this calls layout_menu_histogram_cb */ } @@ -680,7 +854,6 @@ static void layout_menu_overlay_cb(GtkToggleAction *action, gpointer data) static void layout_menu_histogram_cb(GtkToggleAction *action, gpointer data) { LayoutWindow *lw = data; - GtkToggleAction *overlay_action = GTK_TOGGLE_ACTION(gtk_action_group_get_action(lw->action_group, "ImageOverlay")); if (gtk_toggle_action_get_active(action)) { @@ -695,6 +868,21 @@ static void layout_menu_histogram_cb(GtkToggleAction *action, gpointer data) } } +static void layout_menu_animate_cb(GtkToggleAction *action, gpointer data) +{ + LayoutWindow *lw = data; + + if (lw->options.animate == gtk_toggle_action_get_active(action)) return; + layout_image_animate_toggle(lw); +} + +static void layout_menu_rectangular_selection_cb(GtkToggleAction *action, gpointer data) +{ + LayoutWindow *lw = data; + + options->collections.rectangular_selection = gtk_toggle_action_get_active(action); +} + static void layout_menu_histogram_toggle_channel_cb(GtkAction *action, gpointer data) { LayoutWindow *lw = data; @@ -718,7 +906,7 @@ static void layout_menu_histogram_channel_cb(GtkRadioAction *action, GtkRadioAct GtkToggleAction *histogram_action = GTK_TOGGLE_ACTION(gtk_action_group_get_action(lw->action_group, "ImageHistogram")); if (channel < 0 || channel >= HCHAN_COUNT) return; - + gtk_toggle_action_set_active(histogram_action, TRUE); /* this calls layout_menu_histogram_cb */ image_osd_histogram_set_channel(lw->image, channel); } @@ -730,7 +918,7 @@ static void layout_menu_histogram_mode_cb(GtkRadioAction *action, GtkRadioAction GtkToggleAction *histogram_action = GTK_TOGGLE_ACTION(gtk_action_group_get_action(lw->action_group, "ImageHistogram")); if (mode < 0 || mode > 1) return; - + gtk_toggle_action_set_active(histogram_action, TRUE); /* this calls layout_menu_histogram_cb */ image_osd_histogram_set_mode(lw->image, mode); } @@ -745,7 +933,7 @@ static void layout_menu_refresh_cb(GtkAction *action, gpointer data) static void layout_menu_bar_exif_cb(GtkAction *action, gpointer data) { LayoutWindow *lw = data; - + layout_exit_fullscreen(lw); layout_exif_window_new(lw); } @@ -809,10 +997,18 @@ static void layout_menu_bar_sort_cb(GtkToggleAction *action, gpointer data) layout_bar_sort_toggle(lw); } -static void layout_menu_slideshow_cb(GtkAction *action, gpointer data) +static void layout_menu_hide_bars_cb(GtkToggleAction *action, gpointer data) +{ + LayoutWindow *lw = data; + + layout_bars_hide_toggle(lw); +} + +static void layout_menu_slideshow_cb(GtkToggleAction *action, gpointer data) { LayoutWindow *lw = data; + if (layout_image_slideshow_active(lw) == gtk_toggle_action_get_active(action)) return; layout_image_slideshow_toggle(lw); } @@ -823,12 +1019,38 @@ static void layout_menu_slideshow_pause_cb(GtkAction *action, gpointer data) layout_image_slideshow_pause_toggle(lw); } + +static void layout_menu_stereo_mode_next_cb(GtkAction *action, gpointer data) +{ + LayoutWindow *lw = data; + gint mode = layout_image_stereo_pixbuf_get(lw); + + /* 0->1, 1->2, 2->3, 3->1 - disable auto, then cycle */ + mode = mode % 3 + 1; + + GtkAction *radio = gtk_action_group_get_action(lw->action_group, "StereoAuto"); + gtk_radio_action_set_current_value(GTK_RADIO_ACTION(radio), mode); + + /* + this is called via fallback in layout_menu_stereo_mode_cb + layout_image_stereo_pixbuf_set(lw, mode); + */ + +} + +static void layout_menu_stereo_mode_cb(GtkRadioAction *action, GtkRadioAction *current, gpointer data) +{ + LayoutWindow *lw = data; + gint mode = gtk_radio_action_get_current_value(action); + layout_image_stereo_pixbuf_set(lw, mode); +} + static void layout_menu_help_cb(GtkAction *action, gpointer data) { LayoutWindow *lw = data; layout_exit_fullscreen(lw); - help_window_show("html_contents"); + help_window_show("index.html"); } static void layout_menu_help_keys_cb(GtkAction *action, gpointer data) @@ -836,17 +1058,179 @@ static void layout_menu_help_keys_cb(GtkAction *action, gpointer data) LayoutWindow *lw = data; layout_exit_fullscreen(lw); - help_window_show("documentation"); + help_window_show("GuideReferenceKeyboardShortcuts.html"); } static void layout_menu_notes_cb(GtkAction *action, gpointer data) { LayoutWindow *lw = data; - + layout_exit_fullscreen(lw); help_window_show("release_notes"); } +static char *keyboard_map_hardcoded[][2] = { + {"Scroll","Left"}, + {"FastScroll", "<Shift>Left"}, + {"Left Border", "<Primary>Left"}, + {"Left Border", "<Primary><Shift>Left"}, + {"Scroll", "Right"}, + {"FastScroll", "<Shift>Right"}, + {"Right Border", "<Primary>Right"}, + {"Right Border", "<Primary><Shift>Right"}, + {"Scroll", "Up"}, + {"FastScroll", "<Shift>Up"}, + {"Uper Border", "<Primary>Up"}, + {"Uper Border", "<Primary><Shift>Up"}, + {"Scroll", "Down"}, + {"FastScroll", "<Shift>Down"}, + {"Lower Border", "<Primary>Down"}, + {"Lower Border", "<Primary><Shift>Down"}, + {"Next/Drag", "M1"}, + {"FastDrag", "<Shift>M1"}, + {"DnD Start", "M2"}, + {"Menu", "M3"}, + {"PrevImage", "MW4"}, + {"NextImage", "MW5"}, + {"ScrollUp", "<Shift>MW4"}, + {"ScrollDown", "<Shift>MW5"}, + {"ZoomIn", "<Primary>MW4"}, + {"ZoomOut", "<Primary>MW5"}, + {NULL, NULL} +}; + +static void layout_menu_foreach_func( + gpointer data, + const gchar *accel_path, + guint accel_key, + GdkModifierType accel_mods, + gboolean changed) +{ + gchar *path, *name; + gchar *key_name, *menu_name; + gchar **subset_lt_arr, **subset_gt_arr; + gchar *subset_lt, *converted_name; + GPtrArray *array = data; + + path = g_strescape(accel_path, NULL); + name = gtk_accelerator_name(accel_key, accel_mods); + + menu_name = g_strdup(g_strrstr(path, "/")+1); + + if (g_strrstr(name, ">")) + { + subset_lt_arr = g_strsplit_set(name,"<", 4); + subset_lt = g_strjoinv("<", subset_lt_arr); + subset_gt_arr = g_strsplit_set(subset_lt,">", 4); + converted_name = g_strjoinv(">", subset_gt_arr); + key_name = g_strdup(converted_name); + + g_free(converted_name); + g_free(subset_lt); + g_strfreev(subset_lt_arr); + g_strfreev(subset_gt_arr); + } + else + key_name = g_strdup(name); + + g_ptr_array_add(array, (gpointer)menu_name); + g_ptr_array_add(array, (gpointer)key_name); + + g_free(name); + g_free(path); +} + +static void layout_menu_kbd_map_cb(GtkAction *action, gpointer data) +{ + LayoutWindow *lw = data; + gint fd = -1; + GPtrArray *array; + char * tmp_file; + GError *error = NULL; + GIOChannel *channel; + char **pre_key, **post_key; + char *key_name, *converted_line; + int keymap_index, index; + + fd = g_file_open_tmp("geeqie_keymap_XXXXXX.svg", &tmp_file, &error); + if (error) + { + DEBUG_0("Keyboard Map - cannot create file:%s\n",error->message); + g_error_free(error); + } + else + { + array = g_ptr_array_new(); + + gtk_accel_map_foreach(array, layout_menu_foreach_func); + + channel = g_io_channel_unix_new(fd); + + keymap_index = 0; + while (keymap_template[keymap_index]) + { + if (g_strrstr(keymap_template[keymap_index], ">key:")) + { + pre_key = g_strsplit(keymap_template[keymap_index],">key:",2); + post_key = g_strsplit(pre_key[1],"<",2); + + index=0; + key_name = " "; + for (index=0; index < array->len-2; index=index+2) + { + if (!(g_ascii_strcasecmp(g_ptr_array_index(array,index+1), post_key[0]))) + { + key_name = g_ptr_array_index(array,index+0); + break; + } + } + + index=0; + while (keyboard_map_hardcoded[index][0]) + { + if (!(g_strcmp0(keyboard_map_hardcoded[index][1], post_key[0]))) + { + key_name = keyboard_map_hardcoded[index][0]; + break; + } + index++; + } + + converted_line = g_strconcat(pre_key[0], ">", key_name, "<", post_key[1], "\n", NULL); + g_io_channel_write_chars(channel, converted_line, -1, NULL, &error); + if (error) {DEBUG_0("Keyboard Map:%s\n",error->message); g_error_free(error);} + + g_free(converted_line); + g_strfreev(pre_key); + g_strfreev(post_key); + } + else + { + g_io_channel_write_chars(channel, keymap_template[keymap_index], -1, NULL, &error); + if (error) {DEBUG_0("Keyboard Map:%s\n",error->message); g_error_free(error);} + g_io_channel_write_chars(channel, "\n", -1, NULL, &error); + if (error) {DEBUG_0("Keyboard Map:%s\n",error->message); g_error_free(error);} + } + keymap_index++; + } + + g_io_channel_flush(channel, &error); + if (error) {DEBUG_0("Keyboard Map:%s\n",error->message); g_error_free(error);} + g_io_channel_unref(channel); + + index=0; + for (index=0; index < array->len-2; index=index+2) + { + g_free(g_ptr_array_index(array,index)); + g_free(g_ptr_array_index(array,index+1)); + } + g_ptr_array_unref(array); + + view_window_new(file_data_new_simple(tmp_file)); + g_free(tmp_file); + } +} + static void layout_menu_about_cb(GtkAction *action, gpointer data) { LayoutWindow *lw = data; @@ -860,7 +1244,7 @@ static void layout_menu_log_window_cb(GtkAction *action, gpointer data) LayoutWindow *lw = data; layout_exit_fullscreen(lw); - log_window_new(); + log_window_new(lw); } @@ -997,6 +1381,64 @@ static void layout_menu_image_next_cb(GtkAction *action, gpointer data) layout_image_next(lw); } +static void layout_menu_split_pane_next_cb(GtkAction *action, gpointer data) +{ + LayoutWindow *lw = data; + gint active_frame; + + active_frame = lw->active_split_image; + + if (active_frame < MAX_SPLIT_IMAGES-1 && lw->split_images[active_frame+1] ) + { + active_frame++; + } + else + { + active_frame = 0; + } + layout_image_activate(lw, active_frame, FALSE); +} + +static void layout_menu_split_pane_prev_cb(GtkAction *action, gpointer data) +{ + LayoutWindow *lw = data; + gint active_frame; + + active_frame = lw->active_split_image; + + if (active_frame >=1 && lw->split_images[active_frame-1] ) + { + active_frame--; + } + else + { + active_frame = MAX_SPLIT_IMAGES-1; + while (!lw->split_images[active_frame]) + { + active_frame--; + } + } + layout_image_activate(lw, active_frame, FALSE); +} + +static void layout_menu_split_pane_updown_cb(GtkAction *action, gpointer data) +{ + LayoutWindow *lw = data; + gint active_frame; + + active_frame = lw->active_split_image; + + if (lw->split_images[MAX_SPLIT_IMAGES-1] ) + { + active_frame = active_frame ^ 2; + } + else + { + active_frame = active_frame ^ 1; + } + layout_image_activate(lw, active_frame, FALSE); +} + static void layout_menu_image_last_cb(GtkAction *action, gpointer data) { LayoutWindow *lw = data; @@ -1023,9 +1465,9 @@ static void layout_menu_back_cb(GtkAction *action, gpointer data) } if (!path) return; - + /* Open previous path */ - dir_fd = file_data_new_simple(path); + dir_fd = file_data_new_dir(path); layout_set_fd(lw, dir_fd); file_data_unref(dir_fd); } @@ -1034,7 +1476,7 @@ static void layout_menu_home_cb(GtkAction *action, gpointer data) { LayoutWindow *lw = data; const gchar *path; - + if (lw->options.home_path && *lw->options.home_path) path = lw->options.home_path; else @@ -1042,12 +1484,31 @@ static void layout_menu_home_cb(GtkAction *action, gpointer data) if (path) { - FileData *dir_fd = file_data_new_simple(path); + FileData *dir_fd = file_data_new_dir(path); layout_set_fd(lw, dir_fd); file_data_unref(dir_fd); } } +static void layout_menu_up_cb(GtkAction *action, gpointer data) +{ + LayoutWindow *lw = data; + ViewDir *vd = lw->vd; + gchar *path; + + if (!vd->dir_fd || strcmp(vd->dir_fd->path, G_DIR_SEPARATOR_S) == 0) return; + path = remove_level_from_path(vd->dir_fd->path); + + if (vd->select_func) + { + FileData *fd = file_data_new_dir(path); + vd->select_func(vd, fd, vd->select_data); + file_data_unref(fd); + } + + g_free(path); +} + /* *----------------------------------------------------------------------------- @@ -1059,7 +1520,7 @@ static void layout_menu_edit_cb(GtkAction *action, gpointer data) { LayoutWindow *lw = data; const gchar *key = gtk_action_get_name(action); - + if (!editor_window_flag_set(key)) layout_exit_fullscreen(lw); @@ -1084,6 +1545,8 @@ static void layout_color_menu_enable_cb(GtkToggleAction *action, gpointer data) #ifdef HAVE_LCMS LayoutWindow *lw = data; + if (layout_image_color_profile_get_use(lw) == gtk_toggle_action_get_active(action)) return; + layout_image_color_profile_set_use(lw, gtk_toggle_action_get_active(action)); layout_util_sync_color(lw); layout_image_refresh(lw); @@ -1098,6 +1561,7 @@ static void layout_color_menu_use_image_cb(GtkToggleAction *action, gpointer dat gboolean use_image; if (!layout_image_color_profile_get(lw, &input, &use_image)) return; + if (use_image == gtk_toggle_action_get_active(action)) return; layout_image_color_profile_set(lw, input, gtk_toggle_action_get_active(action)); layout_util_sync_color(lw); layout_image_refresh(lw); @@ -1227,32 +1691,35 @@ void layout_recent_add_path(const gchar *path) #define CB G_CALLBACK static GtkActionEntry menu_entries[] = { - { "FileMenu", NULL, N_("_File"), NULL, NULL, NULL }, - { "GoMenu", NULL, N_("_Go"), NULL, NULL, NULL }, - { "EditMenu", NULL, N_("_Edit"), NULL, NULL, NULL }, - { "SelectMenu", NULL, N_("_Select"), NULL, NULL, NULL }, - { "OrientationMenu", NULL, N_("_Orientation"), NULL, NULL, NULL }, - { "ExternalMenu", NULL, N_("E_xternal Editors"), NULL, NULL, NULL }, - { "PreferencesMenu", NULL, N_("P_references"), NULL, NULL, NULL }, - { "ViewMenu", NULL, N_("_View"), NULL, NULL, NULL }, - { "FileDirMenu", NULL, N_("_Files and Folders"), NULL, NULL, NULL }, - { "ZoomMenu", NULL, N_("_Zoom"), NULL, NULL, NULL }, - { "ColorMenu", NULL, N_("_Color Management"), NULL, NULL, NULL }, - { "ConnectZoomMenu", NULL, N_("_Connected Zoom"), NULL, NULL, NULL }, - { "SplitMenu", NULL, N_("Spli_t"), NULL, NULL, NULL }, - { "OverlayMenu", NULL, N_("Image _Overlay"), NULL, NULL, NULL }, - { "HelpMenu", NULL, N_("_Help"), NULL, NULL, NULL }, + { "FileMenu", NULL, N_("_File"), NULL, NULL, NULL }, + { "GoMenu", NULL, N_("_Go"), NULL, NULL, NULL }, + { "EditMenu", NULL, N_("_Edit"), NULL, NULL, NULL }, + { "SelectMenu", NULL, N_("_Select"), NULL, NULL, NULL }, + { "OrientationMenu", NULL, N_("_Orientation"), NULL, NULL, NULL }, + { "RatingMenu", NULL, N_("_Rating"), NULL, NULL, NULL }, + { "ExternalMenu", NULL, N_("E_xternal Editors"), NULL, NULL, NULL }, + { "PreferencesMenu", NULL, N_("P_references"), NULL, NULL, NULL }, + { "ViewMenu", NULL, N_("_View"), NULL, NULL, NULL }, + { "FileDirMenu", NULL, N_("_Files and Folders"), NULL, NULL, NULL }, + { "ZoomMenu", NULL, N_("_Zoom"), NULL, NULL, NULL }, + { "ColorMenu", NULL, N_("_Color Management"), NULL, NULL, NULL }, + { "ConnectZoomMenu", NULL, N_("_Connected Zoom"), NULL, NULL, NULL }, + { "SplitMenu", NULL, N_("Spli_t"), NULL, NULL, NULL }, + { "StereoMenu", NULL, N_("Stere_o"), NULL, NULL, NULL }, + { "OverlayMenu", NULL, N_("Image _Overlay"), NULL, NULL, NULL }, + { "HelpMenu", NULL, N_("_Help"), NULL, NULL, NULL }, { "FirstImage", GTK_STOCK_GOTO_TOP, N_("_First Image"), "Home", N_("First Image"), CB(layout_menu_image_first_cb) }, - { "PrevImage", GTK_STOCK_GO_UP, N_("_Previous Image"), "BackSpace", N_("Previous Image"), CB(layout_menu_image_prev_cb) }, - { "PrevImageAlt1", GTK_STOCK_GO_UP, N_("_Previous Image"), "Page_Up", N_("Previous Image"), CB(layout_menu_image_prev_cb) }, - { "PrevImageAlt2", GTK_STOCK_GO_UP, N_("_Previous Image"), "KP_Page_Up", N_("Previous Image"), CB(layout_menu_image_prev_cb) }, + { "PrevImage", GTK_STOCK_GO_UP, N_("_Previous Image"), "BackSpace", N_("Previous Image"), CB(layout_menu_image_prev_cb) }, + { "PrevImageAlt1", GTK_STOCK_GO_UP, N_("_Previous Image"), "Page_Up", N_("Previous Image"), CB(layout_menu_image_prev_cb) }, + { "PrevImageAlt2", GTK_STOCK_GO_UP, N_("_Previous Image"), "KP_Page_Up", N_("Previous Image"), CB(layout_menu_image_prev_cb) }, { "NextImage", GTK_STOCK_GO_DOWN, N_("_Next Image"), "space", N_("Next Image"), CB(layout_menu_image_next_cb) }, { "NextImageAlt1", GTK_STOCK_GO_DOWN, N_("_Next Image"), "Page_Down", N_("Next Image"), CB(layout_menu_image_next_cb) }, { "NextImageAlt2", GTK_STOCK_GO_DOWN, N_("_Next Image"), "KP_Page_Down", N_("Next Image"), CB(layout_menu_image_next_cb) }, { "LastImage", GTK_STOCK_GOTO_BOTTOM, N_("_Last Image"), "End", N_("Last Image"), CB(layout_menu_image_last_cb) }, { "Back", GTK_STOCK_GO_BACK, N_("_Back"), NULL, N_("Back"), CB(layout_menu_back_cb) }, { "Home", GTK_STOCK_HOME, N_("_Home"), NULL, N_("Home"), CB(layout_menu_home_cb) }, + { "Up", GTK_STOCK_GO_UP, N_("_Up"), NULL, N_("Up"), CB(layout_menu_up_cb) }, { "NewWindow", GTK_STOCK_NEW, N_("New _window"), "N", N_("New window"), CB(layout_menu_new_window_cb) }, { "NewCollection", GTK_STOCK_INDEX, N_("_New collection"), "C", N_("New collection"), CB(layout_menu_new_cb) }, @@ -1267,14 +1734,21 @@ static GtkActionEntry menu_entries[] = { { "Move", NULL, N_("_Move..."), "M", N_("Move..."), CB(layout_menu_move_cb) }, { "Rename", NULL, N_("_Rename..."), "R", N_("Rename..."), CB(layout_menu_rename_cb) }, { "Delete", GTK_STOCK_DELETE, N_("_Delete..."), "D", N_("Delete..."), CB(layout_menu_delete_cb) }, - { "DeleteAlt1", GTK_STOCK_DELETE, N_("_Delete..."), "Delete", N_("Delete..."), CB(layout_menu_delete_cb) }, - { "DeleteAlt2", GTK_STOCK_DELETE, N_("_Delete..."), "KP_Delete", N_("Delete..."), CB(layout_menu_delete_cb) }, + { "DeleteAlt1", GTK_STOCK_DELETE, N_("_Delete..."), "Delete", N_("Delete..."), CB(layout_menu_delete_key_cb) }, + { "DeleteAlt2", GTK_STOCK_DELETE, N_("_Delete..."), "KP_Delete", N_("Delete..."), CB(layout_menu_delete_key_cb) }, { "EnableGrouping", NULL, N_("Enable file _grouping"), NULL, N_("Enable file grouping"), CB(layout_menu_enable_grouping_cb) }, { "DisableGrouping", NULL, N_("Disable file groupi_ng"), NULL, N_("Disable file grouping"), CB(layout_menu_disable_grouping_cb) }, { "CopyPath", NULL, N_("_Copy path to clipboard"), NULL, N_("Copy path to clipboard"), CB(layout_menu_copy_path_cb) }, { "CloseWindow", GTK_STOCK_CLOSE, N_("C_lose window"), "W", N_("Close window"), CB(layout_menu_close_cb) }, { "Quit", GTK_STOCK_QUIT, N_("_Quit"), "Q", N_("Quit"), CB(layout_menu_exit_cb) }, { "RotateCW", NULL, N_("_Rotate clockwise"), "bracketright", N_("Rotate clockwise"), CB(layout_menu_alter_90_cb) }, + { "Rating0", NULL, N_("_Rating 0"), "KP_0", N_("Rating 0"), CB(layout_menu_rating_0_cb) }, + { "Rating1", NULL, N_("_Rating 1"), "KP_1", N_("Rating 1"), CB(layout_menu_rating_1_cb) }, + { "Rating2", NULL, N_("_Rating 2"), "KP_2", N_("Rating 2"), CB(layout_menu_rating_2_cb) }, + { "Rating3", NULL, N_("_Rating 3"), "KP_3", N_("Rating 3"), CB(layout_menu_rating_3_cb) }, + { "Rating4", NULL, N_("_Rating 4"), "KP_4", N_("Rating 4"), CB(layout_menu_rating_4_cb) }, + { "Rating5", NULL, N_("_Rating 5"), "KP_5", N_("Rating 5"), CB(layout_menu_rating_5_cb) }, + { "RatingM1", NULL, N_("_Rating -1"), "KP_Subtract", N_("Rating -1"), CB(layout_menu_rating_m1_cb) }, { "RotateCCW", NULL, N_("Rotate _counterclockwise"), "bracketleft", N_("Rotate counterclockwise"), CB(layout_menu_alter_90cc_cb) }, { "Rotate180", NULL, N_("Rotate 1_80"), "R", N_("Rotate 180"), CB(layout_menu_alter_180_cb) }, { "Mirror", NULL, N_("_Mirror"), "M", N_("Mirror"), CB(layout_menu_alter_mirror_cb) }, @@ -1335,10 +1809,18 @@ static GtkActionEntry menu_entries[] = { { "Refresh", GTK_STOCK_REFRESH, N_("_Refresh"), "R", N_("Refresh"), CB(layout_menu_refresh_cb) }, { "HelpContents", GTK_STOCK_HELP, N_("_Contents"), "F1", N_("Contents"), CB(layout_menu_help_cb) }, { "HelpShortcuts", NULL, N_("_Keyboard shortcuts"), NULL, N_("Keyboard shortcuts"), CB(layout_menu_help_keys_cb) }, + { "HelpKbd", NULL, N_("_Keyboard map"), NULL, N_("Keyboard map"), CB(layout_menu_kbd_map_cb) }, { "HelpNotes", NULL, N_("_Release notes"), NULL, N_("Release notes"), CB(layout_menu_notes_cb) }, { "About", GTK_STOCK_ABOUT, N_("_About"), NULL, N_("About"), CB(layout_menu_about_cb) }, { "LogWindow", NULL, N_("_Log Window"), NULL, N_("Log Window"), CB(layout_menu_log_window_cb) }, { "ExifWin", NULL, N_("_Exif window"), "E", N_("Exif window"), CB(layout_menu_bar_exif_cb) }, + { "StereoCycle", NULL, N_("_Cycle through stereo modes"), NULL, N_("Cycle through stereo modes"), CB(layout_menu_stereo_mode_next_cb) }, + { "SplitNextPane", NULL, N_("_Next Pane"), "Right", N_("Next Pane"), CB(layout_menu_split_pane_next_cb) }, + { "SplitPreviousPane", NULL, N_("_Previous Pane"), "Left", N_("Previous Pane"), CB(layout_menu_split_pane_prev_cb) }, + { "SplitUpPane", NULL, N_("_Up Pane"), "Up", N_("Up Pane"), CB(layout_menu_split_pane_updown_cb) }, + { "SplitDownPane", NULL, N_("_Down Pane"), "Down", N_("Down Pane"), CB(layout_menu_split_pane_updown_cb) }, + { "WriteRotation", NULL, N_("_Write orientation to file"), NULL, N_("Write orientation to file"), CB(layout_menu_write_rotate_cb) }, + { "WriteRotationKeepDate", NULL, N_("_Write orientation to file (preserve timestamp)"), NULL, N_("Write orientation to file (preserve timestamp)"), CB(layout_menu_write_rotate_keep_date_cb) }, }; @@ -1350,12 +1832,16 @@ static GtkToggleActionEntry menu_toggle_entries[] = { { "HideToolbar", NULL, N_("Hide tool_bar"), NULL, N_("Hide toolbar"), CB(layout_menu_toolbar_cb), FALSE }, { "SBar", NULL, N_("_Info sidebar"), "K", N_("Info sidebar"), CB(layout_menu_bar_cb), FALSE }, { "SBarSort", NULL, N_("Sort _manager"), "S", N_("Sort manager"), CB(layout_menu_bar_sort_cb), FALSE }, + { "HideBars", NULL, N_("Hide Bars"), "grave", N_("Hide Bars"), CB(layout_menu_hide_bars_cb), FALSE }, { "SlideShow", GTK_STOCK_MEDIA_PLAY, N_("Toggle _slideshow"), "S", N_("Toggle slideshow"), CB(layout_menu_slideshow_cb), FALSE }, { "UseColorProfiles", GTK_STOCK_SELECT_COLOR, N_("Use _color profiles"), NULL, N_("Use color profiles"), CB(layout_color_menu_enable_cb), FALSE}, { "UseImageProfile", NULL, N_("Use profile from _image"), NULL, N_("Use profile from image"), CB(layout_color_menu_use_image_cb), FALSE}, { "Grayscale", NULL, N_("Toggle _grayscale"), "G", N_("Toggle grayscale"), CB(layout_menu_alter_desaturate_cb), FALSE}, { "ImageOverlay", NULL, N_("Image _Overlay"), NULL, N_("Image Overlay"), CB(layout_menu_overlay_cb), FALSE }, { "ImageHistogram", NULL, N_("_Show Histogram"), NULL, N_("Show Histogram"), CB(layout_menu_histogram_cb), FALSE }, + { "RectangularSelection", NULL, N_("Rectangular Selection"), "R", N_("Rectangular Selection"), CB(layout_menu_rectangular_selection_cb), FALSE }, + { "Animate", NULL, N_("GIF _animation"), "A", N_("Toggle GIF animation"), CB(layout_menu_animate_cb), FALSE }, + { "ExifRotate", GTK_STOCK_ORIENTATION_PORTRAIT, N_("_Exif rotate"), "X", N_("Exif rotate"), CB(layout_menu_exif_rotate_cb), FALSE }, }; static GtkRadioActionEntry menu_radio_entries[] = { @@ -1363,9 +1849,8 @@ static GtkRadioActionEntry menu_radio_entries[] = { { "ViewIcons", NULL, N_("I_cons"), "I", N_("View Images as Icons"), FILEVIEW_ICON } }; -static GtkRadioActionEntry menu_view_dir_radio_entries[] = { - { "FolderList", NULL, N_("Folder Li_st"), "L", N_("View Folders as List"), DIRVIEW_LIST }, - { "FolderTree", NULL, N_("Folder T_ree"), "T", N_("View Folders as Tree"), DIRVIEW_TREE }, +static GtkToggleActionEntry menu_view_dir_toggle_entries[] = { + { "FolderTree", NULL, N_("T_oggle Folder View"), "T", N_("Toggle Folders View"), CB(layout_menu_view_dir_as_cb),FALSE }, }; static GtkRadioActionEntry menu_split_radio_entries[] = { @@ -1397,6 +1882,13 @@ static GtkRadioActionEntry menu_histogram_mode[] = { { "HistogramModeLog", NULL, N_("_Log Histogram"), NULL, N_("Log Histogram"), 1 }, }; +static GtkRadioActionEntry menu_stereo_mode_entries[] = { + { "StereoAuto", NULL, N_("_Auto"), NULL, N_("Stereo Auto"), STEREO_PIXBUF_DEFAULT }, + { "StereoSBS", NULL, N_("_Side by Side"), NULL, N_("Stereo Side by Side"), STEREO_PIXBUF_SBS }, + { "StereoCross", NULL, N_("_Cross"), NULL, N_("Stereo Cross"), STEREO_PIXBUF_CROSS }, + { "StereoOff", NULL, N_("_Off"), NULL, N_("Stereo Off"), STEREO_PIXBUF_NONE } +}; + #undef CB @@ -1436,6 +1928,7 @@ static const gchar *menu_ui_description = " " " " " " +" " " " " " " " @@ -1443,6 +1936,7 @@ static const gchar *menu_ui_description = " " " " " " +" " " " " " " " @@ -1464,6 +1958,22 @@ static const gchar *menu_ui_description = " " " " " " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " " " " " " " @@ -1476,7 +1986,9 @@ static const gchar *menu_ui_description = " " " " " " +#if !GTK_CHECK_VERSION(3,0,0) " " +#endif " " " " " " @@ -1486,7 +1998,6 @@ static const gchar *menu_ui_description = " " " " " " -" " " " " " " " @@ -1534,6 +2045,19 @@ static const gchar *menu_ui_description = " " " " " " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " " " " " " " @@ -1568,9 +2092,11 @@ static const gchar *menu_ui_description = " " " " " " +" " " " " " " " +" " " " " " " " @@ -1581,6 +2107,7 @@ static const gchar *menu_ui_description = " " " " " " +" " " " " " " " @@ -1591,8 +2118,23 @@ static const gchar *menu_ui_description = " " " " " " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " " " " " +" " +" " +" " +" " " " "" "" @@ -1633,7 +2175,7 @@ static void layout_actions_setup_mark(LayoutWindow *lw, gint mark, gchar *name_t g_snprintf(name, sizeof(name), name_tmpl, mark); g_snprintf(label, sizeof(label), label_tmpl, mark); - + if (accel_tmpl) g_snprintf(accel, sizeof(accel), accel_tmpl, mark % 10); else @@ -1643,7 +2185,7 @@ static void layout_actions_setup_mark(LayoutWindow *lw, gint mark, gchar *name_t g_snprintf(tooltip, sizeof(tooltip), tooltip_tmpl, mark); else entry.tooltip = NULL; - + gtk_action_group_add_actions(lw->action_group, &entry, 1, lw); action = gtk_action_group_get_action(lw->action_group, name); g_object_set_data(G_OBJECT(action), "mark_num", GINT_TO_POINTER(mark)); @@ -1660,17 +2202,17 @@ static void layout_actions_setup_marks(LayoutWindow *lw) for (mark = 1; mark <= FILEDATA_MARKS_SIZE; mark++) { - layout_actions_setup_mark(lw, mark, "Mark%d", _("Mark _%d"), NULL, NULL, NULL); - layout_actions_setup_mark(lw, mark, "SetMark%d", _("_Set mark %d"), NULL, _("Set mark %d"), G_CALLBACK(layout_menu_set_mark_sel_cb)); - layout_actions_setup_mark(lw, mark, "ResetMark%d", _("_Reset mark %d"), NULL, _("Reset mark %d"), G_CALLBACK(layout_menu_res_mark_sel_cb)); - layout_actions_setup_mark(lw, mark, "ToggleMark%d", _("_Toggle mark %d"), "%d", _("Toggle mark %d"), G_CALLBACK(layout_menu_toggle_mark_sel_cb)); - layout_actions_setup_mark(lw, mark, "ToggleMark%dAlt1", _("_Toggle mark %d"), "KP_%d", _("Toggle mark %d"), G_CALLBACK(layout_menu_toggle_mark_sel_cb)); - layout_actions_setup_mark(lw, mark, "SelectMark%d", _("Se_lect mark %d"), "%d", _("Select mark %d"), G_CALLBACK(layout_menu_sel_mark_cb)); - layout_actions_setup_mark(lw, mark, "SelectMark%dAlt1", _("_Select mark %d"), "KP_%d", _("Select mark %d"), G_CALLBACK(layout_menu_sel_mark_cb)); - layout_actions_setup_mark(lw, mark, "AddMark%d", _("_Add mark %d"), NULL, _("Add mark %d"), G_CALLBACK(layout_menu_sel_mark_or_cb)); - layout_actions_setup_mark(lw, mark, "IntMark%d", _("_Intersection with mark %d"), NULL, _("Intersection with mark %d"), G_CALLBACK(layout_menu_sel_mark_and_cb)); - layout_actions_setup_mark(lw, mark, "UnselMark%d", _("_Unselect mark %d"), NULL, _("Unselect mark %d"), G_CALLBACK(layout_menu_sel_mark_minus_cb)); - layout_actions_setup_mark(lw, mark, "FilterMark%d", _("_Filter mark %d"), NULL, _("Filter mark %d"), G_CALLBACK(layout_menu_mark_filter_toggle_cb)); + layout_actions_setup_mark(lw, mark, "Mark%d", _("Mark _%d"), NULL, NULL, NULL); + layout_actions_setup_mark(lw, mark, "SetMark%d", _("_Set mark %d"), NULL, _("Set mark %d"), G_CALLBACK(layout_menu_set_mark_sel_cb)); + layout_actions_setup_mark(lw, mark, "ResetMark%d", _("_Reset mark %d"), NULL, _("Reset mark %d"), G_CALLBACK(layout_menu_res_mark_sel_cb)); + layout_actions_setup_mark(lw, mark, "ToggleMark%d", _("_Toggle mark %d"), "%d", _("Toggle mark %d"), G_CALLBACK(layout_menu_toggle_mark_sel_cb)); + layout_actions_setup_mark(lw, mark, "ToggleMark%dAlt1", _("_Toggle mark %d"), "KP_%d", _("Toggle mark %d"), G_CALLBACK(layout_menu_toggle_mark_sel_cb)); + layout_actions_setup_mark(lw, mark, "SelectMark%d", _("Se_lect mark %d"), "%d", _("Select mark %d"), G_CALLBACK(layout_menu_sel_mark_cb)); + layout_actions_setup_mark(lw, mark, "SelectMark%dAlt1", _("_Select mark %d"), "KP_%d", _("Select mark %d"), G_CALLBACK(layout_menu_sel_mark_cb)); + layout_actions_setup_mark(lw, mark, "AddMark%d", _("_Add mark %d"), NULL, _("Add mark %d"), G_CALLBACK(layout_menu_sel_mark_or_cb)); + layout_actions_setup_mark(lw, mark, "IntMark%d", _("_Intersection with mark %d"), NULL, _("Intersection with mark %d"), G_CALLBACK(layout_menu_sel_mark_and_cb)); + layout_actions_setup_mark(lw, mark, "UnselMark%d", _("_Unselect mark %d"), NULL, _("Unselect mark %d"), G_CALLBACK(layout_menu_sel_mark_minus_cb)); + layout_actions_setup_mark(lw, mark, "FilterMark%d", _("_Filter mark %d"), NULL, _("Filter mark %d"), G_CALLBACK(layout_menu_mark_filter_toggle_cb)); g_string_append_printf(desc, " " @@ -1715,23 +2257,23 @@ static GList *layout_actions_editor_menu_path(EditorDescription *editor) gchar **split = g_strsplit(editor->menu_path, "/", 0); gint i = 0; GList *ret = NULL; - - if (split[0] == NULL) + + if (split[0] == NULL) { g_strfreev(split); return NULL; } - + while (split[i]) { ret = g_list_prepend(ret, g_strdup(split[i])); i++; } - + g_strfreev(split); - + ret = g_list_prepend(ret, g_strdup(editor->key)); - + return g_list_reverse(ret); } @@ -1745,13 +2287,13 @@ static void layout_actions_editor_add(GString *desc, GList *path, GList *old_pat } to_open = g_list_length(path) - 1; to_close = g_list_length(old_path) - 1; - + if (to_close > 0) { old_path = g_list_last(old_path); old_path = old_path->prev; } - + for (i = 0; i < to_close; i++) { gchar *name = old_path->data; @@ -1787,7 +2329,7 @@ static void layout_actions_editor_add(GString *desc, GList *path, GList *old_pat } path = path->next; } - + if (path) g_string_append_printf(desc, " ", (gchar *)path->data); } @@ -1799,7 +2341,17 @@ static void layout_actions_setup_editors(LayoutWindow *lw) GList *work; GList *old_path; GString *desc; - + + if (lw->ui_editors_id) + { + gtk_ui_manager_remove_ui(lw->ui_manager, lw->ui_editors_id); + } + + if (lw->action_group_editors) + { + gtk_ui_manager_remove_action_group(lw->ui_manager, lw->action_group_editors); + g_object_unref(lw->action_group_editors); + } lw->action_group_editors = gtk_action_group_new("MenuActionsExternal"); gtk_ui_manager_insert_action_group(lw->ui_manager, lw->action_group_editors, 1); @@ -1809,24 +2361,29 @@ static void layout_actions_setup_editors(LayoutWindow *lw) " "); editors_list = editor_list_get(); - + old_path = NULL; work = editors_list; while (work) { GList *path; EditorDescription *editor = work->data; - GtkActionEntry entry = { editor->key, NULL, editor->name, editor->hotkey, editor->comment, G_CALLBACK(layout_menu_edit_cb) }; - - if (editor->icon && register_theme_icon_as_stock(editor->key, editor->icon)) + GtkActionEntry entry = { editor->key, + NULL, + editor->name, + editor->hotkey, + editor->comment ? editor->comment : editor->name, + G_CALLBACK(layout_menu_edit_cb) }; + + if (editor->icon) { entry.stock_id = editor->key; } gtk_action_group_add_actions(lw->action_group_editors, &entry, 1, lw); - + path = layout_actions_editor_menu_path(editor); layout_actions_editor_add(desc, path, old_path); - + string_list_free(old_path); old_path = path; work = work->next; @@ -1839,7 +2396,7 @@ static void layout_actions_setup_editors(LayoutWindow *lw) "" ); error = NULL; - + lw->ui_editors_id = gtk_ui_manager_add_ui_from_string(lw->ui_manager, desc->str, -1, &error); if (!lw->ui_editors_id) { @@ -1856,6 +2413,7 @@ void layout_actions_setup(LayoutWindow *lw) GError *error; gint i; + DEBUG_1("%s layout_actions_setup: start", get_exec_time()); if (lw->ui_manager) return; lw->action_group = gtk_action_group_new("MenuActions"); @@ -1871,9 +2429,9 @@ void layout_actions_setup(LayoutWindow *lw) gtk_action_group_add_radio_actions(lw->action_group, menu_split_radio_entries, G_N_ELEMENTS(menu_split_radio_entries), 0, G_CALLBACK(layout_menu_split_cb), lw); - gtk_action_group_add_radio_actions(lw->action_group, - menu_view_dir_radio_entries, VIEW_DIR_TYPES_COUNT, - 0, G_CALLBACK(layout_menu_view_dir_as_cb), lw); + gtk_action_group_add_toggle_actions(lw->action_group, + menu_view_dir_toggle_entries, G_N_ELEMENTS(menu_view_dir_toggle_entries), + lw); gtk_action_group_add_radio_actions(lw->action_group, menu_color_radio_entries, COLOR_PROFILE_FILE + COLOR_PROFILE_INPUTS, 0, G_CALLBACK(layout_color_menu_input_cb), lw); @@ -1883,12 +2441,16 @@ void layout_actions_setup(LayoutWindow *lw) gtk_action_group_add_radio_actions(lw->action_group, menu_histogram_mode, G_N_ELEMENTS(menu_histogram_mode), 0, G_CALLBACK(layout_menu_histogram_mode_cb), lw); + gtk_action_group_add_radio_actions(lw->action_group, + menu_stereo_mode_entries, G_N_ELEMENTS(menu_stereo_mode_entries), + 0, G_CALLBACK(layout_menu_stereo_mode_cb), lw); lw->ui_manager = gtk_ui_manager_new(); gtk_ui_manager_set_add_tearoffs(lw->ui_manager, TRUE); gtk_ui_manager_insert_action_group(lw->ui_manager, lw->action_group, 0); + DEBUG_1("%s layout_actions_setup: add menu", get_exec_time()); error = NULL; if (!gtk_ui_manager_add_ui_from_string(lw->ui_manager, menu_ui_description, -1, &error)) { @@ -1896,44 +2458,84 @@ void layout_actions_setup(LayoutWindow *lw) g_error_free(error); exit(EXIT_FAILURE); } - - for (i = 0; i < TOOLBAR_COUNT; i++) - { - layout_toolbar_clear(lw, i); - layout_toolbar_add_default(lw, i); - } - + + DEBUG_1("%s layout_actions_setup: marks", get_exec_time()); layout_actions_setup_marks(lw); + + DEBUG_1("%s layout_actions_setup: editors", get_exec_time()); layout_actions_setup_editors(lw); + DEBUG_1("%s layout_actions_setup: status_update_write", get_exec_time()); layout_util_status_update_write(lw); - + + DEBUG_1("%s layout_actions_setup: actions_add_window", get_exec_time()); layout_actions_add_window(lw, lw->window); + DEBUG_1("%s layout_actions_setup: end", get_exec_time()); } -void layout_editors_reload_all(void) +static gint layout_editors_reload_idle_id = -1; +static GList *layout_editors_desktop_files = NULL; + +static gboolean layout_editors_reload_idle_cb(gpointer data) { - GList *work; + if (!layout_editors_desktop_files) + { + DEBUG_1("%s layout_editors_reload_idle_cb: get_desktop_files", get_exec_time()); + layout_editors_desktop_files = editor_get_desktop_files(); + return TRUE; + } - work = layout_window_list; - while (work) + editor_read_desktop_file(layout_editors_desktop_files->data); + g_free(layout_editors_desktop_files->data); + layout_editors_desktop_files = g_list_delete_link(layout_editors_desktop_files, layout_editors_desktop_files); + + + if (!layout_editors_desktop_files) { - LayoutWindow *lw = work->data; - work = work->next; + GList *work; + DEBUG_1("%s layout_editors_reload_idle_cb: setup_editors", get_exec_time()); + editor_table_finish(); - gtk_ui_manager_remove_ui(lw->ui_manager, lw->ui_editors_id); - gtk_ui_manager_remove_action_group(lw->ui_manager, lw->action_group_editors); - g_object_unref(lw->action_group_editors); + work = layout_window_list; + while (work) + { + LayoutWindow *lw = work->data; + work = work->next; + layout_actions_setup_editors(lw); + } + + DEBUG_1("%s layout_editors_reload_idle_cb: setup_editors done", get_exec_time()); + + layout_editors_reload_idle_id = -1; + return FALSE; } - - editor_load_descriptions(); - - work = layout_window_list; - while (work) + return TRUE; +} + +void layout_editors_reload_start(void) +{ + DEBUG_1("%s layout_editors_reload_start", get_exec_time()); + + if (layout_editors_reload_idle_id != -1) { - LayoutWindow *lw = work->data; - work = work->next; - layout_actions_setup_editors(lw); + g_source_remove(layout_editors_reload_idle_id); + string_list_free(layout_editors_desktop_files); + } + + editor_table_clear(); + layout_editors_reload_idle_id = g_idle_add(layout_editors_reload_idle_cb, NULL); +} + +void layout_editors_reload_finish(void) +{ + if (layout_editors_reload_idle_id != -1) + { + DEBUG_1("%s layout_editors_reload_finish", get_exec_time()); + g_source_remove(layout_editors_reload_idle_id); + while (layout_editors_reload_idle_id != -1) + { + layout_editors_reload_idle_cb(NULL); + } } } @@ -1978,120 +2580,6 @@ GtkWidget *layout_actions_toolbar(LayoutWindow *lw, ToolbarType type) return lw->toolbar[type]; } -void layout_toolbar_clear(LayoutWindow *lw, ToolbarType type) -{ - if (lw->toolbar_merge_id[type]) - { - gtk_ui_manager_remove_ui(lw->ui_manager, lw->toolbar_merge_id[type]); - gtk_ui_manager_ensure_update(lw->ui_manager); - } - string_list_free(lw->toolbar_actions[type]); - lw->toolbar_actions[type] = NULL; - - lw->toolbar_merge_id[type] = gtk_ui_manager_new_merge_id(lw->ui_manager); -} - - -void layout_toolbar_add(LayoutWindow *lw, ToolbarType type, const gchar *action) -{ - const gchar *path = NULL; - if (!action || !lw->ui_manager) return; - - if (g_list_find_custom(lw->toolbar_actions[type], action, (GCompareFunc)strcmp)) return; - - switch (type) - { - case TOOLBAR_MAIN: - path = "/ToolBar"; - break; - case TOOLBAR_STATUS: - path = "/StatusBar"; - break; - default: - break; - } - - gtk_ui_manager_add_ui(lw->ui_manager, lw->toolbar_merge_id[type], path, action, action, GTK_UI_MANAGER_TOOLITEM, FALSE); - lw->toolbar_actions[type] = g_list_append(lw->toolbar_actions[type], g_strdup(action)); -} - - -void layout_toolbar_add_default(LayoutWindow *lw, ToolbarType type) -{ - switch (type) - { - case TOOLBAR_MAIN: - layout_toolbar_add(lw, type, "Thumbnails"); - layout_toolbar_add(lw, type, "Back"); - layout_toolbar_add(lw, type, "Home"); - layout_toolbar_add(lw, type, "Refresh"); - layout_toolbar_add(lw, type, "ZoomIn"); - layout_toolbar_add(lw, type, "ZoomOut"); - layout_toolbar_add(lw, type, "ZoomFit"); - layout_toolbar_add(lw, type, "Zoom100"); - layout_toolbar_add(lw, type, "Preferences"); - layout_toolbar_add(lw, type, "FloatTools"); - break; - case TOOLBAR_STATUS: - layout_toolbar_add(lw, type, "ShowInfoPixel"); - layout_toolbar_add(lw, type, "UseColorProfiles"); - layout_toolbar_add(lw, type, "SaveMetadata"); - break; - default: - break; - } -} - -void layout_toolbar_write_config(LayoutWindow *lw, ToolbarType type, GString *outstr, gint indent) -{ - const gchar *name = NULL; - GList *work = lw->toolbar_actions[type]; - - switch (type) - { - case TOOLBAR_MAIN: - name = "toolbar"; - break; - case TOOLBAR_STATUS: - name = "statusbar"; - break; - default: - break; - } - - WRITE_NL(); WRITE_STRING("<%s>", name); - indent++; - WRITE_NL(); WRITE_STRING(""); - while (work) - { - gchar *action = work->data; - work = work->next; - WRITE_NL(); WRITE_STRING(""); - } - indent--; - WRITE_NL(); WRITE_STRING("", name); -} - -void layout_toolbar_add_from_config(LayoutWindow *lw, ToolbarType type, const gchar **attribute_names, const gchar **attribute_values) -{ - gchar *action = NULL; - - while (*attribute_names) - { - const gchar *option = *attribute_names++; - const gchar *value = *attribute_values++; - - if (READ_CHAR_FULL("action", action)) continue; - - log_printf("unknown attribute %s = %s\n", option, value); - } - - layout_toolbar_add(lw, type, action); - g_free(action); -} - /* *----------------------------------------------------------------------------- * misc @@ -2150,7 +2638,7 @@ void layout_util_sync_color(LayoutWindow *lw) if (!lw->action_group) return; if (!layout_image_color_profile_get(lw, &input, &use_image)) return; - + use_color = layout_image_color_profile_get_use(lw); action = gtk_action_group_get_action(lw->action_group, "UseColorProfiles"); @@ -2183,7 +2671,7 @@ void layout_util_sync_color(LayoutWindow *lw) { sprintf(action_name, "ColorProfile%d", i); action = gtk_action_group_get_action(lw->action_group, action_name); - + if (i >= COLOR_PROFILE_FILE) { const gchar *name = options->color_profile.input_name[i - COLOR_PROFILE_FILE]; @@ -2219,13 +2707,22 @@ static void layout_util_sync_views(LayoutWindow *lw) if (!lw->action_group) return; action = gtk_action_group_get_action(lw->action_group, "FolderTree"); - radio_action_set_current_value(GTK_RADIO_ACTION(action), lw->options.dir_view_type); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.dir_view_type); action = gtk_action_group_get_action(lw->action_group, "SplitSingle"); - radio_action_set_current_value(GTK_RADIO_ACTION(action), lw->split_mode); + gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), lw->split_mode); + + action = gtk_action_group_get_action(lw->action_group, "SplitNextPane"); + gtk_action_set_sensitive(action, !(lw->split_mode == SPLIT_NONE)); + action = gtk_action_group_get_action(lw->action_group, "SplitPreviousPane"); + gtk_action_set_sensitive(action, !(lw->split_mode == SPLIT_NONE)); + action = gtk_action_group_get_action(lw->action_group, "SplitUpPane"); + gtk_action_set_sensitive(action, !(lw->split_mode == SPLIT_NONE)); + action = gtk_action_group_get_action(lw->action_group, "SplitDownPane"); + gtk_action_set_sensitive(action, !(lw->split_mode == SPLIT_NONE)); action = gtk_action_group_get_action(lw->action_group, "ViewIcons"); - radio_action_set_current_value(GTK_RADIO_ACTION(action), lw->options.file_view_type); + gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), lw->options.file_view_type); action = gtk_action_group_get_action(lw->action_group, "FloatTools"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.tools_float); @@ -2238,7 +2735,7 @@ static void layout_util_sync_views(LayoutWindow *lw) action = gtk_action_group_get_action(lw->action_group, "HideToolbar"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.toolbar_hidden); - + action = gtk_action_group_get_action(lw->action_group, "ShowInfoPixel"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.show_info_pixel); @@ -2248,24 +2745,43 @@ static void layout_util_sync_views(LayoutWindow *lw) action = gtk_action_group_get_action(lw->action_group, "SlideShow"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), layout_image_slideshow_active(lw)); + action = gtk_action_group_get_action(lw->action_group, "Animate"); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.animate); + action = gtk_action_group_get_action(lw->action_group, "ImageOverlay"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), osd_flags != OSD_SHOW_NOTHING); action = gtk_action_group_get_action(lw->action_group, "ImageHistogram"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), osd_flags & OSD_SHOW_HISTOGRAM); + action = gtk_action_group_get_action(lw->action_group, "ExifRotate"); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), options->image.exif_rotate_enable); + + action = gtk_action_group_get_action(lw->action_group, "RectangularSelection"); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), options->collections.rectangular_selection); + if (osd_flags & OSD_SHOW_HISTOGRAM) { action = gtk_action_group_get_action(lw->action_group, "HistogramChanR"); - radio_action_set_current_value(GTK_RADIO_ACTION(action), image_osd_histogram_get_channel(lw->image)); + gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), image_osd_histogram_get_channel(lw->image)); action = gtk_action_group_get_action(lw->action_group, "HistogramModeLin"); - radio_action_set_current_value(GTK_RADIO_ACTION(action), image_osd_histogram_get_mode(lw->image)); + gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), image_osd_histogram_get_mode(lw->image)); } action = gtk_action_group_get_action(lw->action_group, "ConnectZoomMenu"); gtk_action_set_sensitive(action, lw->split_mode != SPLIT_NONE); + action = gtk_action_group_get_action(lw->action_group, "WriteRotation"); + gtk_action_set_sensitive(action, !(runcmd("which exiftran >/dev/null") || + runcmd("which mogrify >/dev/null") || options->metadata.write_orientation)); + action = gtk_action_group_get_action(lw->action_group, "WriteRotationKeepDate"); + gtk_action_set_sensitive(action, !(runcmd("which exiftran >/dev/null") || + runcmd("which mogrify >/dev/null") || options->metadata.write_orientation)); + + action = gtk_action_group_get_action(lw->action_group, "StereoAuto"); + gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), layout_image_stereo_pixbuf_get(lw)); + layout_util_sync_color(lw); } @@ -2297,7 +2813,7 @@ void layout_util_sync(LayoutWindow *lw) static gboolean layout_bar_enabled(LayoutWindow *lw) { - return lw->bar && GTK_WIDGET_VISIBLE(lw->bar); + return lw->bar && gtk_widget_get_visible(lw->bar); } static void layout_bar_destroyed(GtkWidget *widget, gpointer data) @@ -2305,7 +2821,7 @@ static void layout_bar_destroyed(GtkWidget *widget, gpointer data) LayoutWindow *lw = data; lw->bar = NULL; -/* +/* do not call layout_util_sync_views(lw) here this is called either when whole layout is destroyed - no need for update or when the bar is replaced - sync is called by upper function at the end of whole operation @@ -2316,13 +2832,13 @@ static void layout_bar_destroyed(GtkWidget *widget, gpointer data) static void layout_bar_set_default(LayoutWindow *lw) { GtkWidget *bar; - + if (!lw->utility_box) return; bar = bar_new(lw); - + layout_bar_set(lw, bar); - + bar_populate_default(bar); } @@ -2350,7 +2866,7 @@ void layout_bar_set(LayoutWindow *lw, GtkWidget *bar) // gtk_box_pack_start(GTK_BOX(lw->utility_box), lw->bar, FALSE, FALSE, 0); - gtk_paned_pack2(GTK_PANED(lw->utility_paned), lw->bar, FALSE, TRUE); + gtk_paned_pack2(GTK_PANED(lw->utility_paned), lw->bar, FALSE, TRUE); bar_set_fd(lw->bar, layout_image_get_fd(lw)); } @@ -2390,7 +2906,7 @@ static void layout_bar_new_selection(LayoutWindow *lw, gint count) static gboolean layout_bar_sort_enabled(LayoutWindow *lw) { - return lw->bar_sort && GTK_WIDGET_VISIBLE(lw->bar_sort); + return lw->bar_sort && gtk_widget_get_visible(lw->bar_sort); } @@ -2400,7 +2916,7 @@ static void layout_bar_sort_destroyed(GtkWidget *widget, gpointer data) lw->bar_sort = NULL; -/* +/* do not call layout_util_sync_views(lw) here this is called either when whole layout is destroyed - no need for update or when the bar is replaced - sync is called by upper function at the end of whole operation @@ -2411,11 +2927,11 @@ static void layout_bar_sort_destroyed(GtkWidget *widget, gpointer data) static void layout_bar_sort_set_default(LayoutWindow *lw) { GtkWidget *bar; - + if (!lw->utility_box) return; bar = bar_sort_new_default(lw); - + layout_bar_sort_set(lw, bar); } @@ -2460,6 +2976,39 @@ void layout_bar_sort_toggle(LayoutWindow *lw) layout_util_sync_views(lw); } +static void layout_bars_hide_toggle(LayoutWindow *lw) +{ + if (lw->options.bars_state.hidden) + { + lw->options.bars_state.hidden = FALSE; + if (lw->options.bars_state.sort) + { + gtk_widget_show(lw->bar_sort); + } + if (lw->options.bars_state.info) + { + gtk_widget_show(lw->bar); + } + layout_tools_float_set(lw, lw->options.tools_float, + lw->options.bars_state.tools_hidden); + } + else + { + lw->options.bars_state.hidden = TRUE; + lw->options.bars_state.sort = layout_bar_sort_enabled(lw); + lw->options.bars_state.info = layout_bar_enabled(lw); + lw->options.bars_state.tools_float = lw->options.tools_float; + lw->options.bars_state.tools_hidden = lw->options.tools_hidden; + + gtk_widget_hide(lw->bar); + if (lw->bar_sort) + gtk_widget_hide(lw->bar_sort); + layout_tools_float_set(lw, lw->options.tools_float, TRUE); + } + + layout_util_sync_views(lw); +} + void layout_bars_new_image(LayoutWindow *lw) { layout_bar_new_image(lw); @@ -2483,9 +3032,9 @@ GtkWidget *layout_bars_prepare(LayoutWindow *lw, GtkWidget *image) lw->utility_paned = gtk_hpaned_new(); gtk_box_pack_start(GTK_BOX(lw->utility_box), lw->utility_paned, TRUE, TRUE, 0); - gtk_paned_pack1(GTK_PANED(lw->utility_paned), image, TRUE, FALSE); + gtk_paned_pack1(GTK_PANED(lw->utility_paned), image, TRUE, FALSE); gtk_widget_show(lw->utility_paned); - + gtk_widget_show(image); g_object_ref(lw->utility_box); @@ -2506,8 +3055,8 @@ static void layout_exif_window_destroy(GtkWidget *widget, gpointer data) void layout_exif_window_new(LayoutWindow *lw) { - if (lw->exif_window) return; - + if (lw->exif_window) return; + lw->exif_window = advanced_exif_new(); if (!lw->exif_window) return; g_signal_connect(G_OBJECT(lw->exif_window), "destroy",