[glade] Added --slideshow option



commit 255647388420b838cb5338d2836acdb2c6f3c2ac
Author: Juan Pablo Ugarte <juanpablougarte gmail com>
Date:   Mon Jul 29 18:56:52 2013 -0300

    Added --slideshow option
    
    Make --screenshot and --slideshow save every widget in a different page if the format supports it
    (like pdf)

 gladeui/glade-preview-window.c |  208 +++++++++++++++++++++++++++-------------
 gladeui/glade-preview-window.h |    3 +
 gladeui/glade-previewer.c      |  112 ++++++++++++++++++++--
 3 files changed, 248 insertions(+), 75 deletions(-)
---
diff --git a/gladeui/glade-preview-window.c b/gladeui/glade-preview-window.c
index 116ec85..c2fe719 100644
--- a/gladeui/glade-preview-window.c
+++ b/gladeui/glade-preview-window.c
@@ -108,6 +108,14 @@ glade_preview_window_key_press_event (GtkWidget *widget, GdkEventKey *event)
       case GDK_KEY_F8:
         extension = priv->extension ? priv->extension : "png";
       break;
+      case GDK_KEY_F11:
+        if (gdk_window_get_state (gtk_widget_get_window (widget)) & GDK_WINDOW_STATE_FULLSCREEN)
+          gtk_window_unfullscreen (GTK_WINDOW (widget));
+        else
+          gtk_window_fullscreen (GTK_WINDOW (widget));
+
+        return TRUE;
+      break;
       default:
         return FALSE;
       break;
@@ -334,7 +342,7 @@ check_for_draw (GdkEvent *event, gpointer loop)
 
 /* Taken from Gtk sources gtk-reftest.c  */
 static void
-wait_for_drawing (GdkWindow *window)
+glade_preview_wait_for_drawing (GdkWindow *window)
 {
   GMainLoop *loop;
 
@@ -355,25 +363,70 @@ wait_for_drawing (GdkWindow *window)
   g_main_loop_run (loop);
 }
 
-static inline gdouble
-get_x_scale (GdkScreen *screen)
+static const gchar *
+glade_preview_get_extension (const gchar *filename)
 {
-  return 72.0 / (gdk_screen_get_width (screen) / (gdk_screen_get_width_mm (screen) * 0.03937008));
+  gchar *extension;
+  
+  g_return_val_if_fail (filename != NULL, NULL);
+
+  extension = g_strrstr (filename,".");
+
+  if (extension)
+    extension++;
+
+  if (!extension)
+    {
+      g_warning ("%s has no extension!", filename);
+      return NULL;
+    }
+  return extension;
 }
 
-static inline gdouble
-get_y_scale (GdkScreen *screen)
+static void
+glade_preview_get_scale (GdkScreen *screen, gdouble *sx, gdouble *sy)
 {
-  return 72.0 / (gdk_screen_get_height (screen) / (gdk_screen_get_height_mm (screen) * 0.03937008));
+  if (sx)
+    *sx = 72.0 / (gdk_screen_get_width (screen) / (gdk_screen_get_width_mm (screen) * 0.03937008));
+
+  if (sy)
+    *sy = 72.0 / (gdk_screen_get_height (screen) / (gdk_screen_get_height_mm (screen) * 0.03937008));
 }
 
