[the-board] [nautilus] Initial code for The Board's nautilus extension
- From: Lucas Rocha <lucasr src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [the-board] [nautilus] Initial code for The Board's nautilus extension
- Date: Sat, 27 Nov 2010 23:24:52 +0000 (UTC)
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]