[evince/wip/recent-view: 1/12] libgd: Added libgd to cut-n-paste



commit 44ce66a557620e49b29859b0985ed7df385ad3b1
Author: Aakash Goenka <aakash goenka gmail com>
Date:   Wed Jul 24 02:59:04 2013 +0530

    libgd: Added libgd to cut-n-paste
    
    A separate commit where libgd is added to cut-n-paste. libgd is used for the bookshelf
    view of recent documents.

 configure.ac                                  |    1 +
 cut-n-paste/Makefile.am                       |    2 +-
 cut-n-paste/libgd/Makefile.am                 |   24 +
 cut-n-paste/libgd/gd-icon-utils.c             |  186 ++++++++
 cut-n-paste/libgd/gd-icon-utils.h             |   35 ++
 cut-n-paste/libgd/gd-main-icon-view.c         |  393 +++++++++++++++++
 cut-n-paste/libgd/gd-main-icon-view.h         |   74 ++++
 cut-n-paste/libgd/gd-main-view-generic.c      |  311 +++++++++++++
 cut-n-paste/libgd/gd-main-view-generic.h      |  116 +++++
 cut-n-paste/libgd/gd-toggle-pixbuf-renderer.c |  198 +++++++++
 cut-n-paste/libgd/gd-toggle-pixbuf-renderer.h |   75 ++++
 cut-n-paste/libgd/gd-two-lines-renderer.c     |  576 +++++++++++++++++++++++++
 cut-n-paste/libgd/gd-two-lines-renderer.h     |   75 ++++
 shell/Makefile.am                             |    2 +
 14 files changed, 2067 insertions(+), 1 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 3f9b933..3e2b22d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -717,6 +717,7 @@ backend/xps/Makefile
 cut-n-paste/Makefile
 cut-n-paste/gimpcellrenderertoggle/Makefile
 cut-n-paste/synctex/Makefile
+cut-n-paste/libgd/Makefile
 data/evince.desktop.in
 data/evince-previewer.desktop.in
 data/Makefile
diff --git a/cut-n-paste/Makefile.am b/cut-n-paste/Makefile.am
index 7205394..2d5684d 100644
--- a/cut-n-paste/Makefile.am
+++ b/cut-n-paste/Makefile.am
@@ -1,3 +1,3 @@
-SUBDIRS = gimpcellrenderertoggle synctex
+SUBDIRS = gimpcellrenderertoggle synctex libgd
 
 -include $(top_srcdir)/git.mk