-typedef enum 
+static cairo_surface_t *
+glade_preview_surface_from_file (const gchar *filename, gdouble w, gdouble h)
 {
-  EXT_TYPE_SVG,
-  EXT_TYPE_PS,
-  EXT_TYPE_PDF,
-  EXT_TYPE_OTHER
-} ExtTypeEnum;
+  cairo_surface_t *surface;
+  const gchar *extension;
+
+  extension = glade_preview_get_extension (filename);
+  
+  if (extension == NULL)
+    return NULL;
+
+  if (g_strcmp0 (extension, "svg") == 0)
+#if CAIRO_HAS_SVG_SURFACE
+    surface = cairo_svg_surface_create (filename, w, h);
+#else
+    g_warning ("PDF not supported by the cairo version used");
+#endif
+  else if (g_strcmp0 (extension, "ps") == 0)
+#if CAIRO_HAS_PS_SURFACE
+    surface = cairo_ps_surface_create (filename, w, h);
+#else
+    g_warning ("PS not supported by the cairo version used");
+#endif
+  else if (g_strcmp0 (extension, "pdf") == 0)
+#if CAIRO_HAS_PDF_SURFACE
+    surface = cairo_pdf_surface_create (filename, w, h);
+#else
+    g_warning ("PDF not supported by the cairo version used");
+#endif
+  else
+    return NULL;
+
+  return surface;
+}
 
 /**
  * glade_preview_window_screenshot:
@@ -390,10 +443,10 @@ glade_preview_window_screenshot (GladePreviewWindow *window,
                                  const gchar *filename)
 {
   GladePreviewWindowPrivate *priv;
+  cairo_surface_t *surface;
   GdkWindow *gdkwindow;
   GdkScreen *screen;
-  gchar *extension;
-  ExtTypeEnum ext_type;
+  gdouble sx, sy;
   gint w, h;
 
   g_return_if_fail (GLADE_IS_PREVIEW_WINDOW (window));
@@ -403,74 +456,99 @@ glade_preview_window_screenshot (GladePreviewWindow *window,
   if (!priv->widget)
     return;
 
-  extension = g_strrstr (filename,".");
-
-  if (extension)
-    extension++;
-
-  if (!extension)
-    {
-      g_warning ("%s has no extension!", filename);
-      return;
-    }
-
   gdkwindow = gtk_widget_get_window (priv->widget);
   screen = gdk_window_get_screen (gdkwindow);
 
   if (wait)
-    wait_for_drawing (gdkwindow);
+    glade_preview_wait_for_drawing (gdkwindow);
 
   w = gtk_widget_get_allocated_width (priv->widget);
   h = gtk_widget_get_allocated_height (priv->widget);
+  glade_preview_get_scale (screen, &sx, &sy);
+    
+  surface = glade_preview_surface_from_file (filename, w*sx, h*sy);
 
-  if (g_strcmp0 (extension, "svg") == 0)
-    ext_type = EXT_TYPE_SVG;
-  else if (g_strcmp0 (extension, "ps") == 0)
-    ext_type = EXT_TYPE_PS;
-  else if (g_strcmp0 (extension, "pdf") == 0)
-    ext_type = EXT_TYPE_PDF;
+  if (surface)
+    {
+      cairo_t *cr = cairo_create (surface);
+      cairo_scale (cr, sx, sy);
+      gtk_widget_draw (priv->widget, cr);
+      cairo_destroy (cr);
+      cairo_surface_destroy(surface);
+    }
   else
-    ext_type = EXT_TYPE_OTHER;
-
-  if (ext_type == EXT_TYPE_OTHER)
     {
       GdkPixbuf *pix = gdk_pixbuf_get_from_window (gdkwindow, 0, 0, w, h);
-
-      gdk_pixbuf_save (pix, filename, extension, NULL, NULL);
+      const gchar *ext = glade_preview_get_extension (filename);
+      GError *error = NULL;
+      
+      if (gdk_pixbuf_save (pix, filename, ext ? ext : "png", &error, NULL))
+        {
+          g_warning ("Could not save screenshot to %s because %s", filename, error->message);
+          g_error_free (error);
+        }
 
       g_object_unref (pix);
     }
-  else
+}
+
+/**
+ * glade_preview_window_slideshow_save:
+ * @window: A GladePreviewWindow
+ * @filename:  a filename to save the slideshow.
+ * 
+ * Takes a screenshot of every widget GtkStack children and save it to @filename
+ * each in a different page
+ */
+void
+glade_preview_window_slideshow_save (GladePreviewWindow *window,
+                                     const gchar *filename)
+{
+  GladePreviewWindowPrivate *priv;
+  cairo_surface_t *surface;
+  GdkWindow *gdkwindow;
+  GtkStack *stack;
+  gdouble sx, sy;
+
+  g_return_if_fail (GLADE_IS_PREVIEW_WINDOW (window));
+  g_return_if_fail (filename != NULL);
+  priv = window->priv;
+
+  g_return_if_fail (priv->widget);
+  g_return_if_fail (GTK_IS_STACK (priv->widget));
+  stack = GTK_STACK (priv->widget);
+
+  gdkwindow = gtk_widget_get_window (priv->widget);
+  glade_preview_wait_for_drawing (gdkwindow);
+  
+  glade_preview_get_scale (gtk_widget_get_screen (GTK_WIDGET (window)), &sx, &sy); 
+  surface = glade_preview_surface_from_file (filename, 
+                                             gtk_widget_get_allocated_width (GTK_WIDGET (stack))*sx,
+                                             gtk_widget_get_allocated_height (GTK_WIDGET (stack))*sy);
+
+  if (surface)
     {
-      cairo_surface_t *surface;
-      cairo_t *cr;
-      gdouble sx = get_x_scale (screen);
-      gdouble sy = get_y_scale (screen);
+      GList *l, *children = gtk_container_get_children (GTK_CONTAINER (stack));
+      cairo_t *cr= cairo_create (surface);
 
-      if (ext_type == EXT_TYPE_SVG)
-#if CAIRO_HAS_SVG_SURFACE
-        surface = cairo_svg_surface_create (filename, w*sx, h*sy);
-#else
-      g_warning ("PDF not supported by the cairo version used");
-#endif
-      else if (ext_type == EXT_TYPE_PS)
-#if CAIRO_HAS_PS_SURFACE
-        surface = cairo_ps_surface_create (filename, w*sx, h*sy);
-#else
-      g_warning ("PS not supported by the cairo version used");
-#endif
-      else if (ext_type == EXT_TYPE_PDF)
-#if CAIRO_HAS_PDF_SURFACE
-        surface = cairo_pdf_surface_create (filename, w*sx, h*sy);
-#else
-      g_warning ("PDF not supported by the cairo version used");
-#endif
-      
-      cr  = cairo_create (surface);
       cairo_scale (cr, sx, sy);
-      gtk_widget_draw (priv->widget, cr);
+
+      for (l = children; l; l = g_list_next (l))
+        {
+          GtkWidget *child = l->data;
+          gtk_stack_set_visible_child (stack, child);
+          glade_preview_wait_for_drawing (gdkwindow);
+          gtk_widget_draw (child, cr);
+          cairo_show_page (cr);
+        }
+
+      if (children)
+        gtk_stack_set_visible_child (stack, children->data);
+
+      g_list_free (children);
       cairo_destroy (cr);
       cairo_surface_destroy(surface);
-
     }
+  else
+    g_warning ("Could not save slideshow to %s", filename);
 }
