[the-board] [nautilus] Initial code for The Board's nautilus extension



commit 228aedcdf9c14f2dc2efa50c2528f06a7d16ed2a
Author: Lucas Rocha <lucasr gnome org>
Date:   Fri Nov 26 11:36:06 2010 +0000

    [nautilus] Initial code for The Board's nautilus extension
    
    For now, it only allows adding photos to The Board.

 configure.ac               |   24 +++
 po/POTFILES.in             |    1 +
 src/Makefile-nautilus.am   |   16 ++
 src/Makefile.am            |    6 +
 src/nautilus/tb-module.c   |   35 ++++
 src/nautilus/tb-nautilus.c |  442 ++++++++++++++++++++++++++++++++++++++++++++
 src/nautilus/tb-nautilus.h |   34 ++++
 7 files changed, 558 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 0e9e533..1f8778b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -76,6 +76,29 @@ else
     HAVE_LIBNOTIFY_RESULT="no"
 fi
 
+AC_ARG_ENABLE([nautilus],
+              AC_HELP_STRING([--enable-nautilus],[enable nautilus support]),,
+              [enable_nautilus=yes])
+
+HAVE_NAUTILUS=0
+
+if test x$enable_nautilus = xyes ; then
+   PKG_CHECK_MODULES([NAUTILUS],
+                     [glib-2.0 >= 2.27.4 gdk-pixbuf-2.0 libnautilus-extension],
+                     [HAVE_NAUTILUS=1],[HAVE_NAUTILUS=0])
+fi
+
+if test x$HAVE_NAUTILUS = x1 ; then
+    HAVE_NAUTILUS_RESULT="yes"
+else
+    HAVE_NAUTILUS_RESULT="no"
+fi
+
+AM_CONDITIONAL(BUILD_NAUTILUS, [test "$HAVE_NAUTILUS" = 1])
+
+NAUTILUSDIR=`$PKG_CONFIG --variable=extensiondir libnautilus-extension`
+AC_SUBST(NAUTILUSDIR)
+
 GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0`
 AC_SUBST(GLIB_MKENUMS)
 
@@ -106,6 +129,7 @@ echo "
         prefix:    ${prefix}
         compiler:  ${CC}
 
+        nautilus:  $HAVE_NAUTILUS_RESULT
         libnotify: $HAVE_LIBNOTIFY_RESULT
 
         Now type 'make' to build $PACKAGE
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 3a2db66..9cb56a9 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -11,3 +11,4 @@ src/js/ui/mainWindow.js
 src/js/ui/pageButton.js
 src/js/ui/toolBoxBackgrounds.js
 src/js/ui/toolBoxThings.js
+src/nautilus/the-board-nautilus.c
diff --git a/src/Makefile-nautilus.am b/src/Makefile-nautilus.am
new file mode 100644
index 0000000..933607d
--- /dev/null
+++ b/src/Makefile-nautilus.am
@@ -0,0 +1,16 @@
+nautilus_LTLIBRARIES += libnautilus-the-board.la
+
+libnautilus_the_board_la_LDFLAGS = \
+    -module -avoid-version -no-undefined \
+    -export-symbols-regex 'nautilus_module_.*'
+
+libnautilus_the_board_la_LIBADD = $(NAUTILUS_LIBS)
+
+libnautilus_the_board_la_CFLAGS = \
+    $(NAUTILUS_CFLAGS) \
+    -DTHE_BOARD_LOCALEDIR=\""$(localedir)"\"
+
+libnautilus_the_board_la_SOURCES = \
+    nautilus/tb-module.c \
+    nautilus/tb-nautilus.h \
+    nautilus/tb-nautilus.c
diff --git a/src/Makefile.am b/src/Makefile.am
index ef926f3..a4c3aa6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -15,12 +15,14 @@ AM_CPPFLAGS = \
 girdir = $(datadir)/gir-1.0
 typelibdir = $(libdir)/girepository-1.0
 localedir = $(datadir)/locale
+nautilusdir = $(NAUTILUSDIR)
 
 # These are added to using += in the included files
 libexec_PROGRAMS =
 bin_SCRIPTS =
 noinst_SCRIPTS =
 lib_LTLIBRARIES =
+nautilus_LTLIBRARIES =
 gir_DATA =
 typelib_DATA =
 EXTRA_DIST =
@@ -45,6 +47,10 @@ include $(INTROSPECTION_MAKEFILE)
 include Makefile-js.am
 include Makefile-tb.am
 
+if BUILD_NAUTILUS
+include Makefile-nautilus.am
+endif
+
 gir_DATA += $(INTROSPECTION_GIRS)
 typelib_DATA += $(gir_DATA:.gir=.typelib)
 
diff --git a/src/nautilus/tb-module.c b/src/nautilus/tb-module.c
new file mode 100644
index 0000000..8103181
--- /dev/null
+++ b/src/nautilus/tb-module.c
@@ -0,0 +1,35 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib/gi18n-lib.h>
+
+#include <libnautilus-extension/nautilus-extension-types.h>
+#include <libnautilus-extension/nautilus-column-provider.h>
+
+#include "tb-nautilus.h"
+
+void
+nautilus_module_initialize (GTypeModule*module)
+{
+  tb_nautilus_register_type (module);
+
+  bindtextdomain (GETTEXT_PACKAGE, THE_BOARD_LOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+}
+
+void
+nautilus_module_shutdown (void)
+{
+}
+
+void 
+nautilus_module_list_types (const GType **types,
+                            int          *num_types)
+{
+  static GType type_list[1];
+
+  type_list[0] = TB_TYPE_NAUTILUS;
+  *types = type_list;
+  *num_types = 1;
+}
diff --git a/src/nautilus/tb-nautilus.c b/src/nautilus/tb-nautilus.c
new file mode 100644
index 0000000..53bb647
--- /dev/null
+++ b/src/nautilus/tb-nautilus.c
@@ -0,0 +1,442 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include <gio/gio.h>
+#include <glib/gi18n-lib.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#include <libnautilus-extension/nautilus-file-info.h>
+#include <libnautilus-extension/nautilus-menu-provider.h>
+#include <libnautilus-extension/nautilus-extension-types.h>
+
+#include "tb-nautilus.h"
+
+static GObjectClass *parent_class;
+
+#define TB_NAUTILUS_GET_PRIVATE(o) \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((o), TB_TYPE_NAUTILUS, TbNautilusPrivate))
+
+#define THE_BOARD_DBUS_NAME  "org.gnome.TheBoard"
+#define THE_BOARD_DBUS_PATH  "/org/gnome/TheBoard"
+#define THE_BOARD_DBUS_IFACE "org.gnome.TheBoard"
+
+struct _TbNautilusPrivate
+{
+  GDBusProxy *proxy;
+  GCancellable *proxy_cancellable;
+  guint watcher_id;
+};
+
+typedef struct
+{
+  gboolean is_image;
+} FileMimeInfo;
+
+static void
+tb_nautilus_on_photos_added (GObject      *object,
+                             GAsyncResult *result,
+                             gpointer      user_data)
+{
+  TbNautilusPrivate *priv = TB_NAUTILUS_GET_PRIVATE (user_data);
+  GVariant *result_variant;
+  GError *error;
+
+  error = NULL;
+
+  result_variant = g_dbus_proxy_call_finish (G_DBUS_PROXY (object),
+                                             result, &error);
+
+  if (error)
+    {
+      g_warning ("Could not call The Board method: %s", error->message);
+      g_error_free (error);
+      return;
+    }
+
+  g_variant_unref (result_variant);
+}
+
+static void
+tb_nautilus_add_photos_to_the_board (TbNautilus *tb,
+                                     GList *images)
+{
+  TbNautilusPrivate *priv = TB_NAUTILUS_GET_PRIVATE (tb);
+  GVariantBuilder array;
+  GError *error;
+  GList *scan;
+
+  g_variant_builder_init (&array,
+                          G_VARIANT_TYPE_ARRAY);
+
+  for (scan = images; scan; scan = scan->next)
+    {
+      GFile *image_location = scan->data;
+      GVariantBuilder photo_array;
+      char *filename;
+      char *path;
+
+      g_variant_builder_init (&photo_array,
+                              G_VARIANT_TYPE_ARRAY);
+
+      g_variant_builder_add (&photo_array,
+                             "{sv}",
+                             "id",
+                             g_variant_new_string ("photo"));
+
+      path = g_file_get_path (image_location);
+
+      g_variant_builder_add (&photo_array,
+                             "{sv}",
+                             "imageFilename",
+                             g_variant_new_string (path));
+
+      g_free (path);
+
+      filename = g_file_get_basename (image_location);
+
+      g_variant_builder_add (&photo_array,
+                             "{sv}",
+                             "text",
+                             g_variant_new_string (filename));
+
+      g_free (filename);
+
+      g_variant_builder_add_value (&array,
+                                   g_variant_builder_end (&photo_array));
+    }
+
+  g_dbus_proxy_call (priv->proxy,
+                     "addThings",
+                     g_variant_new ("(aa{sv})", &array),
+                     G_DBUS_CALL_FLAGS_NONE,
+                     -1,
+                     NULL,
+                     tb_nautilus_on_photos_added,
+                     tb);
+}
+
+static void
+add_to_board_callback (NautilusMenuItem *item,
+                       gpointer          user_data)
+{
+  TbNautilus *tb = TB_NAUTILUS (user_data);
+  GList *files;
+  GList *scan;
+  GList *images = NULL;
+
+  files = g_object_get_data (G_OBJECT (item), "files");
+
+  for (scan = files; scan; scan = scan->next)
+    {
+      NautilusFileInfo *file = scan->data;
+      GFile *location = nautilus_file_info_get_location (file);
+
+      images = g_list_append (images, location);
+    }
+
+  tb_nautilus_add_photos_to_the_board (tb, images);
+
+  for (scan = images; scan; scan = scan->next)
+    {
+      GFile *location = scan->data;;
+      g_object_unref (location);
+    }
+}
+
+static FileMimeInfo
+tb_nautilus_get_file_mime_info (NautilusFileInfo *file)
+{
+  FileMimeInfo file_mime_info;
+  GSList *formats;
+  GSList *scan;
+
+  file_mime_info.is_image = TRUE;
+
+  formats = gdk_pixbuf_get_formats();
+
+  for (scan = formats; scan; scan = scan->next)
+    {
+      GdkPixbufFormat *format; 
+      char **mime_types;
+      int i;
+
+      format = formats->data; 
+      mime_types = gdk_pixbuf_format_get_mime_types(format);
+
+      for (i = 0; i < G_N_ELEMENTS(mime_types); ++i) {
+        if (nautilus_file_info_is_mime_type (file, mime_types[i]))
+          {
+            g_strfreev(mime_types);
+            goto out;
+          }
+      }
+
+      g_strfreev(mime_types);
+    }
+
+  file_mime_info.is_image = FALSE;
+
+out:
+  g_slist_free(formats);
+
+  return file_mime_info;
+}
+
+static gboolean
+tb_nautilus_unsupported_scheme (NautilusFileInfo *file)
+{
+  gboolean result = FALSE;
+  GFile *location;
+  char *scheme;
+
+  location = nautilus_file_info_get_location (file);
+  scheme = g_file_get_uri_scheme (location);
+
+  if (scheme != NULL)
+    {
+      const char *unsupported[] = { "trash", "computer", NULL };
+      int i;
+
+      for (i = 0; unsupported[i] != NULL; i++)
+        if (strcmp (scheme, unsupported[i]) == 0)
+          result = TRUE;
+    }
+
+  g_free (scheme);
+  g_object_unref (location);
+
+  return result;
+}
+
+static GList *
+tb_nautilus_get_file_items (NautilusMenuProvider *provider,
+                            GtkWidget *window,
+                            GList *files)
+{
+  TbNautilus *tb = TB_NAUTILUS (provider);
+  TbNautilusPrivate *priv = TB_NAUTILUS_GET_PRIVATE (tb);
+  GList *items = NULL;
+  GList *scan;
+  gboolean all_images = TRUE;
+
+  if (priv->proxy == NULL)
+    return NULL;
+
+  if (files == NULL)
+    return NULL;
+
+  if (tb_nautilus_unsupported_scheme ((NautilusFileInfo *) files->data))
+    return NULL;
+
+  for (scan = files; scan; scan = scan->next)
+    {
+      NautilusFileInfo *file = scan->data;
+      FileMimeInfo file_mime_info;
+
+      file_mime_info = tb_nautilus_get_file_mime_info (file);
+
+      if (!file_mime_info.is_image) {
+          all_images = FALSE;
+          break;
+      }
+    }
+
+  if (all_images)
+    {
+      NautilusMenuItem *item;
+
+      item = nautilus_menu_item_new ("TbNautilus::add_to_board",
+                                     _("Add to The Board"),
+                                     _("Add selected file to the board"),
+                                     "the-board");
+
+      g_signal_connect (item,
+                        "activate",
+                        G_CALLBACK (add_to_board_callback),
+                        tb);
+
+      g_object_set_data_full (G_OBJECT (item),
+                              "files",
+                              nautilus_file_info_list_copy (files),
+                              (GDestroyNotify) nautilus_file_info_list_free);
+
+      items = g_list_append (items, item);
+    }
+
+  return items;
+}
+
+static void
+tb_nautilus_menu_provider_iface_init (NautilusMenuProviderIface *iface)
+{
+  iface->get_file_items = tb_nautilus_get_file_items;
+}
+
+static void
+tb_nautilus_on_proxy_created (GObject      *object,
+                              GAsyncResult *result,
+                              gpointer      user_data)
+{
+  TbNautilusPrivate *priv = TB_NAUTILUS_GET_PRIVATE (user_data);
+  GError *error;
+
+  if (g_cancellable_is_cancelled (priv->proxy_cancellable))
+    {
+      g_warning ("The Board proxy loading has been cancelled");
+      goto out;
+    }
+
+  error = NULL;
+
+  priv->proxy = g_dbus_proxy_new_finish (result, &error);
+
+  if (error)
+    {
+      g_warning ("Could not create The Board proxy: %s", error->message);
+      g_error_free (error);
+    }
+
+out:
+  g_object_unref (priv->proxy_cancellable);
+  priv->proxy_cancellable = NULL;
+}
+
+static void
+tb_nautilus_on_name_appeared(GDBusConnection *connection,
+                             const char      *name,
+                             const char      *name_owner,
+                             gpointer         user_data)
+{
+  TbNautilus *tb = TB_NAUTILUS (user_data);
+  TbNautilusPrivate *priv = TB_NAUTILUS_GET_PRIVATE (tb);
+
+  /* We're loading proxy, don't do anything */
+  if (priv->proxy_cancellable)
+    return;
+
+  priv->proxy_cancellable = g_cancellable_new ();
+
+  g_dbus_proxy_new (connection,
+                    G_DBUS_PROXY_FLAGS_NONE,
+                    NULL,
+                    THE_BOARD_DBUS_NAME,
+                    THE_BOARD_DBUS_PATH,
+                    THE_BOARD_DBUS_IFACE,
+                    priv->proxy_cancellable,
+                    tb_nautilus_on_proxy_created,
+                    tb);
+}
+
+static void
+tb_nautilus_on_name_vanished(GDBusConnection *connection,
+                             const char      *name,
+                             gpointer         user_data)
+{
+  TbNautilusPrivate *priv = TB_NAUTILUS_GET_PRIVATE (user_data);
+
+  if (priv->proxy_cancellable)
+    {
+      g_cancellable_cancel (priv->proxy_cancellable);
+    }
+
+  if (priv->proxy)
+    {
+      g_object_unref (priv->proxy);
+      priv->proxy = NULL;
+    }
+}
+
+static void
+tb_nautilus_instance_init (TbNautilus *tb)
+{
+  TbNautilusPrivate *priv = tb->priv = TB_NAUTILUS_GET_PRIVATE (tb);
+
+  priv->proxy = NULL;
+
+  priv->watcher_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
+                                       THE_BOARD_DBUS_NAME,
+                                       G_BUS_NAME_WATCHER_FLAGS_NONE,
+                                       tb_nautilus_on_name_appeared,
+                                       tb_nautilus_on_name_vanished,
+                                       tb,
+                                       NULL);
+}
+
+static void
+tb_nautilus_dispose (GObject *object)
+{
+  TbNautilusPrivate *priv = TB_NAUTILUS_GET_PRIVATE (object);
+
+  if (priv->watcher_id)
+    {
+      g_bus_unwatch_name (priv->watcher_id);
+      priv->watcher_id = 0;
+    }
+
+  if (priv->proxy_cancellable)
+    {
+      g_cancellable_cancel (priv->proxy_cancellable);
+    }
+
+  if (priv->proxy)
+    {
+      g_object_unref (priv->proxy);
+      priv->proxy = NULL;
+    }
+
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+tb_nautilus_class_init (TbNautilusClass *klass)
+{
+  parent_class = g_type_class_peek_parent (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = tb_nautilus_dispose;
+
+  g_type_class_add_private (klass, sizeof (TbNautilusPrivate));
+}
+
+static GType tb_type = 0;
+
+GType
+tb_nautilus_get_type (void)
+{
+  return tb_type;
+}
+
+void
+tb_nautilus_register_type (GTypeModule *module)
+{
+  static const GTypeInfo info = {
+    sizeof (TbNautilusClass),
+    (GBaseInitFunc) NULL,
+    (GBaseFinalizeFunc) NULL,
+    (GClassInitFunc) tb_nautilus_class_init,
+    NULL,
+    NULL,
+    sizeof (TbNautilus),
+    0,
+    (GInstanceInitFunc) tb_nautilus_instance_init,
+  };
+
+  static const GInterfaceInfo menu_provider_iface_info = {
+    (GInterfaceInitFunc) tb_nautilus_menu_provider_iface_init,
+    NULL,
+    NULL
+  };
+
+  tb_type = g_type_module_register_type (module,
+                                         G_TYPE_OBJECT,
+                                         "TbNautilus",
+                                         &info, 0);
+
+  g_type_module_add_interface (module,
+                               tb_type,
+                               NAUTILUS_TYPE_MENU_PROVIDER,
+                               &menu_provider_iface_info);
+}
diff --git a/src/nautilus/tb-nautilus.h b/src/nautilus/tb-nautilus.h
new file mode 100644
index 0000000..a1d5113
--- /dev/null
+++ b/src/nautilus/tb-nautilus.h
@@ -0,0 +1,34 @@
+#ifndef TB_NAUTILUS_H
+#define TB_NAUTILUS_H 
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define TB_TYPE_NAUTILUS  (tb_nautilus_get_type ())
+#define TB_NAUTILUS(o)    (G_TYPE_CHECK_INSTANCE_CAST ((o), TB_TYPE_NAUTILUS, TbNautilus))
+#define TB_IS_NAUTILUS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TB_TYPE_NAUTILUS))
+
+typedef struct _TbNautilus        TbNautilus;
+typedef struct _TbNautilusClass   TbNautilusClass;
+typedef struct _TbNautilusPrivate TbNautilusPrivate;
+
+struct _TbNautilus
+{
+  GObject parent;
+
+  TbNautilusPrivate *priv;
+};
+
+struct _TbNautilusClass
+{
+  GObjectClass parent_class;
+};
+
+GType tb_nautilus_get_type      (void);
+
+void  tb_nautilus_register_type (GTypeModule *module);
+
+G_END_DECLS
+
+#endif /* TB_NAUTILUS_H */



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