[gegl] ui: add folder view



commit bc290303b7b070785980ccbf0b79b5506366e6e6
Author: Oyvind Kolas <pippin gimp org>
Date:   Sat Aug 1 21:50:13 2015 +0200

    ui: add folder view
    
    Renders freedesktop spec thumbnails, and has next/prev buttons. Permits quicker
    navigation to a specific photo in a folder.

 bin/gegl.c             |    2 +
 bin/mrg-ui.c           |  329 +++++++++++++++++++++++++++++++++++++----------
 operations/core/crop.c |    2 +
 3 files changed, 263 insertions(+), 70 deletions(-)
---
diff --git a/bin/gegl.c b/bin/gegl.c
index d92d946..c86cb4e 100644
--- a/bin/gegl.c
+++ b/bin/gegl.c
@@ -87,6 +87,8 @@ main (gint    argc,
   gchar       *script    = NULL;
   GError      *err       = NULL;
   gchar       *path_root = NULL;
+      mrg_ui_main (argc, argv);
+      return 0;
 
   g_object_set (gegl_config (),
                 "application-license", "GPL3",
diff --git a/bin/mrg-ui.c b/bin/mrg-ui.c
index b4c516f..8e9fa05 100644
--- a/bin/mrg-ui.c
+++ b/bin/mrg-ui.c
@@ -27,7 +27,10 @@
 
 #if HAVE_MRG
 
+#include <ctype.h>
 #include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -118,77 +121,66 @@ static void mrg_gegl_blit (Mrg *mrg,
                           float scale,
                            float preview_multiplier);
 
+gchar *get_thumb_path (const char *path);
+gchar *get_thumb_path (const char *path)
+{
+  gchar *ret;
+  gchar *uri = g_strdup_printf ("file://%s", path);
+  gchar *hex = g_compute_checksum_for_string (G_CHECKSUM_MD5, uri, -1);
+  int i;  
+  for (i = 0; hex[i]; i++)
+    hex[i] = tolower (hex[i]);
+  ret = g_strdup_printf ("%s/.cache/thumbnails/normal/%s.png", g_get_home_dir(), hex);
+  g_free (uri);
+  g_free (hex);
+  return ret;
+}
+
+
 static void load_path (State *o);
 
 static void go_next (State *o);
 static void go_prev (State *o);
+static void go_parent (State *o);
 
-
-static void go_next_cb (MrgEvent *event, void *data1, void *data2);
-static void go_prev_cb (MrgEvent *event, void *data1, void *data2);
-
+static void get_coords (State *o, float screen_x, float screen_y, float *gegl_x, float *gegl_y);
 static void leave_editor (State *o);
-
 static void drag_preview (MrgEvent *e);
 static void load_into_buffer (State *o, const char *path);
-
 static GeglNode *locate_node (State *o, const char *op_name);
-
 static void zoom_to_fit (State *o);
-
 static void zoom_to_fit_buffer (State *o);
 
-static void zoom_fit_cb (MrgEvent *e, void *data1, void *data2);
-static int deferred_zoom_to_fit (Mrg *mrg, void *data);
-
-static void pan_left_cb (MrgEvent *event, void *data1, void *data2);
-
+static void go_next_cb   (MrgEvent *event, void *data1, void *data2);
+static void go_prev_cb   (MrgEvent *event, void *data1, void *data2);
+static void go_parent_cb (MrgEvent *event, void *data1, void *data2);
+static void zoom_fit_cb  (MrgEvent *e, void *data1, void *data2);
+static void pan_left_cb  (MrgEvent *event, void *data1, void *data2);
 static void pan_right_cb (MrgEvent *event, void *data1, void *data2);
-
-static void pan_down_cb (MrgEvent *event, void *data1, void *data2);
-
-static void pan_up_cb (MrgEvent *event, void *data1, void *data2);
-
-static void get_coords (State *o, float screen_x, float screen_y, float *gegl_x, float *gegl_y);
-
+static void pan_down_cb  (MrgEvent *event, void *data1, void *data2);
+static void pan_up_cb    (MrgEvent *event, void *data1, void *data2);
 static void preview_more_cb (MrgEvent *event, void *data1, void *data2);
-
 static void preview_less_cb (MrgEvent *event, void *data1, void *data2);
-
-static void zoom_1_cb (MrgEvent *event, void *data1, void *data2);
-
-static void zoom_in_cb (MrgEvent *event, void *data1, void *data2);
-
-static void zoom_out_cb (MrgEvent *event, void *data1, void *data2);
-
-static void toggle_actions_cb (MrgEvent *event, void *data1, void *data2);
-
-static void toggle_fullscreen_cb (MrgEvent *event, void *data1, void *data2);
-
-
-static void activate_op_cb (MrgEvent *event, void *data1, void *data2);
-
-
-static void disable_filter_cb (MrgEvent *event, void *data1, void *data2);
-
-static void apply_filter_cb (MrgEvent *event, void *data1, void *data2);
-static void discard_cb (MrgEvent *event, void *data1, void *data2);
-static void save_cb (MrgEvent *event, void *data1, void *data2);
-
-
-
-
+static void zoom_1_cb               (MrgEvent *event, void *data1, void *data2);
+static void zoom_in_cb              (MrgEvent *event, void *data1, void *data2);
+static void zoom_out_cb             (MrgEvent *event, void *data1, void *data2);
+static void toggle_actions_cb       (MrgEvent *event, void *data1, void *data2);
+static void toggle_fullscreen_cb    (MrgEvent *event, void *data1, void *data2);
+static void activate_op_cb          (MrgEvent *event, void *data1, void *data2);
+static void disable_filter_cb       (MrgEvent *event, void *data1, void *data2);
+static void apply_filter_cb         (MrgEvent *event, void *data1, void *data2);
+static void discard_cb              (MrgEvent *event, void *data1, void *data2);
+static void save_cb                 (MrgEvent *event, void *data1, void *data2);
 static void toggle_show_controls_cb (MrgEvent *event, void *data1, void *data2);
 
-static void gegl_ui (Mrg *mrg, void *data);
-int mrg_ui_main (int argc, char **argv);
+static void gegl_ui       (Mrg *mrg, void *data);
+int         mrg_ui_main   (int argc, char **argv);
+void        gegl_meta_set (const char *path, const char *meta_data);
+char *      gegl_meta_get (const char *path); 
 
-void gegl_meta_set (const char *path, const char *meta_data);
-char * gegl_meta_get (const char *path); 
+static void on_viewer_motion (MrgEvent *e, void *data1, void *data2);
 
 static State *hack_state = NULL;  // XXX: this shoudl be factored away
-
-static void on_viewer_motion (MrgEvent *e, void *data1, void *data2);
 int mrg_ui_main (int argc, char **argv)
 {
   Mrg *mrg = mrg_new (1024, 768, NULL);
@@ -518,6 +510,7 @@ static void ui_active_op (State *o)
   }
 }
 