diff --git a/cut-n-paste/libgd/Makefile.am b/cut-n-paste/libgd/Makefile.am
new file mode 100644
index 0000000..aa65bc2
--- /dev/null
+++ b/cut-n-paste/libgd/Makefile.am
@@ -0,0 +1,24 @@
+noinst_LTLIBRARIES = libgd.la
+
+libgd_la_SOURCES =     \
+       gd-icon-utils.c                 \
+       gd-icon-utils.h                 \
+       gd-main-icon-view.c             \
+       gd-main-icon-view.h             \
+       gd-main-view-generic.c          \
+       gd-main-view-generic.h          \
+       gd-toggle-pixbuf-renderer.c     \
+       gd-toggle-pixbuf-renderer.h     \
+       gd-two-lines-renderer.c         \
+       gd-two-lines-renderer.h
+
+libgd_la_CFLAGS =      \
+       $(SHELL_CORE_CFLAGS)    \
+       $(WARNING_CFLAGS)       \
+       $(DISABLE_DEPRECATED)
+
+libgd_la_LIBADD = $(BACKEND_LIBS)
+
+-include $(top_srcdir)/git.mk
+
+AM_CPPFLAGS = $(BACKEND_CFLAGS)
diff --git a/cut-n-paste/libgd/gd-icon-utils.c b/cut-n-paste/libgd/gd-icon-utils.c
new file mode 100644
index 0000000..37a5606
--- /dev/null
+++ b/cut-n-paste/libgd/gd-icon-utils.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2011, 2012 Red Hat, Inc.
+ *
+ * Gnome Documents 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.
+ *
+ * Gnome Documents 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 Gnome Documents; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Cosimo Cecchi <cosimoc redhat com>
+ *
+ */
+
+#include "gd-icon-utils.h"
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <string.h>
+#include <math.h>
+
+#define _BG_MIN_SIZE 20
+#define _EMBLEM_MIN_SIZE 8
+
+/**
+ * gd_create_symbolic_icon:
+ * @name:
+ *
+ * Returns: (transfer full):
+ */
+GIcon *
+gd_create_symbolic_icon (const gchar *name,
+                         gint base_size)
+{
+  gchar *symbolic_name;
+  GIcon *icon, *retval = NULL;
+  cairo_surface_t *surface;
+  cairo_t *cr;
+  GtkStyleContext *style;
+  GtkWidgetPath *path;
+  GdkPixbuf *pixbuf;
+  GtkIconTheme *theme;
+  GtkIconInfo *info;
+  gint bg_size;
+  gint emblem_size;
+  gint total_size;
+
+  total_size = base_size / 2;
+  bg_size = MAX (total_size / 2, _BG_MIN_SIZE);
+  emblem_size = MAX (bg_size - 8, _EMBLEM_MIN_SIZE);
+
+  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, total_size, total_size);
+  cr = cairo_create (surface);
+
+  style = gtk_style_context_new ();
+
+  path = gtk_widget_path_new ();
+  gtk_widget_path_append_type (path, GTK_TYPE_ICON_VIEW);
+  gtk_style_context_set_path (style, path);
+  gtk_widget_path_unref (path);
+
+  gtk_style_context_add_class (style, "documents-icon-bg");
+
+  gtk_render_background (style, cr, (total_size - bg_size) / 2, (total_size - bg_size) / 2, bg_size, 
bg_size);
+
+  symbolic_name = g_strconcat (name, "-symbolic", NULL);
+  icon = g_themed_icon_new_with_default_fallbacks (symbolic_name);
+  g_free (symbolic_name);
+
+  theme = gtk_icon_theme_get_default();
+  info = gtk_icon_theme_lookup_by_gicon (theme, icon, emblem_size,
+                                         GTK_ICON_LOOKUP_FORCE_SIZE);
+  g_object_unref (icon);
+
+  if (info == NULL)
+    goto out;
+
+  pixbuf = gtk_icon_info_load_symbolic_for_context (info, style, NULL, NULL);
+  g_object_unref (info);
+
+  if (pixbuf == NULL)
+    goto out;
+
+  gtk_render_icon (style, cr, pixbuf, (total_size - emblem_size) / 2,  (total_size - emblem_size) / 2);
+  g_object_unref (pixbuf);
+
+  retval = G_ICON (gdk_pixbuf_get_from_surface (surface, 0, 0, total_size, total_size));
+
+ out:
+  g_object_unref (style);
+  cairo_surface_destroy (surface);
+  cairo_destroy (cr);
+
+  return retval;
+}
+
+/**
+ * gd_embed_image_in_frame:
+ * @source_image:
+ * @frame_image_url:
+ * @slice_width:
+ * @border_width:
+ *
+ * Returns: (transfer full):
+ */
+GdkPixbuf *
+gd_embed_image_in_frame (GdkPixbuf *source_image,
+                         const gchar *frame_image_url,
+                         GtkBorder *slice_width,
+                         GtkBorder *border_width)
+{
+  cairo_surface_t *surface;
+  cairo_t *cr;
+  int source_width, source_height;
+  int dest_width, dest_height;
+  gchar *css_str;
+  GtkCssProvider *provider;
+  GtkStyleContext *context;
+  GError *error = NULL;
+  GdkPixbuf *retval;
+  GtkWidgetPath *path;
+
+  source_width = gdk_pixbuf_get_width (source_image);
+  source_height = gdk_pixbuf_get_height (source_image);
+
+  dest_width = source_width +  border_width->left + border_width->right;
+  dest_height = source_height + border_width->top + border_width->bottom;
+
+  css_str = g_strdup_printf (".embedded-image { border-image: url(\"%s\") %d %d %d %d / %dpx %dpx %dpx %dpx 
}",
+                             frame_image_url,
+                             slice_width->top, slice_width->right, slice_width->bottom, slice_width->left,
+                             border_width->top, border_width->right, border_width->bottom, 
border_width->left);
+  provider = gtk_css_provider_new ();
+  gtk_css_provider_load_from_data (provider, css_str, -1, &error);
+
+  if (error != NULL)
+    {
+      g_warning ("Unable to create the thumbnail frame image: %s", error->message);
+      g_error_free (error);
+      g_free (css_str);
+
+      return g_object_ref (source_image);
+    }
+
+  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, dest_width, dest_height);
+  cr = cairo_create (surface);
+
+  context = gtk_style_context_new ();
+  path = gtk_widget_path_new ();
+  gtk_widget_path_append_type (path, GTK_TYPE_ICON_VIEW);
+
+  gtk_style_context_set_path (context, path);
+  gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER (provider), 600);
+
+  gtk_render_icon (context, cr,
+                   source_image,
+                   border_width->left, border_width->top);
+
+  gtk_style_context_save (context);
+  gtk_style_context_add_class (context, "embedded-image");
+
+  gtk_render_frame (context, cr,
+                    0, 0,
+                    dest_width, dest_height);
+
+  gtk_style_context_restore (context);
+
+  retval = gdk_pixbuf_get_from_surface (surface,
+                                        0, 0, dest_width, dest_height);
+
+  cairo_surface_destroy (surface);
+  cairo_destroy (cr);
+
+  gtk_widget_path_unref (path);
+  g_object_unref (provider);
+  g_object_unref (context);
+  g_free (css_str);
+
+  return retval;
+}
diff --git a/cut-n-paste/libgd/gd-icon-utils.h b/cut-n-paste/libgd/gd-icon-utils.h
new file mode 100644
index 0000000..c5796f7
--- /dev/null
+++ b/cut-n-paste/libgd/gd-icon-utils.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011, 2012 Red Hat, Inc.
+ *
+ * Gnome Documents 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.
+ *
+ * Gnome Documents 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 Gnome Documents; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Cosimo Cecchi <cosimoc redhat com>
+ *
+ */
+
+#ifndef __GD_CREATE_SYMBOLIC_ICON_H__
+#define __GD_CREATE_SYMBOLIC_ICON_H__
+
+#include <gtk/gtk.h>
+
+GIcon *gd_create_symbolic_icon (const gchar *name,
+                                gint base_size);
+
+GdkPixbuf *gd_embed_image_in_frame (GdkPixbuf *source_image,
+                                    const gchar *frame_image_url,
+                                    GtkBorder *slice_width,
+                                    GtkBorder *border_width);
+
+#endif /* __GD_CREATE_SYMBOLIC_ICON_H__ */
diff --git a/cut-n-paste/libgd/gd-main-icon-view.c b/cut-n-paste/libgd/gd-main-icon-view.c
new file mode 100644
index 0000000..91466c3
--- /dev/null
+++ b/cut-n-paste/libgd/gd-main-icon-view.c
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 2011 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License 
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Cosimo Cecchi <cosimoc redhat com>
+ *
+ */
+
+#include "gd-main-icon-view.h"
+#include "gd-main-view-generic.h"
+#include "gd-toggle-pixbuf-renderer.h"
+#include "gd-two-lines-renderer.h"
+
+#include <math.h>
+#include <glib/gi18n.h>
+
+#define VIEW_ITEM_WIDTH 140
+#define VIEW_ITEM_WRAP_WIDTH 128
+#define VIEW_COLUMN_SPACING 20
+#define VIEW_MARGIN 16
+
+struct _GdMainIconViewPrivate {
+  GtkCellRenderer *pixbuf_cell;
+  gboolean selection_mode;
+};
+
+static void gd_main_view_generic_iface_init (GdMainViewGenericIface *iface);
+G_DEFINE_TYPE_WITH_CODE (GdMainIconView, gd_main_icon_view, GTK_TYPE_ICON_VIEW,
+                         G_IMPLEMENT_INTERFACE (GD_TYPE_MAIN_VIEW_GENERIC,
+                                                gd_main_view_generic_iface_init))
+
+static GtkTreePath*
+get_source_row (GdkDragContext *context)
+{
+  GtkTreeRowReference *ref;
+
+  ref = g_object_get_data (G_OBJECT (context), "gtk-icon-view-source-row");
+
+  if (ref)
+    return gtk_tree_row_reference_get_path (ref);
+  else
+    return NULL;
+}
+
+static void
+gd_main_icon_view_drag_data_get (GtkWidget *widget,
+                                 GdkDragContext *drag_context,
+                                 GtkSelectionData *data,
+                                 guint info,
+                                 guint time)
+{
+  GdMainIconView *self = GD_MAIN_ICON_VIEW (widget);
+  GtkTreeModel *model = gtk_icon_view_get_model (GTK_ICON_VIEW (self));
+
+  if (info != 0)
+    return;
+
+  _gd_main_view_generic_dnd_common (model, self->priv->selection_mode,
+                                    get_source_row (drag_context), data);
+
+  GTK_WIDGET_CLASS (gd_main_icon_view_parent_class)->drag_data_get (widget, drag_context,
+                                                                    data, info, time);
+}
+
+static void
+gd_main_icon_view_constructed (GObject *obj)
+{
+  GdMainIconView *self = GD_MAIN_ICON_VIEW (obj);
+  GtkCellRenderer *cell;
+  const GtkTargetEntry targets[] = {
+    { (char *) "text/uri-list", GTK_TARGET_OTHER_APP, 0 }
+  };
+
+  G_OBJECT_CLASS (gd_main_icon_view_parent_class)->constructed (obj);
+
+  gtk_widget_set_hexpand (GTK_WIDGET (self), TRUE);
+  gtk_widget_set_vexpand (GTK_WIDGET (self), TRUE);
+  gtk_icon_view_set_selection_mode (GTK_ICON_VIEW (self), GTK_SELECTION_NONE);
+
+  g_object_set (self,
+                "column-spacing", VIEW_COLUMN_SPACING,
+                "margin", VIEW_MARGIN,
+                NULL);
+
+  self->priv->pixbuf_cell = cell = gd_toggle_pixbuf_renderer_new ();
+  g_object_set (cell,
+                "xalign", 0.5,
+                "yalign", 0.5,
+                NULL);
+
+  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (self), cell, FALSE);
+  gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (self), cell,
+                                 "active", GD_MAIN_COLUMN_SELECTED);
+  gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (self), cell,
+                                 "pixbuf", GD_MAIN_COLUMN_ICON);
+
+  cell = gd_two_lines_renderer_new ();
+  g_object_set (cell,
+                "xalign", 0.5,
+                "alignment", PANGO_ALIGN_CENTER,
+                "wrap-mode", PANGO_WRAP_WORD_CHAR,
+                "wrap-width", VIEW_ITEM_WRAP_WIDTH,
+                "text-lines", 3,
+                NULL);
+  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (self), cell, FALSE);
+  gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (self), cell,
+                                 "text", GD_MAIN_COLUMN_PRIMARY_TEXT);
+  gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (self), cell,
+                                 "line-two", GD_MAIN_COLUMN_SECONDARY_TEXT);
+
+  gtk_icon_view_enable_model_drag_source (GTK_ICON_VIEW (self),
+                                          GDK_BUTTON1_MASK,
+                                          targets, 1,
+                                          GDK_ACTION_COPY);
+}
+
+static void
+path_from_line_rects (cairo_t *cr,
+                     GdkRectangle *lines,
+                     int n_lines)
+{
+  int start_line, end_line;
+  GdkRectangle *r;
+  int i;
+
+  /* Join rows vertically by extending to the middle */
+  for (i = 0; i < n_lines - 1; i++)
+    {
+      GdkRectangle *r1 = &lines[i];
+      GdkRectangle *r2 = &lines[i+1];
+      int gap = r2->y - (r1->y + r1->height);
+      int old_y;
+
+      r1->height += gap / 2;
+      old_y = r2->y;
+      r2->y = r1->y + r1->height;
+      r2->height += old_y - r2->y;
+    }
+
+  cairo_new_path (cr);
+  start_line = 0;
+
+  do
+    {
+      for (i = start_line; i < n_lines; i++)
+       {
+         r = &lines[i];
+         if (i == start_line)
+           cairo_move_to (cr, r->x + r->width, r->y);
+         else
+           cairo_line_to (cr, r->x + r->width, r->y);
+         cairo_line_to (cr, r->x + r->width, r->y + r->height);
+
+         if (i < n_lines - 1 &&
+             (r->x + r->width < lines[i+1].x ||
+              r->x > lines[i+1].x + lines[i+1].width))
+           {
+             i++;
+             break;
+           }
+       }
+      end_line = i;
+      for (i = end_line - 1; i >= start_line; i--)
+       {
+         r = &lines[i];
+         cairo_line_to (cr, r->x, r->y + r->height);
+         cairo_line_to (cr, r->x, r->y);
+       }
+      cairo_close_path (cr);
+      start_line = end_line;
+    }
+  while (end_line < n_lines);
+}
+
+static gboolean
+gd_main_icon_view_draw (GtkWidget *widget,
+                       cairo_t   *cr)
+{
+  GdMainIconView *self = GD_MAIN_ICON_VIEW (widget);
+  GtkAllocation allocation;
+  GtkStyleContext *context;
+  GdkRectangle line_rect;
+  GdkRectangle rect;
+  GtkTreePath *path;
+  GArray *lines;
+  GtkTreePath *rubberband_start, *rubberband_end;
+
+  GTK_WIDGET_CLASS (gd_main_icon_view_parent_class)->draw (widget, cr);
+
+  _gd_main_view_generic_get_rubberband_range (GD_MAIN_VIEW_GENERIC (self),
+                                             &rubberband_start, &rubberband_end);
+
+  if (rubberband_start)
+    {
+      cairo_save (cr);
+
+      context = gtk_widget_get_style_context (widget);
+
+      gtk_style_context_save (context);
+      gtk_style_context_add_class (context, GTK_STYLE_CLASS_RUBBERBAND);
+
+      path = gtk_tree_path_copy (rubberband_start);
+
+      line_rect.width = 0;
+      lines = g_array_new (FALSE, FALSE, sizeof (GdkRectangle));
+
+      while (gtk_tree_path_compare (path, rubberband_end) <= 0)
+       {
+         if (gtk_icon_view_get_cell_rect (GTK_ICON_VIEW (widget),
+                                          path,
+                                          NULL, &rect))
+           {
+             if (line_rect.width == 0)
+               line_rect = rect;
+             else
+               {
+                 if (rect.y == line_rect.y)
+                   gdk_rectangle_union (&rect, &line_rect, &line_rect);
+                 else
+                   {
+                     g_array_append_val (lines, line_rect);
+                     line_rect = rect;
+                   }
+               }
+           }
+         gtk_tree_path_next (path);
+       }
+
+      if (line_rect.width != 0)
+       g_array_append_val (lines, line_rect);
+
+      if (lines->len > 0)
+       {
+         GtkStateFlags state;
+         cairo_path_t *path;
+         GtkBorder border;
+         GdkRGBA border_color;
+
+         path_from_line_rects (cr, (GdkRectangle *)lines->data, lines->len);
+
+         /* For some reason we need to copy and reapply the path, or it gets
+            eaten by gtk_render_background() */
+         path = cairo_copy_path (cr);
+
+         cairo_save (cr);
+         cairo_clip (cr);
+         gtk_widget_get_allocation (widget, &allocation);
+         gtk_render_background (context, cr,
+                                0, 0,
+                                allocation.width, allocation.height);
+         cairo_restore (cr);
+
+         cairo_append_path (cr, path);
+         cairo_path_destroy (path);
+
+         state = gtk_widget_get_state_flags (widget);
+         gtk_style_context_get_border_color (context,
+                                             state,
+                                             &border_color);
+         gtk_style_context_get_border (context, state,
+                                       &border);
+
+         cairo_set_line_width (cr, border.left);
+         gdk_cairo_set_source_rgba (cr, &border_color);
+         cairo_stroke (cr);
+       }
+      g_array_free (lines, TRUE);
+
+      gtk_tree_path_free (path);
+
+      gtk_style_context_restore (context);
+      cairo_restore (cr);
+    }
+
+  return FALSE;
+}
+
+static void
+gd_main_icon_view_class_init (GdMainIconViewClass *klass)
+{
+  GObjectClass *oclass = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *wclass = GTK_WIDGET_CLASS (klass);
+  GtkBindingSet *binding_set;
+  GdkModifierType activate_modifiers[] = { GDK_SHIFT_MASK, GDK_CONTROL_MASK, GDK_SHIFT_MASK | 
GDK_CONTROL_MASK };
+  int i;
+
+  binding_set = gtk_binding_set_by_class (klass);
+
+  oclass->constructed = gd_main_icon_view_constructed;
+  wclass->drag_data_get = gd_main_icon_view_drag_data_get;
+  wclass->draw = gd_main_icon_view_draw;
+
+  gtk_widget_class_install_style_property (wclass,
+                                           g_param_spec_int ("check-icon-size",
+                                                             "Check icon size",
+                                                             "Check icon size",
+                                                             -1, G_MAXINT, 40,
+                                                             G_PARAM_READWRITE));
+
+  g_type_class_add_private (klass, sizeof (GdMainIconViewPrivate));
+
+
+  for (i = 0; i < G_N_ELEMENTS (activate_modifiers); i++)
+    {
+      gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, activate_modifiers[i],
+                                   "activate-cursor-item", 0);
+      gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, activate_modifiers[i],
+                                   "activate-cursor-item", 0);
+      gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, activate_modifiers[i],
+                                   "activate-cursor-item", 0);
+      gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, activate_modifiers[i],
+                                   "activate-cursor-item", 0);
+      gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, activate_modifiers[i],
+                                   "activate-cursor-item", 0);
+    }
+}
+
+static void
+gd_main_icon_view_init (GdMainIconView *self)
+{
+  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GD_TYPE_MAIN_ICON_VIEW, GdMainIconViewPrivate);
+}
+
+static GtkTreePath *
+gd_main_icon_view_get_path_at_pos (GdMainViewGeneric *mv,
+                                   gint x,
+                                   gint y)
+{
+  return gtk_icon_view_get_path_at_pos (GTK_ICON_VIEW (mv), x, y);
+}
+
+static void
+gd_main_icon_view_set_selection_mode (GdMainViewGeneric *mv,
+                                      gboolean selection_mode)
+{
+  GdMainIconView *self = GD_MAIN_ICON_VIEW (mv);
+
+  self->priv->selection_mode = selection_mode;
+
+  g_object_set (self->priv->pixbuf_cell,
+                "toggle-visible", selection_mode,
+                NULL);
+  gtk_widget_queue_draw (GTK_WIDGET (self));
+}
+
+static void
+gd_main_icon_view_scroll_to_path (GdMainViewGeneric *mv,
+                                  GtkTreePath *path)
+{
+  gtk_icon_view_scroll_to_path (GTK_ICON_VIEW (mv), path, TRUE, 0.5, 0.5);
+}
+
+static void
+gd_main_icon_view_set_model (GdMainViewGeneric *mv,
+                             GtkTreeModel *model)
+{
+  gtk_icon_view_set_model (GTK_ICON_VIEW (mv), model);
+}
+
+static GtkTreeModel *
+gd_main_icon_view_get_model (GdMainViewGeneric *mv)
+{
+  return gtk_icon_view_get_model (GTK_ICON_VIEW (mv));
+}
+
+static void
+gd_main_view_generic_iface_init (GdMainViewGenericIface *iface)
+{
+  iface->set_model = gd_main_icon_view_set_model;
+  iface->get_model = gd_main_icon_view_get_model;
+  iface->get_path_at_pos = gd_main_icon_view_get_path_at_pos;
+  iface->scroll_to_path = gd_main_icon_view_scroll_to_path;
+  iface->set_selection_mode = gd_main_icon_view_set_selection_mode;
+}
+
+GtkWidget *
+gd_main_icon_view_new (void)
+{
+  return g_object_new (GD_TYPE_MAIN_ICON_VIEW, NULL);
+}
diff --git a/cut-n-paste/libgd/gd-main-icon-view.h b/cut-n-paste/libgd/gd-main-icon-view.h
new file mode 100644
index 0000000..7370b2a
--- /dev/null
+++ b/cut-n-paste/libgd/gd-main-icon-view.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2011 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License 
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Cosimo Cecchi <cosimoc redhat com>
+ *
+ */
+
+#ifndef __GD_MAIN_ICON_VIEW_H__
+#define __GD_MAIN_ICON_VIEW_H__
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GD_TYPE_MAIN_ICON_VIEW gd_main_icon_view_get_type()
+
+#define GD_MAIN_ICON_VIEW(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+   GD_TYPE_MAIN_ICON_VIEW, GdMainIconView))
+
+#define GD_MAIN_ICON_VIEW_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), \
+   GD_TYPE_MAIN_ICON_VIEW, GdMainIconViewClass))
+
+#define GD_IS_MAIN_ICON_VIEW(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+   GD_TYPE_MAIN_ICON_VIEW))
+
+#define GD_IS_MAIN_ICON_VIEW_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+   GD_TYPE_MAIN_ICON_VIEW))
+
+#define GD_MAIN_ICON_VIEW_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+   GD_TYPE_MAIN_ICON_VIEW, GdMainIconViewClass))
+
+typedef struct _GdMainIconView GdMainIconView;
+typedef struct _GdMainIconViewClass GdMainIconViewClass;
+typedef struct _GdMainIconViewPrivate GdMainIconViewPrivate;
+
+struct _GdMainIconView
+{
+  GtkIconView parent;
+
+  GdMainIconViewPrivate *priv;
+};
+
+struct _GdMainIconViewClass
+{
+  GtkIconViewClass parent_class;
+};
+
+GType gd_main_icon_view_get_type (void) G_GNUC_CONST;
+
+GtkWidget * gd_main_icon_view_new (void);
+
+G_END_DECLS
+
+#endif /* __GD_MAIN_ICON_VIEW_H__ */
diff --git a/cut-n-paste/libgd/gd-main-view-generic.c b/cut-n-paste/libgd/gd-main-view-generic.c
new file mode 100644
index 0000000..200153c
--- /dev/null
+++ b/cut-n-paste/libgd/gd-main-view-generic.c
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2011 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License 
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Cosimo Cecchi <cosimoc redhat com>
+ *
+ */
+
+#include "gd-main-view-generic.h"
+
+enum {
+  VIEW_SELECTION_CHANGED,
+  NUM_SIGNALS
+};
+
+static guint signals[NUM_SIGNALS] = { 0, };
+
+typedef GdMainViewGenericIface GdMainViewGenericInterface;
+G_DEFINE_INTERFACE (GdMainViewGeneric, gd_main_view_generic, GTK_TYPE_WIDGET)
+
+static void
+gd_main_view_generic_default_init (GdMainViewGenericInterface *iface)
+{
+  signals[VIEW_SELECTION_CHANGED] =
+    g_signal_new ("view-selection-changed",
+                  GD_TYPE_MAIN_VIEW_GENERIC,
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+}
+
+/**
+ * gd_main_view_generic_set_model:
+ * @self:
+ * @model: (allow-none):
+ *
+ */
+void
+gd_main_view_generic_set_model (GdMainViewGeneric *self,
+                                GtkTreeModel *model)
+{
+  GdMainViewGenericInterface *iface;
+
+  iface = GD_MAIN_VIEW_GENERIC_GET_IFACE (self);
+
+  (* iface->set_model) (self, model);
+}
+
+GtkTreePath *
+gd_main_view_generic_get_path_at_pos (GdMainViewGeneric *self,
+                                      gint x,
+                                      gint y)
+{
+  GdMainViewGenericInterface *iface;
+
+  iface = GD_MAIN_VIEW_GENERIC_GET_IFACE (self);
+
+  return (* iface->get_path_at_pos) (self, x, y);
+}
+
+void
+gd_main_view_generic_set_selection_mode (GdMainViewGeneric *self,
+                                         gboolean selection_mode)
+{
+  GdMainViewGenericInterface *iface;
+
+  iface = GD_MAIN_VIEW_GENERIC_GET_IFACE (self);
+
+  (* iface->set_selection_mode) (self, selection_mode);
+}
+
+
+typedef struct {
+  GtkTreePath *rubberband_start;
+  GtkTreePath *rubberband_end;
+} RubberbandInfo;
+
+static void
+rubber_band_info_destroy (RubberbandInfo *info)
+{
+  g_clear_pointer (&info->rubberband_start,
+                  gtk_tree_path_free);
+  g_clear_pointer (&info->rubberband_end,
+                  gtk_tree_path_free);
+  g_slice_free (RubberbandInfo, info);
+}
+
+static RubberbandInfo*
+get_rubber_band_info (GdMainViewGeneric *self)
+{
+  RubberbandInfo *info;
+
+  info = g_object_get_data (G_OBJECT (self), "gd-main-view-generic-rubber-band");
+  if (info == NULL)
+    {
+      info = g_slice_new0 (RubberbandInfo);
+      g_object_set_data_full (G_OBJECT (self), "gd-main-view-generic-rubber-band",
+                             info, (GDestroyNotify)rubber_band_info_destroy);
+    }
+
+  return info;
+}
+
+void
+gd_main_view_generic_set_rubberband_range (GdMainViewGeneric *self,
+                                          GtkTreePath *start,
+                                          GtkTreePath *end)
+{
+  RubberbandInfo *info;
+
+  info = get_rubber_band_info (self);
+
+  if (start == NULL || end == NULL)
+    {
+      g_clear_pointer (&info->rubberband_start,
+                      gtk_tree_path_free);
+      g_clear_pointer (&info->rubberband_end,
+                      gtk_tree_path_free);
+    }
+  else
+    {
+      if (gtk_tree_path_compare (start, end) < 0)
+       {
+         info->rubberband_start = gtk_tree_path_copy (start);
+         info->rubberband_end = gtk_tree_path_copy (end);
+       }
+      else
+       {
+         info->rubberband_start = gtk_tree_path_copy (end);
+         info->rubberband_end = gtk_tree_path_copy (start);
+       }
+    }
+
+  gtk_widget_queue_draw (GTK_WIDGET (self));
+}
+
+void
+_gd_main_view_generic_get_rubberband_range (GdMainViewGeneric *self,
+                                           GtkTreePath **start,
+                                           GtkTreePath **end)
+{
+  RubberbandInfo *info;
+
+  info = get_rubber_band_info (self);
+
+  *start = info->rubberband_start;
+  *end = info->rubberband_end;
+}
+
+void
+gd_main_view_generic_scroll_to_path (GdMainViewGeneric *self,
+                                     GtkTreePath *path)
+{
+  GdMainViewGenericInterface *iface;
+
+  iface = GD_MAIN_VIEW_GENERIC_GET_IFACE (self);
+
+  (* iface->scroll_to_path) (self, path);
+}
+
+/**
+ * gd_main_view_generic_get_model:
+ *
+ * Returns: (transfer none): The associated model
+ */
+GtkTreeModel *
+gd_main_view_generic_get_model (GdMainViewGeneric *self)
+{
+  GdMainViewGenericInterface *iface;
+
+  iface = GD_MAIN_VIEW_GENERIC_GET_IFACE (self);
+
+  return (* iface->get_model) (self);
+}
+
+static gboolean
+build_selection_uris_foreach (GtkTreeModel *model,
+                              GtkTreePath *path,
+                              GtkTreeIter *iter,
+                              gpointer user_data)
+{
+  GPtrArray *ptr_array = user_data;
+  gchar *uri;
+  gboolean is_selected;
+
+  gtk_tree_model_get (model, iter,
+                      GD_MAIN_COLUMN_URI, &uri,
+                      GD_MAIN_COLUMN_SELECTED, &is_selected,
+                      -1);
+
+  if (is_selected)
+    g_ptr_array_add (ptr_array, uri);
+  else
+    g_free (uri);
+
+  return FALSE;
+}
+
+static gchar **
+model_get_selection_uris (GtkTreeModel *model)
+{
+  GPtrArray *ptr_array = g_ptr_array_new ();
+
+  gtk_tree_model_foreach (model,
+                          build_selection_uris_foreach,
+                          ptr_array);
+  
+  g_ptr_array_add (ptr_array, NULL);
+  return (gchar **) g_ptr_array_free (ptr_array, FALSE);
+}
+
+static gboolean
+set_selection_foreach (GtkTreeModel *model,
+                       GtkTreePath *path,
+                       GtkTreeIter *iter,
+                       gpointer user_data)
+{
+  gboolean selection = GPOINTER_TO_INT (user_data);
+
+  gtk_list_store_set (GTK_LIST_STORE (model), iter,
+                      GD_MAIN_COLUMN_SELECTED, selection,
+                      -1);
+
+  return FALSE;
+}
+
+static void
+set_all_selection (GdMainViewGeneric *self,
+                   GtkTreeModel *model,
+                   gboolean selection)
+{
+  GtkTreeModel *actual_model;
+
+  if (!model)
+    return;
+
+  if (GTK_IS_TREE_MODEL_FILTER (model))
+    actual_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
+  else
+    actual_model = model;
+
+  gtk_tree_model_foreach (actual_model,
+                          set_selection_foreach,
+                          GINT_TO_POINTER (selection));
+  g_signal_emit (self, signals[VIEW_SELECTION_CHANGED], 0);
+}
+
+void
+gd_main_view_generic_select_all (GdMainViewGeneric *self)
+{
+  GtkTreeModel *model = gd_main_view_generic_get_model (self);
+
+  set_all_selection (self, model, TRUE);
+}
+
+void
+gd_main_view_generic_unselect_all (GdMainViewGeneric *self)
+{
+  GtkTreeModel *model = gd_main_view_generic_get_model (self);
+
+  set_all_selection (self, model, FALSE);
+}
+
+void
+_gd_main_view_generic_dnd_common (GtkTreeModel *model,
+                                  gboolean selection_mode,
+                                  GtkTreePath *path,
+                                  GtkSelectionData *data)
+{
+  gchar **uris;
+
+  if (selection_mode)
+    {
+      uris = model_get_selection_uris (model);
+    }
+  else
+    {
+      GtkTreeIter iter;
+      gboolean res;
+      gchar *uri = NULL;
+
+      if (path != NULL)
+        {
+          res = gtk_tree_model_get_iter (model, &iter, path);
+          if (res)
+            gtk_tree_model_get (model, &iter,
+                                GD_MAIN_COLUMN_URI, &uri,
+                                -1);
+        }
+
+      uris = g_new0 (gchar *, 2);
+      uris[0] = uri;
+      uris[1] = NULL;
+    }
+
+  gtk_selection_data_set_uris (data, uris);
+  g_strfreev (uris);
+}
diff --git a/cut-n-paste/libgd/gd-main-view-generic.h b/cut-n-paste/libgd/gd-main-view-generic.h
new file mode 100644
index 0000000..4df84ff
--- /dev/null
+++ b/cut-n-paste/libgd/gd-main-view-generic.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2011 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License 
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Cosimo Cecchi <cosimoc redhat com>
+ *
+ */
+
+#ifndef __GD_MAIN_VIEW_GENERIC_H__
+#define __GD_MAIN_VIEW_GENERIC_H__
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+  GD_MAIN_COLUMN_ID,
+  GD_MAIN_COLUMN_URI,
+  GD_MAIN_COLUMN_PRIMARY_TEXT,
+  GD_MAIN_COLUMN_SECONDARY_TEXT,
+  GD_MAIN_COLUMN_ICON,
+  GD_MAIN_COLUMN_MTIME,
+  GD_MAIN_COLUMN_SELECTED,
+
+  GD_MAIN_COLUMN_LAST
+} GdMainColumns;
+
+#define GD_TYPE_MAIN_VIEW_GENERIC gd_main_view_generic_get_type()
+
+#define GD_MAIN_VIEW_GENERIC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+   GD_TYPE_MAIN_VIEW_GENERIC, GdMainViewGeneric))
+
+#define GD_MAIN_VIEW_GENERIC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), \
+   GD_TYPE_MAIN_VIEW_GENERIC, GdMainViewGenericIface))
+
+#define GD_IS_MAIN_VIEW_GENERIC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+   GD_TYPE_MAIN_VIEW_GENERIC))
+
+#define GD_IS_MAIN_VIEW_GENERIC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+   GD_TYPE_MAIN_VIEW_GENERIC))
+
+#define GD_MAIN_VIEW_GENERIC_GET_IFACE(obj) \
+  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), \
+   GD_TYPE_MAIN_VIEW_GENERIC, GdMainViewGenericIface))
+
+typedef struct _GdMainViewGeneric GdMainViewGeneric;
+typedef struct _GdMainViewGenericIface GdMainViewGenericIface;
+
+struct _GdMainViewGenericIface
+{
+  GTypeInterface base_iface;
+
+  /* vtable */
+  void          (* set_model)            (GdMainViewGeneric  *self,
+                                          GtkTreeModel       *model);
+  GtkTreeModel * (* get_model)           (GdMainViewGeneric *self);
+
+  GtkTreePath * (* get_path_at_pos)      (GdMainViewGeneric *self,
+                                          gint               x, 
+                                          gint               y);
+  void          (* scroll_to_path)       (GdMainViewGeneric *self,
+                                          GtkTreePath       *path);
+  void          (* set_selection_mode)   (GdMainViewGeneric *self,
+                                          gboolean           selection_mode);
+};
+
+GType gd_main_view_generic_get_type (void) G_GNUC_CONST;
+
+void gd_main_view_generic_set_model (GdMainViewGeneric *self,
+                                     GtkTreeModel *model);
+GtkTreeModel * gd_main_view_generic_get_model (GdMainViewGeneric *self);
+
+void gd_main_view_generic_scroll_to_path (GdMainViewGeneric *self,
+                                          GtkTreePath *path);
+void gd_main_view_generic_set_selection_mode (GdMainViewGeneric *self,
+                                              gboolean selection_mode);
+GtkTreePath * gd_main_view_generic_get_path_at_pos (GdMainViewGeneric *self,
+                                                    gint x,
+                                                    gint y);
+void gd_main_view_generic_select_all (GdMainViewGeneric *self);
+void gd_main_view_generic_unselect_all (GdMainViewGeneric *self);
+void gd_main_view_generic_set_rubberband_range (GdMainViewGeneric *self,
+                                               GtkTreePath *start,
+                                               GtkTreePath *end);
+
+/* private */
+void _gd_main_view_generic_dnd_common (GtkTreeModel *model,
+                                       gboolean selection_mode,
+                                       GtkTreePath *path,
+                                       GtkSelectionData *data);
+void _gd_main_view_generic_get_rubberband_range (GdMainViewGeneric *self,
+                                                GtkTreePath **start,
+                                                GtkTreePath **end);
+
+G_END_DECLS
+
+#endif /* __GD_MAIN_VIEW_GENERIC_H__ */
diff --git a/cut-n-paste/libgd/gd-toggle-pixbuf-renderer.c b/cut-n-paste/libgd/gd-toggle-pixbuf-renderer.c
new file mode 100644
index 0000000..3267938
--- /dev/null
+++ b/cut-n-paste/libgd/gd-toggle-pixbuf-renderer.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2011 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License 
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Cosimo Cecchi <cosimoc redhat com>
+ *
+ */
+
+#include "gd-toggle-pixbuf-renderer.h"
+
+G_DEFINE_TYPE (GdTogglePixbufRenderer, gd_toggle_pixbuf_renderer, GTK_TYPE_CELL_RENDERER_PIXBUF);
+
+enum {
+  PROP_ACTIVE = 1,
+  PROP_TOGGLE_VISIBLE,
+  NUM_PROPERTIES
+};
+
+static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
+
+struct _GdTogglePixbufRendererPrivate {
+  gboolean active;
+  gboolean toggle_visible;
+};
+
+static void
+gd_toggle_pixbuf_renderer_render (GtkCellRenderer      *cell,
+                                  cairo_t              *cr,
+                                  GtkWidget            *widget,
+                                  const GdkRectangle   *background_area,
+                                  const GdkRectangle   *cell_area,
+                                  GtkCellRendererState  flags)
+{
+  gint icon_size = -1;
+  gint check_x, check_y, x_offset, xpad, ypad;
+  GtkStyleContext *context;
+  GdTogglePixbufRenderer *self = GD_TOGGLE_PIXBUF_RENDERER (cell);
+  GtkTextDirection direction;
+
+  GTK_CELL_RENDERER_CLASS (gd_toggle_pixbuf_renderer_parent_class)->render
+    (cell, cr, widget,
+     background_area, cell_area, flags);
+
+  if (!self->priv->toggle_visible)
+    return;
+
+  gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
+  direction = gtk_widget_get_direction (widget);
+  gtk_widget_style_get (widget,
+                        "check-icon-size", &icon_size,
+                        NULL);
+
+  if (icon_size == -1)
+    icon_size = 40;
+
+  if (direction == GTK_TEXT_DIR_RTL)
+    x_offset = xpad;
+  else
+    x_offset = cell_area->width - icon_size - xpad;
+
+  check_x = cell_area->x + x_offset;
+  check_y = cell_area->y + cell_area->height - icon_size - ypad;
+
+  context = gtk_widget_get_style_context (widget);
+  gtk_style_context_save (context);
+  gtk_style_context_add_class (context, GTK_STYLE_CLASS_CHECK);
+
+  if (self->priv->active)
+    gtk_style_context_set_state (context, GTK_STATE_FLAG_ACTIVE);
+
+  gtk_render_check (context, cr,
+                    check_x, check_y,
+                    icon_size, icon_size);
+
+  gtk_style_context_restore (context);
+}
+
+static void
+gd_toggle_pixbuf_renderer_get_size (GtkCellRenderer *cell,
+                                    GtkWidget       *widget,
+                                    const GdkRectangle *cell_area,
+                                    gint *x_offset,
+                                    gint *y_offset,
+                                    gint *width,
+                                    gint *height)
+{
+  gint icon_size;
+
+  gtk_widget_style_get (widget,
+                        "check-icon-size", &icon_size,
+                        NULL);
+
+  GTK_CELL_RENDERER_CLASS (gd_toggle_pixbuf_renderer_parent_class)->get_size
+    (cell, widget, cell_area,
+     x_offset, y_offset, width, height);
+
+  *width += icon_size / 4;
+}
+
+static void
+gd_toggle_pixbuf_renderer_get_property (GObject    *object,
+                                        guint       property_id,
+                                        GValue     *value,
+                                        GParamSpec *pspec)
+{
+  GdTogglePixbufRenderer *self = GD_TOGGLE_PIXBUF_RENDERER (object);
+
+  switch (property_id)
+    {
+    case PROP_ACTIVE:
+      g_value_set_boolean (value, self->priv->active);
+      break;
+    case PROP_TOGGLE_VISIBLE:
+      g_value_set_boolean (value, self->priv->toggle_visible);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gd_toggle_pixbuf_renderer_set_property (GObject    *object,
+                                        guint       property_id,
+                                        const GValue *value,
+                                        GParamSpec *pspec)
+{
+  GdTogglePixbufRenderer *self = GD_TOGGLE_PIXBUF_RENDERER (object);
+
+  switch (property_id)
+    {
+    case PROP_ACTIVE:
+      self->priv->active = g_value_get_boolean (value);
+      break;
+    case PROP_TOGGLE_VISIBLE:
+      self->priv->toggle_visible = g_value_get_boolean (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gd_toggle_pixbuf_renderer_class_init (GdTogglePixbufRendererClass *klass)
+{
+  GObjectClass *oclass = G_OBJECT_CLASS (klass);
+  GtkCellRendererClass *crclass = GTK_CELL_RENDERER_CLASS (klass);
+
+  crclass->render = gd_toggle_pixbuf_renderer_render;
+  crclass->get_size = gd_toggle_pixbuf_renderer_get_size;
+  oclass->get_property = gd_toggle_pixbuf_renderer_get_property;
+  oclass->set_property = gd_toggle_pixbuf_renderer_set_property;
+
+  properties[PROP_ACTIVE] = 
+    g_param_spec_boolean ("active",
+                          "Active",
+                          "Whether the cell renderer is active",
+                          FALSE,
+                          G_PARAM_READWRITE |
+                          G_PARAM_STATIC_STRINGS);
+  properties[PROP_TOGGLE_VISIBLE] =
+    g_param_spec_boolean ("toggle-visible",
+                          "Toggle visible",
+                          "Whether to draw the toggle indicator",
+                          FALSE,
+                          G_PARAM_READWRITE |
+                          G_PARAM_STATIC_STRINGS);
+
+  g_type_class_add_private (klass, sizeof (GdTogglePixbufRendererPrivate));
+  g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
+}
+
+static void
+gd_toggle_pixbuf_renderer_init (GdTogglePixbufRenderer *self)
+{
+  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GD_TYPE_TOGGLE_PIXBUF_RENDERER,
+                                            GdTogglePixbufRendererPrivate);
+}
+
+GtkCellRenderer *
+gd_toggle_pixbuf_renderer_new (void)
+{
+  return g_object_new (GD_TYPE_TOGGLE_PIXBUF_RENDERER, NULL);
+}
diff --git a/cut-n-paste/libgd/gd-toggle-pixbuf-renderer.h b/cut-n-paste/libgd/gd-toggle-pixbuf-renderer.h
new file mode 100644
index 0000000..fe54cf4
--- /dev/null
+++ b/cut-n-paste/libgd/gd-toggle-pixbuf-renderer.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2011 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License 
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Cosimo Cecchi <cosimoc redhat com>
+ *
+ */
+
+#ifndef _GD_TOGGLE_PIXBUF_RENDERER_H
+#define _GD_TOGGLE_PIXBUF_RENDERER_H
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GD_TYPE_TOGGLE_PIXBUF_RENDERER gd_toggle_pixbuf_renderer_get_type()
+
+#define GD_TOGGLE_PIXBUF_RENDERER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+   GD_TYPE_TOGGLE_PIXBUF_RENDERER, GdTogglePixbufRenderer))
+
+#define GD_TOGGLE_PIXBUF_RENDERER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), \
+   GD_TYPE_TOGGLE_PIXBUF_RENDERER, GdTogglePixbufRendererClass))
+
+#define GD_IS_TOGGLE_PIXBUF_RENDERER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+   GD_TYPE_TOGGLE_PIXBUF_RENDERER))
+
+#define GD_IS_TOGGLE_PIXBUF_RENDERER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+   GD_TYPE_TOGGLE_PIXBUF_RENDERER))
+
+#define GD_TOGGLE_PIXBUF_RENDERER_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+   GD_TYPE_TOGGLE_PIXBUF_RENDERER, GdTogglePixbufRendererClass))
+
+typedef struct _GdTogglePixbufRenderer GdTogglePixbufRenderer;
+typedef struct _GdTogglePixbufRendererClass GdTogglePixbufRendererClass;
+typedef struct _GdTogglePixbufRendererPrivate GdTogglePixbufRendererPrivate;
+
+struct _GdTogglePixbufRenderer
+{
+  GtkCellRendererPixbuf parent;
+
+  GdTogglePixbufRendererPrivate *priv;
+};
+
+struct _GdTogglePixbufRendererClass
+{
+  GtkCellRendererPixbufClass parent_class;
+};
+
+GType gd_toggle_pixbuf_renderer_get_type (void) G_GNUC_CONST;
+
+GtkCellRenderer *gd_toggle_pixbuf_renderer_new (void);
+
+G_END_DECLS
+
+#endif /* _GD_TOGGLE_PIXBUF_RENDERER_H */
diff --git a/cut-n-paste/libgd/gd-two-lines-renderer.c b/cut-n-paste/libgd/gd-two-lines-renderer.c
new file mode 100644
index 0000000..564be88
--- /dev/null
+++ b/cut-n-paste/libgd/gd-two-lines-renderer.c
@@ -0,0 +1,576 @@
+/*
+ * Copyright (c) 2011 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License 
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Cosimo Cecchi <cosimoc redhat com>
+ *
+ */
+
+#include "gd-two-lines-renderer.h"
+#include <string.h>
+
+G_DEFINE_TYPE (GdTwoLinesRenderer, gd_two_lines_renderer, GTK_TYPE_CELL_RENDERER_TEXT)
+
+struct _GdTwoLinesRendererPrivate {
+  gchar *line_two;
+  gint text_lines;
+};
+
+enum {
+  PROP_TEXT_LINES = 1,
+  PROP_LINE_TWO,
+  NUM_PROPERTIES
+};
+
+static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
+
+static PangoLayout *
+create_layout_with_attrs (GtkWidget *widget,
+                          const GdkRectangle *cell_area,
+                          GdTwoLinesRenderer *self,
+                          PangoEllipsizeMode ellipsize)
+{
+  PangoLayout *layout;
+  gint wrap_width, xpad;
+  PangoWrapMode wrap_mode;
+  PangoAlignment alignment;
+
+  g_object_get (self,
+                "wrap-width", &wrap_width,
+                "wrap-mode", &wrap_mode,
+                "alignment", &alignment,
+                "xpad", &xpad,
+                NULL);
+
+  layout = pango_layout_new (gtk_widget_get_pango_context (widget));
+
+  pango_layout_set_ellipsize (layout, ellipsize);
+  pango_layout_set_alignment (layout, alignment);
+
+  if (wrap_width != -1)
+    {
+      pango_layout_set_width (layout, wrap_width * PANGO_SCALE);
+      pango_layout_set_wrap (layout, wrap_mode);
+    }
+  else
+    {
+      if (cell_area != NULL)
+        pango_layout_set_width (layout, (cell_area->width - 2 * xpad) * PANGO_SCALE);
+      else
+        pango_layout_set_width (layout, -1);
+
+      pango_layout_set_wrap (layout, PANGO_WRAP_CHAR);
+    }
+
+  return layout;
+}
+
+static void
+gd_two_lines_renderer_prepare_layouts (GdTwoLinesRenderer *self,
+                                       const GdkRectangle *cell_area,
+                                       GtkWidget *widget,
+                                       PangoLayout **layout_one,
+                                       PangoLayout **layout_two)
+{
+  PangoLayout *line_one;
+  PangoLayout *line_two = NULL;
+  gchar *text = NULL;
+
+  g_object_get (self,
+                "text", &text,
+                NULL);
+
+  line_one = create_layout_with_attrs (widget, cell_area,
+                                       self, PANGO_ELLIPSIZE_MIDDLE);
+
+  if (self->priv->line_two == NULL ||
+      g_strcmp0 (self->priv->line_two, "") == 0)
+    {
+      pango_layout_set_height (line_one, - (self->priv->text_lines));
+
+      if (text != NULL)
+        pango_layout_set_text (line_one, text, -1);
+    }
+  else
+    {
+      line_two = create_layout_with_attrs (widget, cell_area,
+                                           self, PANGO_ELLIPSIZE_END);
+
+      pango_layout_set_height (line_one, - (self->priv->text_lines - 1));
+      pango_layout_set_height (line_two, -1);
+      pango_layout_set_text (line_two, self->priv->line_two, -1);
+
+      if (text != NULL)
+        pango_layout_set_text (line_one, text, -1);
+    }
+
+  if (layout_one)
+    *layout_one = line_one;
+  if (layout_two)
+    *layout_two = line_two;
+
+  g_free (text);
+}
+
+static void
+gd_two_lines_renderer_get_size (GtkCellRenderer *cell,
+                                GtkWidget *widget,
+                                PangoLayout *layout_1,
+                                PangoLayout *layout_2,
+                                gint *width,
+                                gint *height,
+                                const GdkRectangle *cell_area,
+                                gint *x_offset_1,
+                                gint *x_offset_2,
+                                gint *y_offset)
+{
+  GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (cell);
+  gint xpad, ypad;
+  PangoLayout *layout_one, *layout_two;
+  GdkRectangle layout_one_rect, layout_two_rect, layout_union;
+
+  if (layout_1 == NULL)
+    {
+      gd_two_lines_renderer_prepare_layouts (self, cell_area, widget, &layout_one, &layout_two);
+    }
+  else
+    {
+      layout_one = g_object_ref (layout_1);
+
+      if (layout_2 != NULL)
+        layout_two = g_object_ref (layout_2);
+      else
+        layout_two = NULL;
+    }
+
+  gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
+  pango_layout_get_pixel_extents (layout_one, NULL, (PangoRectangle *) &layout_one_rect);
+
+  if (layout_two != NULL)
+    {
+      pango_layout_get_pixel_extents (layout_two, NULL, (PangoRectangle *) &layout_two_rect);
+
+      layout_union.width = MAX (layout_one_rect.width, layout_two_rect.width);
+      layout_union.height = layout_one_rect.height + layout_two_rect.height;
+    }
+  else
+    {
+      layout_union = layout_one_rect;
+    }
+
+  if (cell_area)
+    {
+      gfloat xalign, yalign;
+
+      gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);
+
+      layout_union.width  = MIN (layout_union.width, cell_area->width - 2 * xpad);
+      layout_union.height = MIN (layout_union.height, cell_area->height - 2 * ypad);
+
+      if (x_offset_1)
+       {
+         if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+           *x_offset_1 = (1.0 - xalign) * (cell_area->width - (layout_one_rect.width + (2 * xpad)));
+         else 
+           *x_offset_1 = xalign * (cell_area->width - (layout_one_rect.width + (2 * xpad)));
+
+          *x_offset_1 = MAX (*x_offset_1, 0);
+       }
+      if (x_offset_2)
+        {
+          if (layout_two != NULL)
+            {
+              if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+                *x_offset_2 = (1.0 - xalign) * (cell_area->width - (layout_two_rect.width + (2 * xpad)));
+              else 
+                *x_offset_2 = xalign * (cell_area->width - (layout_two_rect.width + (2 * xpad)));
+
+              *x_offset_2 = MAX (*x_offset_2, 0);
+            }
+          else
+            {
+              *x_offset_2 = 0;
+            }
+        }
+
+      if (y_offset)
+       {
+         *y_offset = yalign * (cell_area->height - (layout_union.height + (2 * ypad)));
+         *y_offset = MAX (*y_offset, 0);
+       }
+    }
+  else
+    {
+      if (x_offset_1) *x_offset_1 = 0;
+      if (x_offset_2) *x_offset_2 = 0;
+      if (y_offset) *y_offset = 0;
+    }
+
+  g_clear_object (&layout_one);
+  g_clear_object (&layout_two);
+
+  if (height)
+    *height = ypad * 2 + layout_union.height;
+
+  if (width)
+    *width = xpad * 2 + layout_union.width;
+}
+
+static void
+gd_two_lines_renderer_render (GtkCellRenderer      *cell,
+                              cairo_t              *cr,
+                              GtkWidget            *widget,
+                              const GdkRectangle   *background_area,
+                              const GdkRectangle   *cell_area,
+                              GtkCellRendererState  flags)
+{
+  GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (cell);
+  GtkStyleContext *context;
+  gint line_one_height;
+  GtkStateFlags state;
+  GdkRectangle area, render_area = *cell_area;
+  gint xpad, ypad, x_offset_1, x_offset_2, y_offset;
+  PangoLayout *layout_one, *layout_two;
+  PangoRectangle layout_rect;
+
+  /* fetch common information */
+  context = gtk_widget_get_style_context (widget);
+  gd_two_lines_renderer_prepare_layouts (self, cell_area, widget, &layout_one, &layout_two);
+  gd_two_lines_renderer_get_size (cell, widget,
+                                  layout_one, layout_two,
+                                  NULL, NULL,
+                                  cell_area,
+                                  &x_offset_1, &x_offset_2, &y_offset);
+  gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
+
+  area = *cell_area;
+  area.x += xpad;
+  area.y += ypad;
+
+  /* now render the first layout */
+  pango_layout_get_pixel_extents (layout_one, NULL, &layout_rect);
+
+  render_area = area;
+  render_area.x += x_offset_1 - layout_rect.x;
+
+  gtk_render_layout (context, cr,
+                     render_area.x,
+                     render_area.y,
+                     layout_one);
+
+  /* render the second layout */
+  if (layout_two != NULL)
+    {
+      pango_layout_get_pixel_size (layout_one,
+                                   NULL, &line_one_height);
+
+      gtk_style_context_save (context);
+      gtk_style_context_add_class (context, "dim-label");
+
+      state = gtk_cell_renderer_get_state (cell, widget, flags);
+      gtk_style_context_set_state (context, state);
+
+      pango_layout_get_pixel_extents (layout_two, NULL, &layout_rect);
+
+      render_area = area;
+      render_area.x += x_offset_2 - layout_rect.x;
+      render_area.y += line_one_height;
+
+      gtk_render_layout (context, cr,
+                         render_area.x,
+                         render_area.y,
+                         layout_two);
+
+      gtk_style_context_restore (context);
+    }
+
+  g_clear_object (&layout_one);
+  g_clear_object (&layout_two);
+}
+
+static void
+gd_two_lines_renderer_get_preferred_width (GtkCellRenderer *cell,
+                                           GtkWidget       *widget,
+                                           gint            *minimum_size,
+                                           gint            *natural_size)
+{
+  PangoContext *context;
+  PangoFontMetrics *metrics;
+  PangoFontDescription *font_desc;
+  GtkStyleContext *style_context;
+  gint nat_width, min_width;
+  gint xpad, char_width, wrap_width, text_width;
+  gint width_chars, ellipsize_chars;
+
+  g_object_get (cell,
+                "xpad", &xpad,
+                "width-chars", &width_chars,
+                "wrap-width", &wrap_width,
+                NULL);
+  style_context = gtk_widget_get_style_context (widget);
+  gtk_cell_renderer_get_padding (cell, &xpad, NULL);
+
+  gd_two_lines_renderer_get_size (cell, widget,
+                                  NULL, NULL,
+                                  &text_width, NULL,
+                                  NULL, 
+                                  NULL, NULL, NULL);
+
+  /* Fetch the average size of a charachter */
+  context = gtk_widget_get_pango_context (widget);
+  gtk_style_context_get (style_context, 0, "font", &font_desc, NULL);
+  metrics = pango_context_get_metrics (context, font_desc,
+                                       pango_context_get_language (context));
+
+  char_width = pango_font_metrics_get_approximate_char_width (metrics);
+
+  pango_font_metrics_unref (metrics);
+  pango_font_description_free (font_desc);
+
+  /* enforce minimum width for ellipsized labels at ~3 chars */
+  ellipsize_chars = 3;
+
+  /* If no width-chars set, minimum for wrapping text will be the wrap-width */
+  if (wrap_width > -1)
+    min_width = xpad * 2 + MIN (text_width, wrap_width);
+  else
+    min_width = xpad * 2 +
+      MIN (text_width,
+           (PANGO_PIXELS (char_width) * MAX (width_chars, ellipsize_chars)));
+
+  if (width_chars > 0)
+    nat_width = xpad * 2 +
+      MAX ((PANGO_PIXELS (char_width) * width_chars), text_width);
+  else
+    nat_width = xpad * 2 + text_width;
+
+  nat_width = MAX (nat_width, min_width);
+
+  if (minimum_size)
+    *minimum_size = min_width;
+
+  if (natural_size)
+    *natural_size = nat_width;
+}
+
+static void
+gd_two_lines_renderer_get_preferred_height_for_width (GtkCellRenderer *cell,
+                                                      GtkWidget       *widget,
+                                                      gint             width,
+                                                      gint            *minimum_size,
+                                                      gint            *natural_size)
+{
+  GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (cell);
+  PangoLayout *layout_one, *layout_two;
+  gint text_height, wrap_width;
+  gint xpad, ypad;
+
+  gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
+  g_object_get (cell, "wrap-width", &wrap_width, NULL);
+  gd_two_lines_renderer_prepare_layouts (self, NULL, widget, &layout_one, &layout_two);
+
+  if (wrap_width != -1)
+    wrap_width = MIN (width - 2 * xpad, wrap_width);
+  else
+    wrap_width = width - 2 * xpad;
+
+  pango_layout_set_width (layout_one, wrap_width);
+  if (layout_two != NULL)
+    pango_layout_set_width (layout_two, wrap_width);
+
+  gd_two_lines_renderer_get_size (cell, widget,
+                                  layout_one, layout_two,
+                                  NULL, &text_height,
+                                  NULL, 
+                                  NULL, NULL, NULL);
+
+  text_height += 2 * ypad;
+
+  if (minimum_size != NULL)
+    *minimum_size = text_height;
+
+  if (natural_size != NULL)
+    *natural_size = text_height;
+
+  g_clear_object (&layout_one);
+  g_clear_object (&layout_two);
+}
+
+static void
+gd_two_lines_renderer_get_preferred_height (GtkCellRenderer *cell,
+                                            GtkWidget       *widget,
+                                            gint            *minimum_size,
+                                            gint            *natural_size)
+{
+  gint min_width;
+
+  gtk_cell_renderer_get_preferred_width (cell, widget, &min_width, NULL);
+  gd_two_lines_renderer_get_preferred_height_for_width (cell, widget, min_width,
+                                                        minimum_size, natural_size);
+}
+
+static void
+gd_two_lines_renderer_get_aligned_area (GtkCellRenderer      *cell,
+                                        GtkWidget            *widget,
+                                        GtkCellRendererState  flags,
+                                        const GdkRectangle   *cell_area,
+                                        GdkRectangle         *aligned_area)
+{
+  GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (cell);
+  gint x_offset, x_offset_1, x_offset_2, y_offset;
+  PangoLayout *layout_one, *layout_two;
+
+  /* fetch common information */
+  gd_two_lines_renderer_prepare_layouts (self, cell_area, widget, &layout_one, &layout_two);
+  gd_two_lines_renderer_get_size (cell, widget,
+                                  layout_one, layout_two,
+                                  &aligned_area->width, &aligned_area->height,
+                                  cell_area,
+                                  &x_offset_1, &x_offset_2, &y_offset);
+
+  x_offset = MIN (x_offset_1, x_offset_2);
+
+  aligned_area->x = cell_area->x + x_offset;
+  aligned_area->y = cell_area->y;
+
+  g_clear_object (&layout_one);
+  g_clear_object (&layout_two);
+}
+
+static void
+gd_two_lines_renderer_set_line_two (GdTwoLinesRenderer *self,
+                                    const gchar *line_two)
+{
+  if (g_strcmp0 (self->priv->line_two, line_two) == 0)
+    return;
+
+  g_free (self->priv->line_two);
+  self->priv->line_two = g_strdup (line_two);
+
+  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LINE_TWO]);
+}
+
+static void
+gd_two_lines_renderer_set_text_lines (GdTwoLinesRenderer *self,
+                                      gint text_lines)
+{
+  if (self->priv->text_lines == text_lines)
+    return;
+
+  self->priv->text_lines = text_lines;
+  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TEXT_LINES]);
+}
+
+static void
+gd_two_lines_renderer_set_property (GObject    *object,
+                                    guint       property_id,
+                                    const GValue     *value,
+                                    GParamSpec *pspec)
+{
+  GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (object);
+
+  switch (property_id)
+    {
+    case PROP_TEXT_LINES:
+      gd_two_lines_renderer_set_text_lines (self, g_value_get_int (value));
+      break;
+    case PROP_LINE_TWO:
+      gd_two_lines_renderer_set_line_two (self, g_value_get_string (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gd_two_lines_renderer_get_property (GObject    *object,
+                                    guint       property_id,
+                                    GValue     *value,
+                                    GParamSpec *pspec)
+{
+  GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (object);
+
+  switch (property_id)
+    {
+    case PROP_TEXT_LINES:
+      g_value_set_int (value, self->priv->text_lines);
+      break;
+    case PROP_LINE_TWO:
+      g_value_set_string (value, self->priv->line_two);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gd_two_lines_renderer_finalize (GObject *object)
+{
+  GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (object);
+
+  g_free (self->priv->line_two);
+
+  G_OBJECT_CLASS (gd_two_lines_renderer_parent_class)->finalize (object);
+}
+
+static void
+gd_two_lines_renderer_class_init (GdTwoLinesRendererClass *klass)
+{
+  GtkCellRendererClass *cclass = GTK_CELL_RENDERER_CLASS (klass);
+  GObjectClass *oclass = G_OBJECT_CLASS (klass);
+
+  cclass->render = gd_two_lines_renderer_render;
+  cclass->get_preferred_width = gd_two_lines_renderer_get_preferred_width;
+  cclass->get_preferred_height = gd_two_lines_renderer_get_preferred_height;
+  cclass->get_preferred_height_for_width = gd_two_lines_renderer_get_preferred_height_for_width;
+  cclass->get_aligned_area = gd_two_lines_renderer_get_aligned_area;
+
+  oclass->set_property = gd_two_lines_renderer_set_property;
+  oclass->get_property = gd_two_lines_renderer_get_property;
+  oclass->finalize = gd_two_lines_renderer_finalize;
+  
+  properties[PROP_TEXT_LINES] =
+    g_param_spec_int ("text-lines",
+                      "Lines of text",
+                      "The total number of lines to be displayed",
+                      2, G_MAXINT, 2,
+                      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_LINE_TWO] =
+    g_param_spec_string ("line-two",
+                         "Second line",
+                         "Second line",
+                         NULL,
+                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  g_type_class_add_private (klass, sizeof (GdTwoLinesRendererPrivate));
+  g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
+}
+
+static void
+gd_two_lines_renderer_init (GdTwoLinesRenderer *self)
+{
+  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GD_TYPE_TWO_LINES_RENDERER,
+                                            GdTwoLinesRendererPrivate);
+}
+
+GtkCellRenderer *
+gd_two_lines_renderer_new (void)
+{
+  return g_object_new (GD_TYPE_TWO_LINES_RENDERER, NULL);
+}
diff --git a/cut-n-paste/libgd/gd-two-lines-renderer.h b/cut-n-paste/libgd/gd-two-lines-renderer.h
new file mode 100644
index 0000000..23bf70f
--- /dev/null
+++ b/cut-n-paste/libgd/gd-two-lines-renderer.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2011 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License 
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Cosimo Cecchi <cosimoc redhat com>
+ *
+ */
+
+#ifndef _GD_TWO_LINES_RENDERER_H
+#define _GD_TWO_LINES_RENDERER_H
+
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GD_TYPE_TWO_LINES_RENDERER gd_two_lines_renderer_get_type()
+
+#define GD_TWO_LINES_RENDERER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+   GD_TYPE_TWO_LINES_RENDERER, GdTwoLinesRenderer))
+
+#define GD_TWO_LINES_RENDERER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), \
+   GD_TYPE_TWO_LINES_RENDERER, GdTwoLinesRendererClass))
+
+#define GD_IS_TWO_LINES_RENDERER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+   GD_TYPE_TWO_LINES_RENDERER))
+
+#define GD_IS_TWO_LINES_RENDERER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+   GD_TYPE_TWO_LINES_RENDERER))
+
+#define GD_TWO_LINES_RENDERER_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+   GD_TYPE_TWO_LINES_RENDERER, GdTwoLinesRendererClass))
+
+typedef struct _GdTwoLinesRenderer GdTwoLinesRenderer;
+typedef struct _GdTwoLinesRendererClass GdTwoLinesRendererClass;
+typedef struct _GdTwoLinesRendererPrivate GdTwoLinesRendererPrivate;
+
+struct _GdTwoLinesRenderer
+{
+  GtkCellRendererText parent;
+
+  GdTwoLinesRendererPrivate *priv;
+};
+
+struct _GdTwoLinesRendererClass
+{
+  GtkCellRendererTextClass parent_class;
+};
+
+GType gd_two_lines_renderer_get_type (void) G_GNUC_CONST;
+
+GtkCellRenderer *gd_two_lines_renderer_new (void);
+
+G_END_DECLS
+
+#endif /* _GD_TWO_LINES_RENDERER_H */
diff --git a/shell/Makefile.am b/shell/Makefile.am
index 6266ce3..3d3d3e7 100644
--- a/shell/Makefile.am
+++ b/shell/Makefile.am
@@ -97,6 +97,7 @@ evince_CPPFLAGS = \
        -I$(top_srcdir) \
        -I$(top_builddir) \
        -I$(top_srcdir)/cut-n-paste/gimpcellrenderertoggle \
+       -I$(top_srcdir)/cut-n-paste/libgd/                      \
        -I$(top_srcdir)/libdocument \
        -I$(top_builddir)/libdocument \
        -I$(top_srcdir)/libview \
@@ -119,6 +120,7 @@ endif
 
 evince_LDADD=                                                                          \
        $(top_builddir)/cut-n-paste/gimpcellrenderertoggle/libgimpcellrenderertoggle.la \
+       $(top_builddir)/cut-n-paste/libgd/libgd.la                                      \
        $(top_builddir)/properties/libevproperties.la                                   \
        $(top_builddir)/libdocument/libevdocument3.la                                   \
        $(top_builddir)/libview/libevview3.la                                           \


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