diff --git a/gladeui/glade-preview-window.h b/gladeui/glade-preview-window.h
index 7ed54f8..0ff2bdc 100644
--- a/gladeui/glade-preview-window.h
+++ b/gladeui/glade-preview-window.h
@@ -73,6 +73,9 @@ void       glade_preview_window_screenshot  (GladePreviewWindow *window,
                                              gboolean wait,
                                              const gchar *filename);
 
+void       glade_preview_window_slideshow_save (GladePreviewWindow *window,
+                                                const gchar        *filename);
+
 G_END_DECLS
 
 #endif /* _GLADE_PREVIEW_WINDOW_H_ */
diff --git a/gladeui/glade-previewer.c b/gladeui/glade-previewer.c
index 4a428d0..30f1726 100644
--- a/gladeui/glade-previewer.c
+++ b/gladeui/glade-previewer.c
@@ -45,12 +45,12 @@ get_toplevel (GtkBuilder *builder, gchar *name)
 
   if (name == NULL)
     {
-      GSList *objects;
+      GSList *l, *objects = gtk_builder_get_objects (builder);
 
       /* Iterate trough objects and search for a window or widget */
-      for (objects = gtk_builder_get_objects (builder); objects; objects = g_slist_next (objects))
+      for (l = objects; l; l = g_slist_next (l))
         {
-          GObject *obj = objects->data;
+          GObject *obj = l->data;
 
           if (!GTK_IS_WIDGET (obj) || gtk_widget_get_parent (GTK_WIDGET (obj)))
             continue;
@@ -289,8 +289,56 @@ glade_previewer_free (GladePreviewer *app)
   g_free (app);
 }
 
+static gint
+objects_cmp_func (gconstpointer a, gconstpointer b)
+{
+  const gchar *name_a, *name_b;
+  name_a = gtk_buildable_get_name (GTK_BUILDABLE (a));
+  name_b = gtk_buildable_get_name (GTK_BUILDABLE (b));
+  return g_strcmp0 (name_a, name_b);
+}
+static gboolean 
+glade_previewer_stack_key_press_event (GtkWidget *window, GdkEventKey *event, GtkWidget *widget)
+{
+  GtkWidget *child =  gtk_stack_get_visible_child  (GTK_STACK (widget));
+  GList *children, *node;
+  gboolean retval;
+  
+  if (!child)
+    return FALSE;
+
+  children = gtk_container_get_children (GTK_CONTAINER (widget));
+
+  node = g_list_find (children, child);
+
+  if (node)
+    {
+      switch (event->keyval)
+        {
+          case GDK_KEY_Page_Up:
+            if (node->prev)
+              gtk_stack_set_visible_child  (GTK_STACK (widget), node->prev->data);
+            retval = TRUE;
+            break;
+          case GDK_KEY_Page_Down:
+            if (node->next)
+              gtk_stack_set_visible_child  (GTK_STACK (widget), node->next->data);
+            retval = TRUE;
+            break;
+          default:
+            retval = FALSE;
+            break;
+        }
+    }
+
+  g_list_free (children);
+  return retval;
+}
+
+
 static gboolean listen = FALSE;
 static gboolean version = FALSE;
+static gboolean slideshow = FALSE;
 static gchar *file_name = NULL;
 static gchar *toplevel_name = NULL;
 static gchar *css_file_name = NULL;
@@ -303,6 +351,7 @@ static GOptionEntry option_entries[] =
     {"screenshot", 0, 0, G_OPTION_ARG_FILENAME, &screenshot_file_name, N_("File name to save a screenshot"), 
NULL},
     {"css", 0, 0, G_OPTION_ARG_FILENAME, &css_file_name, N_("CSS file to use"), NULL},
     {"listen", 'l', 0, G_OPTION_ARG_NONE, &listen, N_("Listen standard input"), NULL},
+    {"slideshow", 0, 0, G_OPTION_ARG_NONE, &slideshow, N_("make a slideshow of every toplevel widget by 
adding them in a GtkStack"), NULL},
     {"version", 'v', 0, G_OPTION_ARG_NONE, &version, N_("Display previewer version"), NULL},
     {NULL}
 };
@@ -373,7 +422,6 @@ main (int argc, char **argv)
     {
       GtkBuilder *builder = gtk_builder_new ();
       GError *error = NULL;
-      GtkWidget *widget;
 
       /* Use from_file() function gives builder a chance to know where to load resources from */
       if (!gtk_builder_add_from_file (builder, app->file_name, &error))
@@ -383,14 +431,58 @@ main (int argc, char **argv)
           return 1;
         }
 
-      widget = get_toplevel (builder, toplevel_name);
-      glade_preview_window_set_widget (app->window, widget);
-      gtk_widget_show (widget);
+      if (slideshow)
+        {
+          GSList *l, *objects = gtk_builder_get_objects (builder);
+          GtkStack *stack = GTK_STACK (gtk_stack_new ());
+
+          /* Add Page up and Page down key binding */
+          g_signal_connect (app->window, "key-press-event",
+                            G_CALLBACK (glade_previewer_stack_key_press_event),
+                            stack);
+
+          objects = g_slist_sort (objects, objects_cmp_func);
+
+          for (l = objects; l; l = g_slist_next (l))
+            {
+              GObject *obj = l->data;
+
+              if (!GTK_IS_WIDGET (obj) || gtk_widget_get_parent (GTK_WIDGET (obj)))
+                continue;
 
-      if (screenshot_file_name)
-        glade_preview_window_screenshot (app->window, TRUE, screenshot_file_name);
+              /* TODO: make sure we can add a toplevel inside a stack */
+              if (GTK_IS_WINDOW (obj))
+                continue;
+
+              gtk_stack_add_named (stack, GTK_WIDGET (obj),
+                                   gtk_buildable_get_name (GTK_BUILDABLE (obj)));
+            }
+
+          glade_preview_window_set_widget (app->window, GTK_WIDGET (stack));
+          gtk_widget_show (GTK_WIDGET (stack));
+          
+          if (screenshot_file_name)
+            glade_preview_window_slideshow_save (app->window, screenshot_file_name);
+          else
+            {
+              gtk_stack_set_transition_type (stack, GTK_STACK_TRANSITION_TYPE_CROSSFADE);
+
+              gtk_main ();
+            }
+
+          g_slist_free (objects);
+        }
       else
-        gtk_main ();
+        {
+          GtkWidget *widget = get_toplevel (builder, toplevel_name);
+          glade_preview_window_set_widget (app->window, widget);
+          gtk_widget_show (widget);
+
+          if (screenshot_file_name)
+            glade_preview_window_screenshot (app->window, TRUE, screenshot_file_name);
+          else
+            gtk_main ();
+        }
 
       g_object_unref (builder);
     }


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