+#if DEBUG_OP_LIST
 static void ui_debug_op_chain (State *o)
 {
   Mrg *mrg = o->mrg;
@@ -538,6 +531,7 @@ static void ui_debug_op_chain (State *o)
      iter = gegl_node_get_producer (iter, "input", NULL);
    }
 }
+#endif
 
 static void ui_actions (State *o)
 {
@@ -571,6 +565,147 @@ static void ui_actions (State *o)
   cairo_new_path (cr);
 }
 
+static void dir_pgdn_cb (MrgEvent *event, void *data1, void *data2)
+{
+  State *o = data1;
+  o->u -= mrg_width (o->mrg) * 0.6; 
+  mrg_queue_draw (o->mrg, NULL);
+  mrg_event_stop_propagate (event);
+}
+
+static void dir_pgup_cb (MrgEvent *event, void *data1, void *data2)
+{
+  State *o = data1;
+  o->u += mrg_width (o->mrg) * 0.6; 
+  mrg_queue_draw (o->mrg, NULL);
+  mrg_event_stop_propagate (event);
+}
+
+static void entry_pressed (MrgEvent *event, void *data1, void *data2)
+{
+  State *o = data2;
+  struct dirent *entry = data1;
+
+  if (!strcmp (entry->d_name, ".."))
+  {
+    go_parent (o);
+    mrg_event_stop_propagate (event);
+    return;
+  }
+  switch (entry->d_type)
+  {
+    case DT_DIR:
+    case DT_REG:
+     {
+       char *newpath = malloc (strlen(o->path) + strlen (entry->d_name) + 2);
+#define PATH_SEP "/"
+       if (!strcmp (o->path, PATH_SEP))
+         sprintf (newpath, "%s%s", PATH_SEP, entry->d_name);
+       else
+         sprintf (newpath, "%s%s%s", o->path, PATH_SEP, entry->d_name);
+       free (o->path);
+       o->path = newpath;
+       load_path (o);
+       mrg_queue_draw (event->mrg, NULL);
+     }
+    default:
+      break;
+  }
+}
+
+static void ui_dir_viewer (State *o)
+{
+  Mrg *mrg = o->mrg;
+  cairo_t *cr = mrg_cr (mrg);
+  struct dirent **namelist;
+  int n = scandir (o->path, &namelist, NULL, alphasort);
+  int i;
+  float x = 0;
+  float y = 0;
+  float dim = mrg_height (mrg) * 0.25;
+
+  cairo_rectangle (cr, 0,0, mrg_width(mrg), mrg_height(mrg));
+  //mrg_listen (mrg, MRG_DRAG, on_pan_drag, o, NULL);
+  mrg_listen (mrg, MRG_MOTION, on_viewer_motion, o, NULL);
+  cairo_new_path (cr);
+
+  mrg_set_edge_right (mrg, 4095);
+  cairo_save (cr);
+  cairo_translate (cr, o->u, 0);//o->v);
+
+  for (i = 0; i < n; i++)
+  {
+    if (namelist[i]->d_name[0] != '.')
+    {
+      int w, h;
+      gchar *path = g_strdup_printf ("%s/%s", o->path, namelist[i]->d_name);
+      gchar *thumbpath = get_thumb_path (path);
+  
+      if (
+         access (thumbpath, F_OK) != -1 && //XXX: query image should suffice
+         mrg_query_image (mrg, thumbpath, &w, &h))
+      {
+        float wdim = dim;
+        float hdim = dim;
+        if (w > h)
+          hdim = dim / (1.0 * w / h);
+        else
+          wdim = dim * (1.0 * w / h);
+
+        mrg_image (mrg, x + (dim-wdim)/2, y + (dim-hdim)/2, wdim, hdim, thumbpath);
+      }
+      g_free (path);
+      g_free (thumbpath);
+
+      mrg_set_xy (mrg, x, y + dim - mrg_em(mrg));
+      mrg_printf (mrg, "%s\n", namelist[i]->d_name);
+      cairo_new_path (mrg_cr(mrg));
+      cairo_rectangle (mrg_cr(mrg), x, y, dim, dim);
+      mrg_listen_full (mrg, MRG_CLICK, entry_pressed, namelist[i], o, (void*)free, NULL);
+      cairo_new_path (mrg_cr(mrg));
+
+      y += dim;
+      if (y+dim > mrg_height (mrg))
+      {
+        y = 0;
+        x += dim;
+      }
+    } 
+  }
+  cairo_restore (cr);
+
+  cairo_scale (cr, mrg_width(mrg), mrg_height(mrg));
+  cairo_new_path (cr);
+  cairo_move_to (cr, 0.2, 0.8);
+  cairo_line_to (cr, 0.2, 1.0);
+  cairo_line_to (cr, 0.0, 0.9);
+  cairo_close_path (cr);
+  if (o->show_controls)
+    contrasty_stroke (cr);
+  else
+    cairo_new_path (cr);
+  cairo_rectangle (cr, 0.0, 0.8, 0.2, 0.2); 
+  mrg_listen (mrg, MRG_PRESS, dir_pgup_cb, o, NULL);
+
+  cairo_new_path (cr);
+
+  cairo_move_to (cr, 0.8, 0.8);
+  cairo_line_to (cr, 0.8, 1.0);
+  cairo_line_to (cr, 1.0, 0.9);
+  cairo_close_path (cr);
+
+  if (o->show_controls)
+    contrasty_stroke (cr);
+  else
+    cairo_new_path (cr);
+  cairo_rectangle (cr, 0.8, 0.8, 0.2, 0.2); 
+  mrg_listen (mrg, MRG_PRESS, dir_pgdn_cb, o, NULL);
+  cairo_new_path (cr);
+
+  mrg_add_binding (mrg, "left", NULL, NULL, dir_pgup_cb, o);
+  mrg_add_binding (mrg, "right", NULL, NULL, dir_pgdn_cb, o);
+}
+
 static void ui_viewer (State *o)
 {
   Mrg *mrg = o->mrg;
@@ -578,8 +713,21 @@ static void ui_viewer (State *o)
   cairo_rectangle (cr, 0,0, mrg_width(mrg), mrg_height(mrg));
   mrg_listen (mrg, MRG_DRAG, on_pan_drag, o, NULL);
   mrg_listen (mrg, MRG_MOTION, on_viewer_motion, o, NULL);
-  cairo_new_path (cr);
   cairo_scale (cr, mrg_width(mrg), mrg_height(mrg));
+  cairo_new_path (cr);
+  cairo_rectangle (cr, 0.05, 0.05, 0.05, 0.05);
+  cairo_rectangle (cr, 0.15, 0.05, 0.05, 0.05);
+  cairo_rectangle (cr, 0.05, 0.15, 0.05, 0.05);
+  cairo_rectangle (cr, 0.15, 0.15, 0.05, 0.05);
+  if (o->show_controls)
+    contrasty_stroke (cr);
+  else
+    cairo_new_path (cr);
+  cairo_rectangle (cr, 0.0, 0.0, 0.2, 0.2); 
+  mrg_listen (mrg, MRG_PRESS, go_parent_cb, o, NULL);
+
+
+  cairo_new_path (cr);
   cairo_move_to (cr, 0.2, 0.8);
   cairo_line_to (cr, 0.2, 1.0);
   cairo_line_to (cr, 0.0, 0.9);
@@ -614,6 +762,23 @@ static void ui_viewer (State *o)
   cairo_rectangle (cr, 0.8, 0.0, 0.2, 0.2); 
   mrg_listen (mrg, MRG_PRESS, toggle_actions_cb, o, NULL);
   cairo_new_path (cr);
+
+  mrg_add_binding (mrg, "left", NULL, NULL,  pan_left_cb, o);
+  mrg_add_binding (mrg, "right", NULL, NULL, pan_right_cb, o);
+  mrg_add_binding (mrg, "up", NULL, NULL,    pan_up_cb, o);
+  mrg_add_binding (mrg, "down", NULL, NULL,  pan_down_cb, o);
+  mrg_add_binding (mrg, "+", NULL, NULL,     zoom_in_cb, o);
+  mrg_add_binding (mrg, "=", NULL, NULL,     zoom_in_cb, o);
+  mrg_add_binding (mrg, "-", NULL, NULL,     zoom_out_cb, o);
+  mrg_add_binding (mrg, "1", NULL, NULL,     zoom_1_cb, o);
+  mrg_add_binding (mrg, "m", NULL, NULL,     zoom_fit_cb, o);
+  mrg_add_binding (mrg, "m", NULL, NULL,     zoom_fit_cb, o);
+  mrg_add_binding (mrg, "x", NULL, NULL,     discard_cb, o);
+
+  mrg_add_binding (mrg, "space", NULL, NULL,     go_next_cb , o);
+  mrg_add_binding (mrg, "n", NULL, NULL,         go_next_cb, o);
+  mrg_add_binding (mrg, "p", NULL, NULL,         go_prev_cb, o);
+  mrg_add_binding (mrg, "backspace", NULL, NULL, go_prev_cb, o);
 }
 
 static void toggle_show_controls_cb (MrgEvent *event, void *data1, void *data2)
