[tracker/nautilus-extension] Added a new Nautilus extension for managing tags.
- From: Debarshi Ray <debarshir src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [tracker/nautilus-extension] Added a new Nautilus extension for managing tags.
- Date: Wed, 18 Nov 2009 13:53:37 +0000 (UTC)
commit b249428d6e18745f45bca84ba2edf7a021122697
Author: Debarshi Ray <debarshir src gnome org>
Date: Wed Nov 18 14:46:43 2009 +0200
Added a new Nautilus extension for managing tags.
It provides a menu items and a property page for adding or removing
tags, and attaching or detaching tags from files.
This replaces the older (and broken) extension written in Python, and
can be enabled using --enable-nautilus-extension.
Makefile.am | 2 +-
configure.ac | 46 ++
extensions/Makefile.am | 7 +
extensions/nautilus-extension/Makefile.am | 28 +
.../nautilus-extension/tracker-tags-add-dialog.c | 131 +++++
.../nautilus-extension/tracker-tags-add-dialog.h | 53 ++
.../nautilus-extension/tracker-tags-extension.c | 305 +++++++++++
extensions/nautilus-extension/tracker-tags-utils.c | 104 ++++
extensions/nautilus-extension/tracker-tags-utils.h | 28 +
extensions/nautilus-extension/tracker-tags-view.c | 542 ++++++++++++++++++++
extensions/nautilus-extension/tracker-tags-view.h | 52 ++
po/POTFILES.in | 2 +
python/nautilus/README | 15 -
python/nautilus/tracker-tags-tab.py | 195 -------
14 files changed, 1299 insertions(+), 211 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index b120c48..2fb4f8d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
include $(top_srcdir)/Makefile.decl
-SUBDIRS = data src docs po python utils
+SUBDIRS = data src docs extensions po python utils
if HAVE_UNIT_TESTS
SUBDIRS += tests
diff --git a/configure.ac b/configure.ac
index 29cf706..7945757 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1352,6 +1352,46 @@ fi
AM_CONDITIONAL(HAVE_EVOLUTION_PLUGIN, test "$have_evolution_plugin" = "yes")
+####################################################################
+# Enable Nautilus extension support?
+####################################################################
+
+AC_ARG_ENABLE([nautilus-extension],
+ AS_HELP_STRING([--enable-nautilus-extension],
+ [Enable the nautilus extension [[default=no]]]),
+ [enable_nautilus_extension=yes],
+ [enable_nautilus_extension=no])
+
+AM_CONDITIONAL([ENABLE_NAUTILUS_EXTENSION], [test "x$enable_nautilus_extension" != "xno"])
+
+AC_ARG_WITH([nautilus-extensions-dir],
+ AS_HELP_STRING([--with-nautilus-extensions-dir],
+ [Path to Nautilus extensions directory]))
+
+NAUTILUS_EXTENSION_INSTALL_DIR="/dev/null"
+
+if test "x$enable_nautilus_extension" != "xno"; then
+ PKG_CHECK_MODULES([NAUTILUS_EXTENSION],
+ [libnautilus-extension],
+ [have_nautilus_extension=yes],
+ [have_nautilus_extension=no])
+
+ if test "x$have_nautilus_extension" = "xyes"; then
+ if test "x$with_nautilus_extensions_dir" = "x"; then
+ nautilus_extensions_dir=`$PKG_CONFIG --variable=extensiondir libnautilus-extension`
+ else
+ nautilus_extensions_dir="$with_nautilus_extensions_dir"
+ fi
+ NAUTILUS_EXTENSION_INSTALL_DIR="$nautilus_extensions_dir"
+
+ AC_DEFINE([HAVE_NAUTILUS_EXTENSION], [], [Define if we have libnautilus-extension])
+ else
+ AC_MSG_ERROR([Couldn't find Nautilus extension requirements (libnautilus-extension).])
+ fi
+fi
+
+AC_SUBST([NAUTILUS_EXTENSION_INSTALL_DIR])
+
####################################################################
# Include/Exclude functional tests
@@ -1443,6 +1483,8 @@ AC_CONFIG_FILES([
docs/reference/libtracker-common/version.xml
docs/reference/libtracker-miner/Makefile
docs/reference/libtracker-miner/version.xml
+ extensions/Makefile
+ extensions/nautilus-extension/Makefile
Makefile
po/Makefile.in
python/deskbar-handler/Makefile
@@ -1551,6 +1593,10 @@ Metadata Extractors:
Support MP3 album art: $selected_for_albumart
Support playlists (w/ Totem): $have_playlist
+Extensions:
+
+ Nautilus extension: $enable_nautilus_extension
+
Plugins:
Evolution plugin (data-push): $enable_evolution_miner
diff --git a/extensions/Makefile.am b/extensions/Makefile.am
new file mode 100644
index 0000000..7f011f6
--- /dev/null
+++ b/extensions/Makefile.am
@@ -0,0 +1,7 @@
+include $(top_srcdir)/Makefile.decl
+
+SUBDIRS =
+
+if ENABLE_NAUTILUS_EXTENSION
+SUBDIRS += nautilus-extension
+endif
diff --git a/extensions/nautilus-extension/Makefile.am b/extensions/nautilus-extension/Makefile.am
new file mode 100644
index 0000000..cd98dc5
--- /dev/null
+++ b/extensions/nautilus-extension/Makefile.am
@@ -0,0 +1,28 @@
+include $(top_srcdir)/Makefile.decl
+
+INCLUDES = \
+ -I$(top_srcdir)/src \
+ $(GCOV_CFLAGS) \
+ $(WARN_CFLAGS) \
+ $(NAUTILUS_EXTENSION_CFLAGS) \
+ $(TRACKER_APPS_CFLAGS)
+
+nautilus_extensiondir = $(NAUTILUS_EXTENSION_INSTALL_DIR)
+
+nautilus_extension_LTLIBRARIES = libnautilus-tracker-tags.la
+
+libnautilus_tracker_tags_la_SOURCES = \
+ tracker-tags-add-dialog.c \
+ tracker-tags-add-dialog.h \
+ tracker-tags-extension.c \
+ tracker-tags-utils.c \
+ tracker-tags-utils.h \
+ tracker-tags-view.c \
+ tracker-tags-view.h
+
+libnautilus_tracker_tags_la_LDFLAGS = -module -avoid-version
+libnautilus_tracker_tags_la_LIBADD = \
+ $(top_builddir)/src/libtracker-client/libtracker-client- TRACKER_API_VERSION@.la \
+ $(GCOV_LIBS) \
+ $(NAUTILUS_EXTENSION_LIBS) \
+ $(TRACKER_APPS_LIBS)
diff --git a/extensions/nautilus-extension/tracker-tags-add-dialog.c b/extensions/nautilus-extension/tracker-tags-add-dialog.c
new file mode 100644
index 0000000..6b0b442
--- /dev/null
+++ b/extensions/nautilus-extension/tracker-tags-add-dialog.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2009 Debarshi Ray <debarshir src gnome org>
+ *
+ * This library 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.
+ *
+ * This library 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <glib/gi18n.h>
+
+#include "tracker-tags-add-dialog.h"
+
+struct _TrackerTagsAddDialogPrivate
+{
+ GtkWidget *entry;
+};
+
+G_DEFINE_TYPE (TrackerTagsAddDialog, tracker_tags_add_dialog, GTK_TYPE_DIALOG)
+
+#define TRACKER_TAGS_ADD_DIALOG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), TRACKER_TYPE_TAGS_ADD_DIALOG, TrackerTagsAddDialogPrivate))
+
+static void
+tracker_tags_add_dialog_entry_changed_cb (GtkEditable *editable, gpointer user_data)
+{
+ GtkDialog *const add_dialog = GTK_DIALOG (user_data);
+ GtkEntry *const entry = GTK_ENTRY (editable);
+
+ if (0 == gtk_entry_get_text_length (entry))
+ gtk_dialog_set_response_sensitive (add_dialog, GTK_RESPONSE_OK, FALSE);
+ else
+ gtk_dialog_set_response_sensitive (add_dialog, GTK_RESPONSE_OK, TRUE);
+}
+
+void
+tracker_tags_add_dialog_register_type (GTypeModule *module)
+{
+ tracker_tags_add_dialog_get_type ();
+}
+
+static void
+tracker_tags_add_dialog_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (tracker_tags_add_dialog_parent_class)->finalize (object);
+}
+
+static void
+tracker_tags_add_dialog_response (GtkDialog *dialog, gint response_id)
+{
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+static void
+tracker_tags_add_dialog_class_init (TrackerTagsAddDialogClass *klass)
+{
+ GObjectClass *const gobject_class = G_OBJECT_CLASS (klass);
+ GtkDialogClass *const dialog_class = GTK_DIALOG_CLASS (klass);
+
+ gobject_class->finalize = tracker_tags_add_dialog_finalize;
+ dialog_class->response = tracker_tags_add_dialog_response;
+
+ g_type_class_add_private (gobject_class, sizeof (TrackerTagsAddDialogPrivate));
+
+ tracker_tags_add_dialog_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+tracker_tags_add_dialog_init (TrackerTagsAddDialog *add_dialog)
+{
+ TrackerTagsAddDialogPrivate *const priv = TRACKER_TAGS_ADD_DIALOG_GET_PRIVATE (add_dialog);
+ GtkWidget *action_area;
+ GtkWidget *dialog;
+ GtkWidget *hbox;
+ GtkWidget *label;
+ GtkWidget *vbox;
+
+ add_dialog->priv = priv;
+
+ gtk_container_set_border_width (GTK_CONTAINER (add_dialog), 5);
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (add_dialog), TRUE);
+ gtk_window_set_modal (GTK_WINDOW (add_dialog), TRUE);
+ gtk_window_set_title (GTK_WINDOW (add_dialog), N_("Add Tag"));
+ gtk_window_set_resizable (GTK_WINDOW (add_dialog), FALSE);
+ gtk_dialog_set_has_separator (GTK_DIALOG (add_dialog), FALSE);
+ gtk_dialog_add_button (GTK_DIALOG (add_dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ gtk_dialog_add_button (GTK_DIALOG (add_dialog), GTK_STOCK_OK, GTK_RESPONSE_OK);
+ gtk_dialog_set_default_response (GTK_DIALOG (add_dialog), GTK_RESPONSE_OK);
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (add_dialog), GTK_RESPONSE_OK, FALSE);
+
+ action_area = gtk_dialog_get_action_area (GTK_DIALOG (add_dialog));
+ gtk_container_set_border_width (GTK_CONTAINER (action_area), 5);
+ gtk_box_set_spacing (GTK_BOX (action_area), 6);
+
+ vbox = gtk_dialog_get_content_area (GTK_DIALOG (add_dialog));
+ gtk_box_set_spacing (GTK_BOX (vbox), 2);
+
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
+
+ label = gtk_label_new_with_mnemonic (N_("_Tag label:"));
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+
+ add_dialog->priv->entry = gtk_entry_new ();
+ gtk_box_pack_start (GTK_BOX (hbox), add_dialog->priv->entry, TRUE, TRUE, 0);
+ g_signal_connect (add_dialog->priv->entry, "changed", G_CALLBACK (tracker_tags_add_dialog_entry_changed_cb), add_dialog);
+
+ gtk_widget_show_all (vbox);
+}
+
+GtkWidget *
+tracker_tags_add_dialog_new (void)
+{
+ return GTK_WIDGET (g_object_new (TRACKER_TYPE_TAGS_ADD_DIALOG, NULL));
+}
+
+const gchar *
+tracker_tags_add_dialog_get_text (TrackerTagsAddDialog *add_dialog)
+{
+ return gtk_entry_get_text (GTK_ENTRY (add_dialog->priv->entry));
+}
diff --git a/extensions/nautilus-extension/tracker-tags-add-dialog.h b/extensions/nautilus-extension/tracker-tags-add-dialog.h
new file mode 100644
index 0000000..bc813e5
--- /dev/null
+++ b/extensions/nautilus-extension/tracker-tags-add-dialog.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2009 Debarshi Ray <debarshir src gnome org>
+ *
+ * This library 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.
+ *
+ * This library 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef TRACKER_TAGS_ADD_DIALOG_H
+#define TRACKER_TAGS_ADD_DIALOG_H
+
+#include <gtk/gtk.h>
+
+#define TRACKER_TYPE_TAGS_ADD_DIALOG (tracker_tags_add_dialog_get_type ())
+#define TRACKER_TAGS_ADD_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRACKER_TYPE_TAGS_ADD_DIALOG, TrackerTagsAddDialog))
+#define TRACKER_TAGS_ADD_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TRACKER_TYPE_TAGS_ADD_DIALOG, TrackerTagsAddDialogClass))
+#define TRACKER_IS_TAGS_ADD_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRACKER_TYPE_TAGS_ADD_DIALOG))
+#define TRACKER_IS_TAGS_ADD_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TRACKER_TYPE_TAGS_ADD_DIALOG))
+
+typedef struct _TrackerTagsAddDialogPrivate TrackerTagsAddDialogPrivate;
+
+typedef struct _TrackerTagsAddDialog TrackerTagsAddDialog;
+typedef struct _TrackerTagsAddDialogClass TrackerTagsAddDialogClass;
+
+struct _TrackerTagsAddDialog
+{
+ GtkDialog parent;
+ TrackerTagsAddDialogPrivate *priv;
+};
+
+struct _TrackerTagsAddDialogClass
+{
+ GtkDialogClass parent;
+};
+
+GType tracker_tags_add_dialog_get_type (void);
+void tracker_tags_add_dialog_register_type (GTypeModule *module);
+
+GtkWidget *tracker_tags_add_dialog_new (void);
+const gchar *tracker_tags_add_dialog_get_text (TrackerTagsAddDialog *add_dialog);
+
+#endif /* TRACKER_TAGS_ADD_DIALOG_H */
diff --git a/extensions/nautilus-extension/tracker-tags-extension.c b/extensions/nautilus-extension/tracker-tags-extension.c
new file mode 100644
index 0000000..ccd462d
--- /dev/null
+++ b/extensions/nautilus-extension/tracker-tags-extension.c
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2009 Debarshi Ray <debarshir src gnome org>
+ *
+ * This library 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.
+ *
+ * This library 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <gtk/gtk.h>
+
+#include <libnautilus-extension/nautilus-menu-provider.h>
+#include <libnautilus-extension/nautilus-property-page-provider.h>
+#include <libtracker-client/tracker.h>
+
+#include "tracker-tags-add-dialog.h"
+#include "tracker-tags-utils.h"
+#include "tracker-tags-view.h"
+
+#define TRACKER_TYPE_TAGS_PLUGIN (tracker_tags_plugin_get_type ())
+#define TRACKER_TAGS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRACKER_TYPE_TAGS_PLUGIN, TrackerTagsPlugin))
+#define TRACKER_TAGS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TRACKER_TYPE_TAGS_PLUGIN, TrackerTagsPluginClass))
+#define TRACKER_IS_TAGS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRACKER_TYPE_TAGS_PLUGIN))
+#define TRACKER_IS_TAGS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TRACKER_TYPE_TAGS_PLUGIN))
+
+typedef struct _TrackerTagsPluginPrivate TrackerTagsPluginPrivate;
+
+typedef struct _TrackerTagsPlugin TrackerTagsPlugin;
+typedef struct _TrackerTagsPluginClass TrackerTagsPluginClass;
+
+struct _TrackerTagsPlugin
+{
+ GObject parent;
+ TrackerTagsPluginPrivate *priv;
+};
+
+struct _TrackerTagsPluginClass
+{
+ GObjectClass parent;
+};
+
+struct _TrackerTagsPluginPrivate
+{
+ TrackerClient *tracker_client;
+};
+
+static void tracker_tags_plugin_menu_provider_iface_init (NautilusMenuProviderIface *iface);
+static void tracker_tags_plugin_property_page_provider_iface_init (NautilusPropertyPageProviderIface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (TrackerTagsPlugin, tracker_tags_plugin, G_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE (NAUTILUS_TYPE_MENU_PROVIDER,
+ tracker_tags_plugin_menu_provider_iface_init)
+ G_IMPLEMENT_INTERFACE (NAUTILUS_TYPE_PROPERTY_PAGE_PROVIDER,
+ tracker_tags_plugin_property_page_provider_iface_init));
+
+#define TRACKER_TAGS_PLUGIN_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), TRACKER_TYPE_TAGS_PLUGIN, TrackerTagsPluginPrivate))
+
+static void
+tracker_tags_plugin_update_finished (GError *error, gpointer user_data)
+{
+ if (NULL != error)
+ {
+ GtkWidget *error_dialog;
+
+ error_dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_NO_SEPARATOR, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, error->message);
+ g_signal_connect (error_dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
+ gtk_dialog_run (GTK_DIALOG (error_dialog));
+ g_error_free (error);
+ }
+}
+
+static void
+tracker_tags_plugin_add_dialog_response_cb (GtkDialog *dialog, gint response_id, gpointer user_data)
+{
+ TrackerTagsPlugin *const plugin = TRACKER_TAGS_PLUGIN (user_data);
+
+ switch (response_id)
+ {
+ case GTK_RESPONSE_CANCEL:
+ case GTK_RESPONSE_DELETE_EVENT:
+ break;
+
+ case GTK_RESPONSE_OK:
+ {
+ const gchar *query;
+ const gchar *tag_label;
+
+ tag_label = tracker_tags_add_dialog_get_text (TRACKER_TAGS_ADD_DIALOG (dialog));
+ query = tracker_tags_utils_add_query (tag_label);
+ tracker_resources_sparql_update_async (plugin->priv->tracker_client, query, tracker_tags_plugin_update_finished, NULL);
+ g_free ((gpointer) query);
+ break;
+ }
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+static void
+tracker_tags_plugin_add_activate_cb (NautilusMenuItem *menu_item, gpointer user_data)
+{
+ void **const arg = user_data;
+ TrackerTagsPlugin *const plugin = TRACKER_TAGS_PLUGIN (arg[0]);
+ GtkWindow *const window = GTK_WINDOW (arg[1]);
+ GtkWidget *add_dialog;
+
+ /* g_free (arg); */
+
+ add_dialog = tracker_tags_add_dialog_new ();
+ gtk_window_set_transient_for (GTK_WINDOW (add_dialog), window);
+ g_signal_connect (add_dialog, "response", G_CALLBACK (tracker_tags_plugin_add_dialog_response_cb), plugin);
+ gtk_widget_show_all (add_dialog);
+}
+
+static void
+tracker_tags_plugin_manage_activate_cb (NautilusMenuItem *menu_item, gpointer user_data)
+{
+ void **const arg = user_data;
+ GList *const files = arg[0];
+ GtkWindow *const window = GTK_WINDOW (arg[1]);
+ GtkWidget *action_area;
+ GtkWidget *manage_dialog;
+ GtkWidget *vbox;
+ GtkWidget *view;
+
+ /* g_free (arg); */
+
+ manage_dialog = gtk_dialog_new_with_buttons (N_("Manage Tags"), window, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR, GTK_STOCK_CLOSE, NULL);
+ gtk_container_set_border_width (GTK_CONTAINER (manage_dialog), 5);
+ gtk_window_set_default_size (GTK_WINDOW (manage_dialog), 250, 375);
+ gtk_window_set_resizable (GTK_WINDOW (manage_dialog), TRUE);
+ gtk_window_set_transient_for (GTK_WINDOW (manage_dialog), window);
+ g_signal_connect (manage_dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
+
+ action_area = gtk_dialog_get_action_area (GTK_DIALOG (manage_dialog));
+ gtk_container_set_border_width (GTK_CONTAINER (action_area), 5);
+
+ vbox = gtk_dialog_get_content_area (GTK_DIALOG (manage_dialog));
+ gtk_box_set_spacing (GTK_BOX (vbox), 2);
+
+ view = tracker_tags_view_new (files);
+ gtk_box_pack_start (GTK_BOX (vbox), view, TRUE, TRUE, 0);
+
+ gtk_widget_show_all (manage_dialog);
+}
+
+static GList *
+tracker_tags_plugin_get_background_items (NautilusMenuProvider *provider,
+ GtkWidget *window,
+ NautilusFileInfo *current_folder)
+{
+ GList *menu_items = NULL;
+ NautilusMenuItem *menu_item;
+ void **arg;
+
+ if (NULL == current_folder)
+ return NULL;
+
+ menu_item = nautilus_menu_item_new ("tracker-tags-new", N_("Create Tag..."), N_("Create a new tag for this desktop"), NULL);
+ menu_items = g_list_append (menu_items, menu_item);
+ arg = g_new (void *, 2);
+ arg[0] = provider;
+ arg[1] = window;
+ g_signal_connect (menu_item, "activate", G_CALLBACK (tracker_tags_plugin_add_activate_cb), arg);
+
+ return menu_items;
+}
+
+static GList *
+tracker_tags_plugin_get_file_items (NautilusMenuProvider *provider,
+ GtkWidget *window,
+ GList *files)
+{
+ GList *menu_items = NULL;
+ NautilusMenuItem *menu_item;
+ void **arg;
+
+ if (NULL == files)
+ return NULL;
+
+ menu_item = nautilus_menu_item_new ("tracker-tags-new", N_("Create Tag..."), N_("Create a new tag for this desktop"), NULL);
+ menu_items = g_list_append (menu_items, menu_item);
+ arg = g_new (void *, 2);
+ arg[0] = provider;
+ arg[1] = window;
+ g_signal_connect (menu_item, "activate", G_CALLBACK (tracker_tags_plugin_add_activate_cb), arg);
+
+ menu_item = nautilus_menu_item_new ("tracker-tags-manage", N_("Manage Tags..."), N_("Change the tags attached to the selected objects"), NULL);
+ menu_items = g_list_append (menu_items, menu_item);
+ arg = g_new (void *, 2);
+ arg[0] = g_list_copy (files);
+ arg[1] = window;
+ g_signal_connect (menu_item, "activate", G_CALLBACK (tracker_tags_plugin_manage_activate_cb), arg);
+
+ return menu_items;
+}
+
+static GList *
+tracker_tags_plugin_get_pages (NautilusPropertyPageProvider *provider,
+ GList *files)
+{
+ GList *property_pages = NULL;
+ GtkWidget *label;
+ GtkWidget *view;
+ NautilusPropertyPage *property_page;
+
+ if (NULL == files)
+ return NULL;
+
+ label = gtk_label_new ("Tags");
+ view = tracker_tags_view_new (files);
+ property_page = nautilus_property_page_new ("tracker-tags", label, view);
+
+ property_pages = g_list_prepend (property_pages, property_page);
+ return property_pages;
+}
+
+static GList *
+tracker_tags_plugin_get_toolbar_items (NautilusMenuProvider *provider,
+ GtkWidget *window,
+ NautilusFileInfo *current_folder)
+{
+ return NULL;
+}
+
+static void
+tracker_tags_plugin_menu_provider_iface_init (NautilusMenuProviderIface *iface)
+{
+ iface->get_file_items = tracker_tags_plugin_get_file_items;
+ iface->get_background_items = tracker_tags_plugin_get_background_items;
+ iface->get_toolbar_items = tracker_tags_plugin_get_toolbar_items;
+}
+
+static void
+tracker_tags_plugin_property_page_provider_iface_init (NautilusPropertyPageProviderIface *iface)
+{
+ iface->get_pages = tracker_tags_plugin_get_pages;
+}
+
+static void
+tracker_tags_plugin_class_finalize (TrackerTagsPluginClass *klass)
+{
+}
+
+static void
+tracker_tags_plugin_finalize (GObject *object)
+{
+ TrackerTagsPlugin *const plugin = TRACKER_TAGS_PLUGIN (object);
+
+ tracker_disconnect (plugin->priv->tracker_client);
+ G_OBJECT_CLASS (tracker_tags_plugin_parent_class)->finalize (object);
+}
+
+static void
+tracker_tags_plugin_class_init (TrackerTagsPluginClass *klass)
+{
+ GObjectClass *const gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = tracker_tags_plugin_finalize;
+ g_type_class_add_private (gobject_class, sizeof (TrackerTagsPluginPrivate));
+}
+
+static void
+tracker_tags_plugin_init (TrackerTagsPlugin *self)
+{
+ TrackerTagsPluginPrivate *const priv = TRACKER_TAGS_PLUGIN_GET_PRIVATE (self);
+
+ self->priv = priv;
+ self->priv->tracker_client = tracker_connect (TRUE, G_MAXINT);
+}
+
+void
+nautilus_module_initialize (GTypeModule *module)
+{
+ tracker_tags_plugin_register_type (module);
+ tracker_tags_view_register_type (module);
+}
+
+void
+nautilus_module_shutdown (void)
+{
+}
+
+void
+nautilus_module_list_types (const GType **types,
+ int *num_types)
+{
+ static GType type_list[1];
+
+ type_list[0] = tracker_tags_plugin_type_id;
+ *types = type_list;
+ *num_types = G_N_ELEMENTS (type_list);
+}
diff --git a/extensions/nautilus-extension/tracker-tags-utils.c b/extensions/nautilus-extension/tracker-tags-utils.c
new file mode 100644
index 0000000..916a57c
--- /dev/null
+++ b/extensions/nautilus-extension/tracker-tags-utils.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2009 Debarshi Ray <debarshir src gnome org>
+ *
+ * This library 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.
+ *
+ * This library 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <string.h>
+#include "tracker-tags-utils.h"
+
+/* Copied from src/tracker-utils/tracker-tags.c */
+static const gchar *
+get_escaped_sparql_string (const gchar *str)
+{
+ GString *sparql;
+
+ sparql = g_string_new ("");
+ g_string_append_c (sparql, '"');
+
+ while (*str != '\0') {
+ gsize len = strcspn (str, "\t\n\r\"\\");
+ g_string_append_len (sparql, str, len);
+ str += len;
+ switch (*str) {
+ case '\t':
+ g_string_append (sparql, "\\t");
+ break;
+ case '\n':
+ g_string_append (sparql, "\\n");
+ break;
+ case '\r':
+ g_string_append (sparql, "\\r");
+ break;
+ case '"':
+ g_string_append (sparql, "\\\"");
+ break;
+ case '\\':
+ g_string_append (sparql, "\\\\");
+ break;
+ default:
+ continue;
+ }
+ str++;
+ }
+
+ g_string_append_c (sparql, '"');
+
+ return g_string_free (sparql, FALSE);
+}
+
+const gchar *
+tracker_tags_utils_add_query (const gchar *tag_label)
+{
+ const gchar *query;
+ const gchar *tag_label_escaped;
+
+ tag_label_escaped = get_escaped_sparql_string (tag_label);
+ query = g_strdup_printf ("INSERT { "
+ " _:tag a nao:Tag ;"
+ " nao:prefLabel %s ."
+ "} "
+ "WHERE {"
+ " OPTIONAL {"
+ " ?tag a nao:Tag ;"
+ " nao:prefLabel %s"
+ " } ."
+ " FILTER (!bound(?tag)) "
+ "}",
+ tag_label_escaped, tag_label_escaped);
+
+ g_free ((gpointer) tag_label_escaped);
+ return query;
+}
+
+const gchar *
+tracker_tags_utils_remove_query (const gchar *tag_label)
+{
+ const gchar *query;
+ const gchar *tag_label_escaped;
+
+ tag_label_escaped = get_escaped_sparql_string (tag_label);
+ query = g_strdup_printf ("DELETE { "
+ " ?tag a nao:Tag "
+ "} "
+ "WHERE {"
+ " ?tag nao:prefLabel %s "
+ "}",
+ tag_label_escaped);
+
+ g_free ((gpointer) tag_label_escaped);
+ return query;
+}
diff --git a/extensions/nautilus-extension/tracker-tags-utils.h b/extensions/nautilus-extension/tracker-tags-utils.h
new file mode 100644
index 0000000..8b1a599
--- /dev/null
+++ b/extensions/nautilus-extension/tracker-tags-utils.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2009 Debarshi Ray <debarshir src gnome org>
+ *
+ * This library 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.
+ *
+ * This library 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef TRACKER_TAGS_UTILS_H
+#define TRACKER_TAGS_UTILS_H
+
+#include <glib.h>
+
+const gchar *tracker_tags_utils_add_query (const gchar *tag_label);
+const gchar *tracker_tags_utils_remove_query (const gchar *tag_label);
+
+#endif /* TRACKER_TAGS_UTILS_H */
diff --git a/extensions/nautilus-extension/tracker-tags-view.c b/extensions/nautilus-extension/tracker-tags-view.c
new file mode 100644
index 0000000..654faea
--- /dev/null
+++ b/extensions/nautilus-extension/tracker-tags-view.c
@@ -0,0 +1,542 @@
+/*
+ * Copyright (C) 2009 Debarshi Ray <debarshir src gnome org>
+ *
+ * This library 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.
+ *
+ * This library 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <string.h>
+
+#include <libnautilus-extension/nautilus-file-info.h>
+#include <libtracker-client/tracker.h>
+
+#include "tracker-tags-add-dialog.h"
+#include "tracker-tags-utils.h"
+#include "tracker-tags-view.h"
+
+enum
+{
+ COLUMN_SELECTED,
+ COLUMN_TAG_NAME,
+ N_COLUMNS
+};
+
+enum
+{
+ SELECTED_INCONSISTENT = -1,
+ SELECTED_FALSE = 0,
+ SELECTED_TRUE
+};
+
+struct _TrackerTagsViewPrivate
+{
+ TrackerClient *tracker_client;
+ GList *files;
+ GtkListStore *list_store;
+ GtkWidget *remove_button;
+ gchar *selected_tag_label;
+};
+
+G_DEFINE_TYPE (TrackerTagsView, tracker_tags_view, GTK_TYPE_VBOX);
+
+#define TRACKER_TAGS_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), TRACKER_TYPE_TAGS_VIEW, TrackerTagsViewPrivate))
+
+/* Copied from src/tracker-utils/tracker-tags.c */
+static gchar *
+get_escaped_sparql_string (const gchar *str)
+{
+ GString *sparql;
+
+ sparql = g_string_new ("");
+ g_string_append_c (sparql, '"');
+
+ while (*str != '\0') {
+ gsize len = strcspn (str, "\t\n\r\"\\");
+ g_string_append_len (sparql, str, len);
+ str += len;
+ switch (*str) {
+ case '\t':
+ g_string_append (sparql, "\\t");
+ break;
+ case '\n':
+ g_string_append (sparql, "\\n");
+ break;
+ case '\r':
+ g_string_append (sparql, "\\r");
+ break;
+ case '"':
+ g_string_append (sparql, "\\\"");
+ break;
+ case '\\':
+ g_string_append (sparql, "\\\\");
+ break;
+ default:
+ continue;
+ }
+ str++;
+ }
+
+ g_string_append_c (sparql, '"');
+
+ return g_string_free (sparql, FALSE);
+}
+
+/* Copied from src/tracker-utils/tracker-tags.c */
+static gchar *
+get_filter_string (GStrv files,
+ const gchar *tag)
+{
+ GString *filter;
+ gint i, len;
+
+ if (!files) {
+ return NULL;
+ }
+
+ len = g_strv_length (files);
+
+ if (len < 1) {
+ return NULL;
+ }
+
+ filter = g_string_new ("");
+
+ g_string_append_printf (filter, "FILTER (");
+
+ if (tag) {
+ g_string_append (filter, "(");
+ }
+
+ for (i = 0; i < len; i++) {
+ g_string_append_printf (filter, "?f = <%s>", files[i]);
+
+ if (i < len - 1) {
+ g_string_append (filter, " || ");
+ }
+ }
+
+ if (tag) {
+ g_string_append_printf (filter, ") && ?t = <%s>", tag);
+ }
+
+ g_string_append (filter, ")");
+
+ return g_string_free (filter, FALSE);
+}
+
+static void
+tracker_tags_view_check_foreach (gpointer data, gpointer user_data)
+{
+ const GStrv element = data;
+ TrackerTagsView *const view = TRACKER_TAGS_VIEW (user_data);
+ GList *node;
+
+ for (node = view->priv->files; NULL != node; node = g_list_next (node))
+ {
+ gchar *uri;
+ gint cmp;
+
+ uri = nautilus_file_info_get_uri (NAUTILUS_FILE_INFO (node->data));
+ cmp = g_strcmp0 (element[0], uri);
+ g_free (uri);
+
+ if (0 == cmp)
+ {
+ view->priv->files = g_list_delete_link (view->priv->files, node);
+ break;
+ }
+ }
+}
+
+static void
+tracker_tags_view_query_each_tag_finished (GPtrArray *result, GError *error, gpointer user_data)
+{
+ void **const arg = user_data;
+ TrackerTagsView *const view = TRACKER_TAGS_VIEW (arg[0]);
+ GtkTreeIter *const iter = arg[1];
+ GList *files;
+ guint post_num;
+ guint pre_num;
+
+ g_free (arg);
+
+ if (NULL != error)
+ {
+ GtkWidget *error_dialog;
+
+ error_dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_NO_SEPARATOR, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, error->message);
+ g_signal_connect (error_dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
+ gtk_dialog_run (GTK_DIALOG (error_dialog));
+ g_error_free (error);
+ goto end;
+ }
+
+ files = g_list_copy (view->priv->files);
+
+ pre_num = g_list_length (view->priv->files);
+ g_ptr_array_foreach (result, tracker_tags_view_check_foreach, view);
+ g_ptr_array_foreach (result, (GFunc) g_strfreev, NULL);
+ g_ptr_array_free (result, TRUE);
+ post_num = g_list_length (view->priv->files);
+
+ if (pre_num == post_num)
+ gtk_list_store_set (view->priv->list_store, iter, COLUMN_SELECTED, SELECTED_FALSE, -1);
+ else if (0 == post_num)
+ gtk_list_store_set (view->priv->list_store, iter, COLUMN_SELECTED, SELECTED_TRUE, -1);
+ else
+ gtk_list_store_set (view->priv->list_store, iter, COLUMN_SELECTED, SELECTED_INCONSISTENT, -1);
+
+ g_list_free (view->priv->files);
+ view->priv->files = files;
+
+end:
+ gtk_tree_iter_free (iter);
+}
+
+static void
+tracker_tags_view_append_foreach (gpointer data, gpointer user_data)
+{
+ const GStrv element = data;
+ TrackerTagsView *const view = TRACKER_TAGS_VIEW (user_data);
+ GtkTreeIter iter;
+ gchar *query;
+ gchar *tag_escaped;
+ void **arg;
+
+ gtk_list_store_append (view->priv->list_store, &iter);
+ gtk_list_store_set (view->priv->list_store, &iter, COLUMN_SELECTED, SELECTED_FALSE, COLUMN_TAG_NAME, element[1], -1);
+
+ tag_escaped = get_escaped_sparql_string (element[0]);
+ query = g_strdup_printf ("SELECT ?f "
+ "WHERE {"
+ " ?f a rdfs:Resource ;"
+ " nao:hasTag %s ."
+ "}",
+ tag_escaped);
+ g_free (tag_escaped);
+ arg = g_new (void *, 2);
+ arg[0] = view;
+ arg[1] = gtk_tree_iter_copy (&iter);
+ tracker_resources_sparql_query_async (view->priv->tracker_client, query, tracker_tags_view_query_each_tag_finished, arg);
+ g_free (query);
+}
+
+static void
+tracker_tags_view_query_all_tags_finished (GPtrArray *result, GError *error, gpointer user_data)
+{
+ TrackerTagsView *const view = TRACKER_TAGS_VIEW (user_data);
+
+ if (NULL != error)
+ {
+ GtkWidget *error_dialog;
+
+ error_dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_NO_SEPARATOR, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, error->message);
+ g_signal_connect (error_dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
+ gtk_dialog_run (GTK_DIALOG (error_dialog));
+ g_error_free (error);
+ return;
+ }
+
+ g_ptr_array_foreach (result, tracker_tags_view_append_foreach, view);
+ g_ptr_array_foreach (result, (GFunc) g_strfreev, NULL);
+ g_ptr_array_free (result, TRUE);
+}
+
+static void
+tracker_tags_view_toggle_cell_data_func (GtkTreeViewColumn *column,
+ GtkCellRenderer *cell_renderer,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ GValue inconsistent = {0};
+ gint selected;
+
+ gtk_tree_model_get (tree_model, iter, COLUMN_SELECTED, &selected, -1);
+ gtk_cell_renderer_toggle_set_active (GTK_CELL_RENDERER_TOGGLE (cell_renderer), SELECTED_TRUE == selected);
+
+ g_value_init (&inconsistent, G_TYPE_BOOLEAN);
+ g_value_set_boolean (&inconsistent, SELECTED_INCONSISTENT == selected);
+ g_object_set_property (G_OBJECT (cell_renderer), "inconsistent", &inconsistent);
+}
+
+static void
+tracker_tags_view_update_finished (GError *error, gpointer user_data)
+{
+ if (NULL != error)
+ {
+ GtkWidget *error_dialog;
+
+ error_dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_NO_SEPARATOR, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, error->message);
+ g_signal_connect (error_dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
+ gtk_dialog_run (GTK_DIALOG (error_dialog));
+ g_error_free (error);
+ }
+}
+
+static void
+tracker_tags_view_add_dialog_response_cb (GtkDialog *dialog, gint response_id, gpointer user_data)
+{
+ TrackerTagsView *const view = TRACKER_TAGS_VIEW (user_data);
+
+ switch (response_id)
+ {
+ case GTK_RESPONSE_CANCEL:
+ case GTK_RESPONSE_DELETE_EVENT:
+ break;
+
+ case GTK_RESPONSE_OK:
+ {
+ const gchar *query;
+ const gchar *tag_label;
+
+ tag_label = tracker_tags_add_dialog_get_text (TRACKER_TAGS_ADD_DIALOG (dialog));
+ query = tracker_tags_utils_add_query (tag_label);
+ tracker_resources_sparql_update_async (view->priv->tracker_client, query, tracker_tags_view_update_finished, NULL);
+ g_free ((gpointer) query);
+ break;
+ }
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+static void
+tracker_tags_view_add_clicked_cb (GtkButton *button, gpointer user_data)
+{
+ TrackerTagsView *const view = TRACKER_TAGS_VIEW (user_data);
+ GtkWidget *add_dialog;
+
+ add_dialog = tracker_tags_add_dialog_new ();
+ gtk_window_set_screen (GTK_WINDOW (add_dialog), gtk_widget_get_screen (GTK_WIDGET (view)));
+ g_signal_connect (add_dialog, "response", G_CALLBACK (tracker_tags_view_add_dialog_response_cb), view);
+ gtk_widget_show_all (add_dialog);
+}
+
+static void
+tracker_tags_view_copy_uri_foreach (gpointer data, gpointer user_data)
+{
+ NautilusFileInfo *const file_info = NAUTILUS_FILE_INFO (data);
+ GStrv *const arg = user_data;
+ gchar *uri;
+
+ uri = nautilus_file_info_get_uri (file_info);
+ (*arg)[0] = uri;
+ (*arg)++;
+}
+
+static void
+tracker_tags_view_remove_clicked_cb (GtkButton *button, gpointer user_data)
+{
+ TrackerTagsView *const view = TRACKER_TAGS_VIEW (user_data);
+ const gchar *query;
+
+ query = tracker_tags_utils_remove_query (view->priv->selected_tag_label);
+ tracker_resources_sparql_update_async (view->priv->tracker_client, query, tracker_tags_view_update_finished, NULL);
+ g_free ((gpointer) query);
+}
+
+static void
+tracker_tags_view_row_activated_cb (GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data)
+{
+ TrackerTagsView *const view = TRACKER_TAGS_VIEW (user_data);
+ GStrv files;
+ GStrv arg;
+ GtkTreeIter iter;
+ GtkTreeModel *tree_model;
+ gchar *filter;
+ gchar *query;
+ gchar *tag_label_escaped;
+ gint selected;
+ guint num;
+
+ tree_model = gtk_tree_view_get_model (tree_view);
+ if (FALSE == gtk_tree_model_get_iter (tree_model, &iter, path))
+ return;
+
+ gtk_tree_model_get (tree_model, &iter, COLUMN_SELECTED, &selected, COLUMN_TAG_NAME, &view->priv->selected_tag_label, -1);
+ selected = (SELECTED_FALSE == selected) ? SELECTED_TRUE : SELECTED_FALSE;
+ gtk_list_store_set (view->priv->list_store, &iter, COLUMN_SELECTED, selected, -1);
+
+ tag_label_escaped = get_escaped_sparql_string (view->priv->selected_tag_label);
+
+ num = g_list_length (view->priv->files);
+ arg = files = g_new0 (char *, num + 1);
+ g_list_foreach (view->priv->files, tracker_tags_view_copy_uri_foreach, &arg);
+ filter = get_filter_string (files, NULL);
+
+ if (TRUE == selected)
+ {
+ query = g_strdup_printf ("INSERT { "
+ " ?urn nao:hasTag ?tag "
+ "} "
+ "WHERE {"
+ " ?urn nie:isStoredAs ?f ." /* NB: ?f is used in filter. */
+ " ?tag nao:prefLabel %s ."
+ " %s "
+ "}",
+ tag_label_escaped, filter);
+ }
+ else
+ {
+ query = g_strdup_printf ("DELETE { "
+ " ?urn nao:hasTag ?tag "
+ "} "
+ "WHERE { "
+ " ?urn nie:isStoredAs ?f ." /* NB: ?f is used in filter. */
+ " ?tag nao:prefLabel %s ."
+ " %s "
+ "}",
+ tag_label_escaped, filter);
+ }
+
+ g_strfreev (files);
+ g_free (tag_label_escaped);
+ tracker_resources_sparql_update_async (view->priv->tracker_client, query, tracker_tags_view_update_finished, NULL);
+ g_free (query);
+}
+
+static void
+tracker_tags_view_selection_changed_cb (GtkTreeSelection *tree_selection, gpointer *user_data)
+{
+ TrackerTagsView *const view = TRACKER_TAGS_VIEW (user_data);
+ GtkTreeIter iter;
+ GtkTreeModel *tree_model;
+
+ gtk_widget_set_sensitive (GTK_WIDGET (view->priv->remove_button), FALSE);
+ view->priv->selected_tag_label = NULL;
+ if (!gtk_tree_selection_get_selected (tree_selection, &tree_model, &iter))
+ return;
+
+ gtk_tree_model_get (tree_model, &iter, COLUMN_TAG_NAME, &view->priv->selected_tag_label, -1);
+ gtk_widget_set_sensitive (GTK_WIDGET (view->priv->remove_button), TRUE);
+}
+
+void
+tracker_tags_view_register_type (GTypeModule *module)
+{
+ tracker_tags_view_get_type ();
+}
+
+static void
+tracker_tags_view_finalize (GObject *object)
+{
+ TrackerTagsView *const view = TRACKER_TAGS_VIEW (object);
+
+ tracker_disconnect (view->priv->tracker_client);
+ g_list_free (view->priv->files);
+ G_OBJECT_CLASS (tracker_tags_view_parent_class)->finalize (object);
+}
+
+static void
+tracker_tags_view_class_init (TrackerTagsViewClass *klass)
+{
+ GObjectClass *const gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = tracker_tags_view_finalize;
+ g_type_class_add_private (gobject_class, sizeof (TrackerTagsViewPrivate));
+
+ tracker_tags_view_parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+tracker_tags_view_init (TrackerTagsView *view)
+{
+ TrackerTagsViewPrivate *const priv = TRACKER_TAGS_VIEW_GET_PRIVATE (view);
+ GtkCellRenderer *cell_renderer;
+ GtkTreeSelection *tree_selection;
+ GtkTreeViewColumn *column;
+ GtkWidget *button;
+ GtkWidget *button_box;
+ GtkWidget *scrolled_window;
+ GtkWidget *tree_view;
+
+ view->priv = priv;
+ view->priv->tracker_client = tracker_connect (TRUE, G_MAXINT);
+ view->priv->files = NULL;
+ view->priv->list_store = gtk_list_store_new (N_COLUMNS, G_TYPE_INT, G_TYPE_STRING);
+
+ gtk_container_set_border_width (GTK_CONTAINER (view), 6);
+ gtk_box_set_homogeneous (GTK_BOX (view), FALSE);
+ gtk_box_set_spacing (GTK_BOX (view), 0);
+
+ scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_box_pack_start (GTK_BOX (view), scrolled_window, TRUE, TRUE, 6);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN);
+
+ tree_view = gtk_tree_view_new ();
+ gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view);
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
+ cell_renderer = gtk_cell_renderer_toggle_new ();
+ gtk_tree_view_column_pack_start (column, cell_renderer, TRUE);
+ gtk_tree_view_column_set_cell_data_func (column, cell_renderer, tracker_tags_view_toggle_cell_data_func, NULL, NULL);
+ gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (cell_renderer), FALSE);
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
+ cell_renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, cell_renderer, TRUE);
+ gtk_tree_view_column_add_attribute(column, cell_renderer, "text", COLUMN_TAG_NAME);
+
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree_view), FALSE);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), GTK_TREE_MODEL (view->priv->list_store));
+
+ tree_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+ gtk_tree_selection_set_mode (tree_selection, GTK_SELECTION_SINGLE);
+ g_signal_connect (tree_selection, "changed", G_CALLBACK (tracker_tags_view_selection_changed_cb), view);
+
+ g_signal_connect (tree_view, "row-activated", G_CALLBACK (tracker_tags_view_row_activated_cb), view);
+
+ button_box = gtk_hbutton_box_new ();
+ gtk_box_pack_start (GTK_BOX (view), button_box, FALSE, FALSE, 6);
+ gtk_box_set_spacing (GTK_BOX (button_box), 6);
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (button_box), GTK_BUTTONBOX_END);
+
+ button = gtk_button_new_from_stock (GTK_STOCK_ADD);
+ gtk_box_pack_start (GTK_BOX (button_box), button, FALSE, FALSE, 0);
+ g_signal_connect (button, "clicked", G_CALLBACK (tracker_tags_view_add_clicked_cb), view);
+
+ view->priv->remove_button = gtk_button_new_from_stock (GTK_STOCK_REMOVE);
+ gtk_box_pack_start (GTK_BOX (button_box), view->priv->remove_button, FALSE, FALSE, 0);
+ gtk_widget_set_sensitive (GTK_WIDGET (view->priv->remove_button), FALSE);
+ g_signal_connect (view->priv->remove_button, "clicked", G_CALLBACK (tracker_tags_view_remove_clicked_cb), view);
+
+ view->priv->selected_tag_label = NULL;
+
+ tracker_resources_sparql_query_async (view->priv->tracker_client,
+ "SELECT ?u ?t "
+ "WHERE {"
+ " ?u a nao:Tag ;"
+ " nao:prefLabel ?t ."
+ "}",
+ tracker_tags_view_query_all_tags_finished, view);
+
+ gtk_widget_show_all (GTK_WIDGET (view));
+}
+
+GtkWidget *
+tracker_tags_view_new (GList *files)
+{
+ TrackerTagsView *self;
+
+ self = g_object_new (TRACKER_TYPE_TAGS_VIEW, NULL);
+ self->priv->files = g_list_copy (files);
+ return GTK_WIDGET (self);
+}
diff --git a/extensions/nautilus-extension/tracker-tags-view.h b/extensions/nautilus-extension/tracker-tags-view.h
new file mode 100644
index 0000000..b12810b
--- /dev/null
+++ b/extensions/nautilus-extension/tracker-tags-view.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2009 Debarshi Ray <debarshir src gnome org>
+ *
+ * This library 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.
+ *
+ * This library 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef TRACKER_TAGS_VIEW_H
+#define TRACKER_TAGS_VIEW_H
+
+#include <gtk/gtk.h>
+
+#define TRACKER_TYPE_TAGS_VIEW (tracker_tags_view_get_type ())
+#define TRACKER_TAGS_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRACKER_TYPE_TAGS_VIEW, TrackerTagsView))
+#define TRACKER_TAGS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TRACKER_TYPE_TAGS_VIEW, TrackerTagsViewClass))
+#define TRACKER_IS_TAGS_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRACKER_TYPE_TAGS_VIEW))
+#define TRACKER_IS_TAGS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TRACKER_TYPE_TAGS_VIEW))
+
+typedef struct _TrackerTagsViewPrivate TrackerTagsViewPrivate;
+
+typedef struct _TrackerTagsView TrackerTagsView;
+typedef struct _TrackerTagsViewClass TrackerTagsViewClass;
+
+struct _TrackerTagsView
+{
+ GtkVBox parent;
+ TrackerTagsViewPrivate *priv;
+};
+
+struct _TrackerTagsViewClass
+{
+ GtkVBoxClass parent;
+};
+
+GType tracker_tags_view_get_type (void);
+void tracker_tags_view_register_type (GTypeModule *module);
+
+GtkWidget *tracker_tags_view_new (GList *files);
+
+#endif /* TRACKER_TAGS_VIEW_H */
diff --git a/po/POTFILES.in b/po/POTFILES.in
index a4352c3..3a0494a 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -7,6 +7,8 @@ data/miners/tracker-miner-files.desktop.in
data/tracker-miner-fs.desktop.in.in
data/tracker-status-icon.desktop.in.in
data/tracker-store.desktop.in.in
+extensions/nautilus-extension/tracker-tags-add-dialog.c
+extensions/nautilus-extension/tracker-tags-plugin.c
python/deskbar-handler/tracker-handler.py
python/deskbar-handler/tracker-handler-static.py
python/deskbar-handler/tracker-module.py
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]