Fix #264, 274, 285, 436: Add 'Losslessly rotate image' keyboard shortcuts
[geeqie.git] / src / layout_util.c
index 36e2705..9cc0558 100644 (file)
@@ -51,6 +51,7 @@
 #include "ui_tabcomp.h"
 #include "utilops.h"
 #include "view_dir.h"
+#include "view_file.h"
 #include "window.h"
 #include "metadata.h"
 #include "desktop_file.h"
@@ -59,6 +60,7 @@
 #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);
@@ -352,6 +354,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;
@@ -402,6 +453,101 @@ static void layout_menu_exif_rotate_cb(GtkToggleAction *action, gpointer data)
        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;
@@ -1524,6 +1670,7 @@ static GtkActionEntry menu_entries[] = {
   { "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 },
@@ -1569,6 +1716,13 @@ static GtkActionEntry menu_entries[] = {
   { "CloseWindow",     GTK_STOCK_CLOSE,        N_("C_lose window"),                    "<control>W",           N_("Close window"),                     CB(layout_menu_close_cb) },
   { "Quit",            GTK_STOCK_QUIT,         N_("_Quit"),                            "<control>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"),        "<alt>KP_0",    N_("Rating 0"),                 CB(layout_menu_rating_0_cb) },
+  { "Rating1",         NULL,                   N_("_Rating 1"),        "<alt>KP_1",    N_("Rating 1"),                 CB(layout_menu_rating_1_cb) },
+  { "Rating2",         NULL,                   N_("_Rating 2"),        "<alt>KP_2",    N_("Rating 2"),                 CB(layout_menu_rating_2_cb) },
+  { "Rating3",         NULL,                   N_("_Rating 3"),        "<alt>KP_3",    N_("Rating 3"),                 CB(layout_menu_rating_3_cb) },
+  { "Rating4",         NULL,                   N_("_Rating 4"),        "<alt>KP_4",    N_("Rating 4"),                 CB(layout_menu_rating_4_cb) },
+  { "Rating5",         NULL,                   N_("_Rating 5"),        "<alt>KP_5",    N_("Rating 5"),                 CB(layout_menu_rating_5_cb) },
+  { "RatingM1",                NULL,                   N_("_Rating -1"),       "<alt>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"),                      "<shift>R",             N_("Rotate 180"),                       CB(layout_menu_alter_180_cb) },
   { "Mirror",          NULL,                   N_("_Mirror"),                          "<shift>M",             N_("Mirror"),                           CB(layout_menu_alter_mirror_cb) },
@@ -1637,6 +1791,8 @@ static GtkActionEntry menu_entries[] = {
   { "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"),       "<alt>Right",                   N_("Next Pane"),        CB(layout_menu_split_pane_next_cb) },
   { "SplitPreviousPane",       NULL,                   N_("_Previous Pane"),   "<alt>Left",                    N_("Previous Pane"),    CB(layout_menu_split_pane_prev_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) },
 
 };
 
@@ -1776,6 +1932,19 @@ static const gchar *menu_ui_description =
 "        <separator/>"
 "        <menuitem action='ExifRotate'/>"
 "        <separator/>"
+"        <menuitem action='WriteRotation'/>"
+"        <menuitem action='WriteRotationKeepDate'/>"
+"        <separator/>"
+"      </menu>"
+"      <menu action='RatingMenu'>"
+"        <menuitem action='Rating0'/>"
+"        <menuitem action='Rating1'/>"
+"        <menuitem action='Rating2'/>"
+"        <menuitem action='Rating3'/>"
+"        <menuitem action='Rating4'/>"
+"        <menuitem action='Rating5'/>"
+"        <menuitem action='RatingM1'/>"
+"        <separator/>"
 "      </menu>"
 "      <menuitem action='SaveMetadata'/>"
 "      <placeholder name='PropertiesSection'/>"
@@ -1788,7 +1957,9 @@ static const gchar *menu_ui_description =
 "      </menu>"
 "      <placeholder name='PreferencesSection'/>"
 "      <separator/>"
+#if !GTK_CHECK_VERSION(3,0,0)
 "      <menuitem action='Wallpaper'/>"
+#endif
 "      <separator/>"
 "    </menu>"
 "    <menu action='ViewMenu'>"
@@ -2565,6 +2736,13 @@ static void layout_util_sync_views(LayoutWindow *lw)
        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 >null") ||
+                                                       runcmd("which mogrify >null") || options->metadata.write_orientation));
+       action = gtk_action_group_get_action(lw->action_group, "WriteRotationKeepDate");
+       gtk_action_set_sensitive(action, !(runcmd("which exiftran >null") ||
+                                                       runcmd("which mogrify >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));