@@ -655,31 +820,27 @@ static void gegl_ui (Mrg *mrg, void *data)
   }
   else
   {
-    ui_viewer (o);
+    struct stat stat_buf;
+    lstat (o->path, &stat_buf);
+    if (S_ISREG (stat_buf.st_mode))
+    {
+      ui_viewer (o);
+
+    }
+    else if (S_ISDIR (stat_buf.st_mode))
+    {
+      ui_dir_viewer (o);
+    }
+    
+    mrg_add_binding (mrg, "escape", NULL, NULL, go_parent_cb, o);
     mrg_add_binding (mrg, "return", NULL, NULL, toggle_actions_cb, o);
   }
 
-  mrg_add_binding (mrg, "left", NULL, NULL,      pan_left_cb, o);
-  mrg_add_binding (mrg, "right", NULL, NULL,     pan_right_cb, o);
-  mrg_add_binding (mrg, "up", NULL, NULL,        pan_up_cb, o);
-  mrg_add_binding (mrg, "down", NULL, NULL,      pan_down_cb, o);
-  mrg_add_binding (mrg, "+", NULL, NULL,         zoom_in_cb, o);
-  mrg_add_binding (mrg, "=", NULL, NULL,         zoom_in_cb, o);
-  mrg_add_binding (mrg, "-", NULL, NULL,         zoom_out_cb, o);
-  mrg_add_binding (mrg, "1", NULL, NULL,         zoom_1_cb, o);
-  mrg_add_binding (mrg, "m", NULL, NULL,         zoom_fit_cb, o);
-
   mrg_add_binding (mrg, "control-q", NULL, NULL, mrg_quit_cb, o);
