[gnome-documents] all: add a context menu to set/unset favorite state



commit 4f8844982c30db4d55d0a7afe3b008d2c4e43fe0
Author: Cosimo Cecchi <cosimoc gnome org>
Date:   Thu Aug 25 17:43:23 2011 -0400

    all: add a context menu to set/unset favorite state
    
    There's a missing glue between the updates on the tracker model and the
    items on the view.

 src/docFactory.js   |    4 ++--
 src/iconView.js     |    4 ++++
 src/lib/gd-utils.c  |   46 +++++++++++++++++++++++++++++++++++++++++++---
 src/lib/gd-utils.h  |   12 +++++++++++-
 src/listView.js     |    4 ++++
 src/trackerModel.js |    4 ++--
 src/trackerUtils.js |   18 ++++++++++++++++++
 src/view.js         |   49 +++++++++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 133 insertions(+), 8 deletions(-)
---
diff --git a/src/docFactory.js b/src/docFactory.js
index 4652ae0..44ac5ff 100644
--- a/src/docFactory.js
+++ b/src/docFactory.js
@@ -42,8 +42,8 @@ DocCommon.prototype = {
         this.author = cursor.get_string(TrackerModel.TrackerColumns.AUTHOR)[0];
         this.mtime = cursor.get_string(TrackerModel.TrackerColumns.MTIME)[0];
         this.resourceUrn = cursor.get_string(TrackerModel.TrackerColumns.RESOURCE_URN)[0];
+        this.favorite = cursor.get_boolean(TrackerModel.TrackerColumns.FAVORITE);
 
-        this._favorite = cursor.get_boolean(TrackerModel.TrackerColumns.FAVORITE);
         this._type = cursor.get_string(TrackerModel.TrackerColumns.TYPE)[0];
         this.pixbuf = Utils.pixbufFromRdfType(this._type);
 
@@ -65,7 +65,7 @@ DocCommon.prototype = {
     },
 
     checkEmblemsAndUpdateIcon: function() {
-        if (this._favorite) {
+        if (this.favorite) {
             let emblemIcon = new Gio.ThemedIcon({ name: 'emblem-favorite' });
             let emblem = new Gio.Emblem({ icon: emblemIcon });
             let emblemedIcon = new Gio.EmblemedIcon({ gicon: this.pixbuf });
diff --git a/src/iconView.js b/src/iconView.js
index 782a511..2d51a1e 100644
--- a/src/iconView.js
+++ b/src/iconView.js
@@ -69,6 +69,10 @@ IconView.prototype = {
         return this.widget;
     },
 
+    getPathAtPos: function(position) {
+        return this.widget.get_path_at_pos(position[0], position[1]);
+    },
+
     createRenderers: function() {
         let pixbufRenderer =
             new Gd.FramedPixbufRenderer({ xalign: 0.5,
diff --git a/src/lib/gd-utils.c b/src/lib/gd-utils.c
index 3fd56d8..d30f8f1 100644
--- a/src/lib/gd-utils.c
+++ b/src/lib/gd-utils.c
@@ -37,14 +37,15 @@
 GtkListStore *
 gd_create_list_store (void)
 {
-  return gtk_list_store_new (7,
+  return gtk_list_store_new (8,
                              G_TYPE_STRING, // URN
                              G_TYPE_STRING, // URI
                              G_TYPE_STRING, // TITLE
                              G_TYPE_STRING, // AUTHOR
                              G_TYPE_STRING, // MTIME
                              GDK_TYPE_PIXBUF, // ICON
-                             G_TYPE_STRING); // RESOURCE_URN
+                             G_TYPE_STRING, // RESOURCE_URN
+                             G_TYPE_BOOLEAN); // FAVORITE
 }
 
 void
@@ -56,7 +57,8 @@ gd_store_set (GtkListStore *store,
               const gchar *author,
               const gchar *mtime,
               GdkPixbuf *icon,
-              const gchar *resource_urn)
+              const gchar *resource_urn,
+              gboolean favorite)
 {
   gtk_list_store_set (store, iter,
                       0, urn,
@@ -66,6 +68,7 @@ gd_store_set (GtkListStore *store,
                       4, mtime,
                       5, icon,
                       6, resource_urn,
+                      7, favorite,
                       -1);
 }
 
@@ -273,3 +276,40 @@ gd_gtk_tree_view_set_activate_on_single_click (GtkTreeView *tree_view,
 				   GUINT_TO_POINTER (button_press_id));
 	}
 }
+
+guint
+gd_gdk_event_get_button (GdkEvent *event)
+{
+  GdkEventButton *button_ev = (GdkEventButton *) event;
+
+  return button_ev->button;
+}
+
+/**
+ * gd_gdk_event_get_position:
+ * @event:
+ * @x: (out):
+ * @y: (out):
+ *
+ */
+void
+gd_gdk_event_get_position (GdkEvent *event,
+                           gdouble *x,
+                           gdouble *y)
+{
+  GdkEventButton *button_ev = (GdkEventButton *) event;
+
+  if (x)
+    *x = button_ev->x;
+
+  if (y)
+    *y = button_ev->y;
+}
+
+void
+gd_gtk_menu_popup (GtkMenu *menu,
+                   guint button,
+                   guint32 timestamp)
+{
+  gtk_menu_popup (menu, NULL, NULL, NULL, NULL, button, timestamp);
+}
diff --git a/src/lib/gd-utils.h b/src/lib/gd-utils.h
index 3f6d525..9d1acfa 100644
--- a/src/lib/gd-utils.h
+++ b/src/lib/gd-utils.h
@@ -34,7 +34,8 @@ void gd_store_set (GtkListStore *store,
                    const gchar *author,
                    const gchar *mtime,
                    GdkPixbuf *icon,
-                   const gchar *resource_urn);
+                   const gchar *resource_urn,
+                   gboolean favorite);
 
 void gd_store_update_icon (GtkListStore *store,
                            GtkTreeIter *iter,
@@ -55,6 +56,15 @@ void gd_sidebar_store_set (GtkListStore *store,
                            const gchar *icon_name,
                            gboolean heading);
 
+void gd_gtk_menu_popup (GtkMenu *menu,
+                        guint button,
+                        guint32 timestamp);
+
+guint gd_gdk_event_get_button (GdkEvent *event);
+void  gd_gdk_event_get_position (GdkEvent *event,
+                                 gdouble *x,
+                                 gdouble *y);
+
 void gd_queue_thumbnail_job_for_file_async (GFile *file,
                                             GAsyncReadyCallback callback,
                                             gpointer user_data);
diff --git a/src/listView.js b/src/listView.js
index 0fc9e58..7b20eaa 100644
--- a/src/listView.js
+++ b/src/listView.js
@@ -67,6 +67,10 @@ ListView.prototype = {
         return this.getSelectionObject().get_selected_rows()[0];
     },
 
+    getPathAtPos: function(position) {
+        return this.widget.get_path_at_pos(position[0], position[1])[1];
+    },
+
     createRenderers: function() {
         let col = new Gtk.TreeViewColumn();
         this.widget.append_column(col);
diff --git a/src/trackerModel.js b/src/trackerModel.js
index a06c074..82d7751 100644
--- a/src/trackerModel.js
+++ b/src/trackerModel.js
@@ -43,7 +43,7 @@ const ModelColumns = {
     MTIME: 4,
     ICON: 5,
     RESOURCE_URN: 6,
-    N_COLUMNS: 7
+    FAVORITE: 7
 };
 
 const MINER_REFRESH_TIMEOUT = 60; /* seconds */
@@ -207,7 +207,7 @@ TrackerModel.prototype = {
                      newDoc.urn, newDoc.uri,
                      newDoc.title, newDoc.author,
                      newDoc.mtime, newDoc.pixbuf,
-                     newDoc.resourceUrn);
+                     newDoc.resourceUrn, newDoc.favorite);
 
         newDoc.connect('icon-updated', Lang.bind(this,
             function() {
diff --git a/src/trackerUtils.js b/src/trackerUtils.js
index 8a1f829..d9066bb 100644
--- a/src/trackerUtils.js
+++ b/src/trackerUtils.js
@@ -19,6 +19,8 @@
  *
  */
 
+const GLib = imports.gi.GLib;
+
 function sourceIdFromResourceUrn(connection, resourceUrn, callback) {
     //FIXME: is this right?
     if(resourceUrn[0] != '<')
@@ -90,3 +92,19 @@ function resourceUrnFromSourceId(connection, sourceId, callback) {
                  });
          });
 }
+
+function setFavorite(connection, urn, isFavorite, callback) {
+    connection.update_async(
+        ('%s { <%s> nao:hasTag nao:predefined-tag-favorite }').format((isFavorite ? 'INSERT OR REPLACE' : 'DELETE'), urn),
+        GLib.PRIORITY_DEFAULT, null,
+        function(object, res) {
+            try {
+                connection.update_finish(res);
+            } catch (e) {
+                log('Unable to set the favorite property on ' + urn + ' to ' + isFavorite + ': ' + e.toString());
+            }
+
+            if (callback)
+                callback();
+        });
+}
diff --git a/src/view.js b/src/view.js
index d3a3e74..0c2c6da 100644
--- a/src/view.js
+++ b/src/view.js
@@ -19,15 +19,43 @@
  *
  */
 
+const Gd = imports.gi.Gd;
 const Gtk = imports.gi.Gtk;
+const _ = imports.gettext.gettext;
 
 const Lang = imports.lang;
 const Signals = imports.signals;
 
 const Global = imports.global;
 const TrackerModel = imports.trackerModel;
+const TrackerUtils = imports.trackerUtils;
 const Utils = imports.utils;
 
+function ContextMenu(urn, isFavorite) {
+    this._init(urn, isFavorite);
+}
+
+ContextMenu.prototype = {
+    _init: function(urn, isFavorite) {
+        this._urn = urn;
+        this._isFavorite = isFavorite;
+
+        this.widget = new Gtk.Menu();
+
+        let favoriteLabel = (isFavorite) ? _("Remove from favorites") : _("Add to favorites");
+        let favoriteItem = new Gtk.MenuItem({ label: favoriteLabel });
+        favoriteItem.show();
+        this.widget.append(favoriteItem);
+
+        favoriteItem.connect('activate', Lang.bind(this,
+            function() {
+                TrackerUtils.setFavorite(Global.connection, this._urn, !this._isFavorite, null);
+            }));
+
+        this.widget.show_all();
+    }
+};
+
 function View() {
     this._init();
 }
@@ -43,6 +71,7 @@ View.prototype = {
             function() {
                 Global.selectionController.disconnect(this._selectionControllerId);
             }));
+        this.widget.connect('button-release-event', Lang.bind(this, this._onButtonRelease));
 
         this.createRenderers();
 
@@ -86,6 +115,26 @@ View.prototype = {
         Global.selectionController.setSelection(selectedURNs);
     },
 
+    _onButtonRelease: function(view, event) {
+        let button = Gd.gdk_event_get_button(event);
+        let position = Gd.gdk_event_get_position(event);
+        let timestamp = event.get_time();
+
+        if (button != 3)
+            return false;
+
+        let path = this.getPathAtPos(position);
+        let iter = this._treeModel.get_iter(path)[1];
+
+        let urn = this._treeModel.get_value(iter, TrackerModel.ModelColumns.URN);
+        let isFavorite = this._treeModel.get_value(iter, TrackerModel.ModelColumns.FAVORITE);
+
+        let menu = new ContextMenu(urn, isFavorite);
+        Gd.gtk_menu_popup(menu.widget, button, timestamp);
+
+        return true;
+    },
+
     // this must be overridden by all implementations
     createRenderers: function() {
         throw new Error('Missing implementation of createRenderers in ' + this);



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