-  mrg_add_binding (mrg, "m", NULL, NULL,         zoom_fit_cb, o);
   mrg_add_binding (mrg, "q", NULL, NULL,         mrg_quit_cb, o);
-  mrg_add_binding (mrg, "x", NULL, NULL,         discard_cb, o);
   mrg_add_binding (mrg, "f", NULL, NULL,         toggle_fullscreen_cb, o);
   mrg_add_binding (mrg, "F11", NULL, NULL,       toggle_fullscreen_cb, o);
   mrg_add_binding (mrg, "tab", NULL, NULL,       toggle_show_controls_cb, o);
-  mrg_add_binding (mrg, "space", NULL, NULL,     go_next_cb , o);
-  mrg_add_binding (mrg, "n", NULL, NULL,         go_next_cb, o);
-  mrg_add_binding (mrg, "p", NULL, NULL,         go_prev_cb, o);
-  mrg_add_binding (mrg, "backspace", NULL, NULL, go_prev_cb, o);
 
   mrg_add_binding (mrg, ",", NULL, NULL,         preview_less_cb, o);
   mrg_add_binding (mrg, ".", NULL, NULL,         preview_more_cb, o);
@@ -851,6 +1012,11 @@ static void load_path (State *o)
 
   g_object_unref (o->gegl);
   o->gegl = NULL;
+  o->sink = NULL;
+  o->source = NULL;
+  o->rev = 0;
+  o->u = 0;
+  o->v = 0;
 
   meta = gegl_meta_get (path);
   if (meta)
@@ -907,7 +1073,6 @@ static void load_path (State *o)
   zoom_to_fit (o);
 
   mrg_queue_draw (o->mrg, NULL);
-  o->rev = 0;
 }
 
 
@@ -951,6 +1116,20 @@ static void go_next (State *o)
   }
 }
 
+static void go_parent (State *o)
+{
+  char *lastslash = strrchr (o->path, '/');
+  if (lastslash)
+  {
+    if (lastslash == o->path)
+      lastslash[1] = '\0';
+    else
+      lastslash[0] = '\0';
+    load_path (o);
+    mrg_queue_draw (o->mrg, NULL);
+  }
+}
+
 static void go_prev (State *o)
 {
   char *lastslash;
@@ -1011,6 +1190,16 @@ static void go_next_cb (MrgEvent *event, void *data1, void *data2)
   mrg_event_stop_propagate (event);
 }
 
+static void go_parent_cb (MrgEvent *event, void *data1, void *data2)
+{
+  State *o = data1;
+  if (o->rev)
+    save_cb (event, data1, data2);
+  go_parent (data1);
+  o->active = NULL;
+  mrg_event_stop_propagate (event);
+}
+
 static void go_prev_cb (MrgEvent *event, void *data1, void *data2)
 {
   State *o = data1;
diff --git a/operations/core/crop.c b/operations/core/crop.c
index f83e589..ac47844 100644
--- a/operations/core/crop.c
+++ b/operations/core/crop.c
@@ -42,6 +42,8 @@ property_double (height, _("Height"), 10.0 )
   ui_meta       ("unit", "pixel-distance")
   ui_meta       ("axis", "y")
 
+property_boolean (reset_origin, _("Reset origin"), FALSE)
+
 #else
 
 #define GEGL_OP_FILTER


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]