[seahorse] Add ability to lock and unlock from the sidebar.
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [seahorse] Add ability to lock and unlock from the sidebar.
- Date: Wed, 2 Nov 2011 09:06:33 +0000 (UTC)
commit 6b294359c31b0d8b187d7a1c3682a2f689ddca29
Author: Stef Walter <stefw collabora co uk>
Date: Tue Oct 25 11:42:02 2011 +0200
Add ability to lock and unlock from the sidebar.
gkr/seahorse-gkr-actions.c | 49 ++++--
gkr/seahorse-gkr-keyring.c | 23 +++-
gkr/seahorse-gkr-keyring.h | 2 +
src/seahorse-sidebar.c | 389 +++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 448 insertions(+), 15 deletions(-)
---
diff --git a/gkr/seahorse-gkr-actions.c b/gkr/seahorse-gkr-actions.c
index 9e5e71b..4884768 100644
--- a/gkr/seahorse-gkr-actions.c
+++ b/gkr/seahorse-gkr-actions.c
@@ -189,6 +189,15 @@ on_keyrings_unlock (GtkAction *action,
}
static void
+on_keyring_unlock (GtkAction *action,
+ gpointer user_data)
+{
+ GtkWindow *parent = seahorse_action_get_window (action);
+ gnome_keyring_unlock (seahorse_gkr_keyring_get_name (SEAHORSE_GKR_KEYRING (user_data)), NULL,
+ on_keyring_unlock_done, g_object_ref (parent), g_object_unref);
+}
+
+static void
on_keyring_lock_done (GnomeKeyringResult result, gpointer user_data)
{
GtkWindow *parent = GTK_WINDOW (user_data);
@@ -220,6 +229,15 @@ on_keyrings_lock (GtkAction *action,
}
static void
+on_keyring_lock (GtkAction *action,
+ gpointer user_data)
+{
+ GtkWindow *parent = seahorse_action_get_window (action);
+ gnome_keyring_lock (seahorse_gkr_keyring_get_name (SEAHORSE_GKR_KEYRING (user_data)),
+ on_keyring_lock_done, g_object_ref (parent), g_object_unref);
+}
+
+static void
on_set_default_keyring_done (GnomeKeyringResult result,
gpointer user_data)
{
@@ -344,6 +362,12 @@ static const GtkActionEntry KEYRING_ACTIONS[] = {
N_("Change the unlock password of the password storage keyring"), G_CALLBACK (on_keyring_password) },
{ "keyring-properties", GTK_STOCK_PROPERTIES, NULL, NULL,
N_("Properties of the keyring."), G_CALLBACK (on_keyring_properties) },
+
+ /* Generic actions used by the sidebar for the current selection */
+ { "lock", NULL, NULL, "",
+ N_("Lock the password storage keyring."), G_CALLBACK (on_keyring_lock) },
+ { "unlock", NULL, NULL, "",
+ N_("Unlock the password storage keyring."), G_CALLBACK (on_keyring_unlock) },
};
static const gchar* KEYRING_UI =
@@ -376,25 +400,18 @@ static GtkActionGroup *
seahorse_gkr_keyring_actions_clone_for_objects (SeahorseActions *actions,
GList *objects)
{
- GnomeKeyringInfo *info;
gboolean locked = FALSE;
gboolean unlocked = FALSE;
- gboolean can_default = FALSE;
GtkActionGroup *cloned;
GList *l;
g_return_val_if_fail (objects != NULL, NULL);
for (l = objects; l; l = g_list_next (l)) {
- info = seahorse_gkr_keyring_get_info (l->data);
- if (info != NULL) {
- if (gnome_keyring_info_get_is_locked (info))
- locked = TRUE;
- else
- unlocked = TRUE;
- if (!seahorse_gkr_keyring_get_is_default (l->data))
- can_default = TRUE;
- }
+ if (seahorse_gkr_keyring_get_locked (l->data))
+ locked = TRUE;
+ else
+ unlocked = TRUE;
}
cloned = gtk_action_group_new ("KeyringObject");
@@ -413,7 +430,15 @@ seahorse_gkr_keyring_actions_clone_for_objects (SeahorseActions *actions,
G_N_ELEMENTS (KEYRING_ACTIONS),
g_object_ref (objects->data),
g_object_unref);
- gtk_action_set_sensitive (gtk_action_group_get_action (cloned, "keyring-default"), can_default);
+ g_object_bind_property (objects->data, "is-default",
+ gtk_action_group_get_action (cloned, "keyring-default"), "sensitive",
+ G_BINDING_INVERT_BOOLEAN | G_BINDING_SYNC_CREATE);
+ g_object_bind_property (objects->data, "locked",
+ gtk_action_group_get_action (cloned, "lock"), "sensitive",
+ G_BINDING_INVERT_BOOLEAN | G_BINDING_SYNC_CREATE);
+ g_object_bind_property (objects->data, "locked",
+ gtk_action_group_get_action (cloned, "unlock"), "sensitive",
+ G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
}
return cloned;
diff --git a/gkr/seahorse-gkr-keyring.c b/gkr/seahorse-gkr-keyring.c
index 6de6a17..7bad05d 100644
--- a/gkr/seahorse-gkr-keyring.c
+++ b/gkr/seahorse-gkr-keyring.c
@@ -43,12 +43,14 @@ enum {
PROP_IS_DEFAULT,
PROP_URI,
PROP_ACTIONS,
+ PROP_LOCKED,
};
struct _SeahorseGkrKeyringPrivate {
GHashTable *items;
gchar *keyring_name;
gboolean is_default;
+ gboolean locked;
gpointer req_info;
GnomeKeyringInfo *keyring_info;
@@ -434,6 +436,9 @@ seahorse_gkr_keyring_get_property (GObject *obj, guint prop_id, GValue *value,
case PROP_ACTIONS:
g_value_set_object (value, self->pv->actions);
break;
+ case PROP_LOCKED:
+ g_value_set_boolean (value, seahorse_gkr_keyring_get_locked (self));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
break;
@@ -463,10 +468,15 @@ seahorse_gkr_keyring_class_init (SeahorseGkrKeyringClass *klass)
g_object_class_install_property (gobject_class, PROP_KEYRING_INFO,
g_param_spec_boxed ("keyring-info", "Gnome Keyring Info", "Info about keyring.",
boxed_type_keyring_info (), G_PARAM_READWRITE));
-
+
g_object_class_install_property (gobject_class, PROP_IS_DEFAULT,
g_param_spec_boolean ("is-default", "Is default", "Is the default keyring.",
FALSE, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_LOCKED,
+ g_param_spec_boolean ("locked", "Locked", "Keyring is locked?",
+ FALSE, G_PARAM_READABLE));
+
}
static void
@@ -560,6 +570,7 @@ seahorse_gkr_keyring_set_info (SeahorseGkrKeyring *self, GnomeKeyringInfo *info)
g_object_freeze_notify (obj);
seahorse_gkr_keyring_realize (self);
g_object_notify (obj, "keyring-info");
+ g_object_notify (obj, "locked");
g_object_thaw_notify (obj);
}
@@ -577,3 +588,13 @@ seahorse_gkr_keyring_set_is_default (SeahorseGkrKeyring *self, gboolean is_defau
self->pv->is_default = is_default;
g_object_notify (G_OBJECT (self), "is-default");
}
+
+gboolean
+seahorse_gkr_keyring_get_locked (SeahorseGkrKeyring *self)
+{
+ g_return_val_if_fail (SEAHORSE_IS_GKR_KEYRING (self), TRUE);
+
+ if (!self->pv->keyring_info)
+ return TRUE;
+ return gnome_keyring_info_get_is_locked (self->pv->keyring_info);
+}
diff --git a/gkr/seahorse-gkr-keyring.h b/gkr/seahorse-gkr-keyring.h
index 4735ef5..121509b 100644
--- a/gkr/seahorse-gkr-keyring.h
+++ b/gkr/seahorse-gkr-keyring.h
@@ -73,6 +73,8 @@ gboolean seahorse_gkr_keyring_get_is_default (SeahorseGkrKeyring *
void seahorse_gkr_keyring_set_is_default (SeahorseGkrKeyring *self,
gboolean is_default);
+gboolean seahorse_gkr_keyring_get_locked (SeahorseGkrKeyring *self);
+
void seahorse_gkr_keyring_load_async (SeahorseGkrKeyring *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
diff --git a/src/seahorse-sidebar.c b/src/seahorse-sidebar.c
index bfe0465..5db03ed 100644
--- a/src/seahorse-sidebar.c
+++ b/src/seahorse-sidebar.c
@@ -23,6 +23,8 @@
#include "seahorse-sidebar.h"
+#include "seahorse-action.h"
+#include "seahorse-actions.h"
#include "seahorse-backend.h"
#include "seahorse-place.h"
#include "seahorse-registry.h"
@@ -52,6 +54,15 @@ struct _SeahorseSidebar {
/* A set of chosen uris, used with settings */
GHashTable *chosen;
+ /* Action icons */
+ GdkPixbuf *pixbuf_lock;
+ GdkPixbuf *pixbuf_unlock;
+ GdkPixbuf *pixbuf_lock_l;
+ GdkPixbuf *pixbuf_unlock_l;
+ GtkTreePath *action_highlight_path;
+ GtkCellRenderer *action_cell_renderer;
+ gint action_button_size;
+
guint update_places_sig;
};
@@ -59,6 +70,8 @@ struct _SeahorseSidebarClass {
GtkScrolledWindowClass parent_class;
};
+#define ACTION_BUTTON_XPAD 6
+
enum {
PROP_0,
PROP_COLLECTION,
@@ -80,6 +93,7 @@ enum {
SIDEBAR_CATEGORY,
SIDEBAR_COLLECTION,
SIDEBAR_URI,
+ SIDEBAR_ACTIONS,
SIDEBAR_N_COLUMNS
};
@@ -92,6 +106,7 @@ static GType column_types[] = {
G_TYPE_STRING,
0 /* later */,
G_TYPE_STRING,
+ 0 /* later */
};
enum {
@@ -109,6 +124,7 @@ seahorse_sidebar_init (SeahorseSidebar *self)
g_assert (SIDEBAR_N_COLUMNS == G_N_ELEMENTS (column_types));
column_types[SIDEBAR_ICON] = G_TYPE_ICON;
column_types[SIDEBAR_COLLECTION] = GCR_TYPE_COLLECTION;
+ column_types[SIDEBAR_ACTIONS] = GTK_TYPE_ACTION_GROUP;
self->store = gtk_list_store_newv (SIDEBAR_N_COLUMNS, column_types);
self->backends = g_ptr_array_new_with_free_func (g_object_unref);
@@ -117,6 +133,101 @@ seahorse_sidebar_init (SeahorseSidebar *self)
self->chosen = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
}
+static guchar
+lighten_component (guchar cur_value)
+{
+ int new_value = cur_value + 24 + (cur_value >> 3);
+ return (new_value > 255) ? (guchar)255 : (guchar)new_value;
+}
+
+static GdkPixbuf *
+create_spotlight_pixbuf (GdkPixbuf* src)
+{
+ GdkPixbuf *dest;
+ int i, j;
+ int width, height, has_alpha, src_row_stride, dst_row_stride;
+ guchar *target_pixels, *original_pixels;
+ guchar *pixsrc, *pixdest;
+
+ dest = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (src),
+ gdk_pixbuf_get_has_alpha (src),
+ gdk_pixbuf_get_bits_per_sample (src),
+ gdk_pixbuf_get_width (src),
+ gdk_pixbuf_get_height (src));
+
+ has_alpha = gdk_pixbuf_get_has_alpha (src);
+ width = gdk_pixbuf_get_width (src);
+ height = gdk_pixbuf_get_height (src);
+ dst_row_stride = gdk_pixbuf_get_rowstride (dest);
+ src_row_stride = gdk_pixbuf_get_rowstride (src);
+ target_pixels = gdk_pixbuf_get_pixels (dest);
+ original_pixels = gdk_pixbuf_get_pixels (src);
+
+ for (i = 0; i < height; i++) {
+ pixdest = target_pixels + i * dst_row_stride;
+ pixsrc = original_pixels + i * src_row_stride;
+ for (j = 0; j < width; j++) {
+ *pixdest++ = lighten_component (*pixsrc++);
+ *pixdest++ = lighten_component (*pixsrc++);
+ *pixdest++ = lighten_component (*pixsrc++);
+ if (has_alpha) {
+ *pixdest++ = *pixsrc++;
+ }
+ }
+ }
+ return dest;
+}
+
+static void
+ensure_sidebar_pixbufs (SeahorseSidebar *self)
+{
+ GtkIconInfo *icon_info;
+ GIcon *icon;
+ GtkIconTheme *icon_theme;
+ GtkStyleContext *style;
+ gint height;
+
+ if (self->pixbuf_lock &&
+ self->pixbuf_lock_l &&
+ self->pixbuf_unlock_l &&
+ self->pixbuf_unlock)
+ return;
+
+ icon_theme = gtk_icon_theme_get_default ();
+ style = gtk_widget_get_style_context (GTK_WIDGET (self));
+ if (!gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &self->action_button_size, &height))
+ self->action_button_size = 16;
+
+ /* Lock icon */
+ icon = g_themed_icon_new_with_default_fallbacks ("changes-prevent-symbolic");
+ icon_info = gtk_icon_theme_lookup_by_gicon (icon_theme, icon, self->action_button_size, 0);
+ if (!self->pixbuf_lock)
+ self->pixbuf_lock = gtk_icon_info_load_symbolic_for_context (icon_info, style, NULL, NULL);
+ if (!self->pixbuf_lock_l)
+ self->pixbuf_lock_l = create_spotlight_pixbuf (self->pixbuf_lock);
+ gtk_icon_info_free (icon_info);
+ g_object_unref (icon);
+
+ /* Unlock icon */
+ icon = g_themed_icon_new_with_default_fallbacks ("changes-allow-symbolic");
+ icon_info = gtk_icon_theme_lookup_by_gicon (icon_theme, icon, self->action_button_size, 0);
+ if (!self->pixbuf_unlock)
+ self->pixbuf_unlock = gtk_icon_info_load_symbolic_for_context (icon_info, style, NULL, NULL);
+ if (!self->pixbuf_unlock_l)
+ self->pixbuf_unlock_l = create_spotlight_pixbuf (self->pixbuf_unlock);
+ gtk_icon_info_free (icon_info);
+ g_object_unref (icon);
+}
+
+static void
+invalidate_sidebar_pixbufs (SeahorseSidebar *self)
+{
+ g_clear_object (&self->pixbuf_lock);
+ g_clear_object (&self->pixbuf_unlock);
+ g_clear_object (&self->pixbuf_lock_l);
+ g_clear_object (&self->pixbuf_unlock_l);
+}
+
static void
next_or_append_row (GtkListStore *store,
GtkTreeIter *iter,
@@ -177,11 +288,14 @@ update_backend (SeahorseSidebar *self,
GtkTreeIter *iter)
{
GList *collections, *l;
+ GtkActionGroup *actions;
+ GtkActionGroup *cloned;
GParamSpec *spec;
gchar *category;
gchar *tooltip;
gchar *label;
GIcon *icon = NULL;
+ GList *objects;
gchar *uri;
collections = gcr_collection_get_objects (backend);
@@ -216,8 +330,17 @@ update_backend (SeahorseSidebar *self,
"description", &tooltip,
"icon", &icon,
"uri", &uri,
+ "actions", &actions,
NULL);
+ cloned = NULL;
+ if (actions) {
+ objects = g_list_append (NULL, l->data);
+ cloned = seahorse_actions_clone_for_objects (actions, objects);
+ g_list_free (objects);
+ g_object_unref (actions);
+ }
+
spec = g_object_class_find_property (G_OBJECT_GET_CLASS (l->data), "label");
g_return_if_fail (spec != NULL);
@@ -230,9 +353,17 @@ update_backend (SeahorseSidebar *self,
SIDEBAR_ICON, icon,
SIDEBAR_EDITABLE, (spec->flags & G_PARAM_WRITABLE) ? TRUE : FALSE,
SIDEBAR_COLLECTION, l->data,
+ SIDEBAR_ACTIONS, cloned,
SIDEBAR_URI, uri,
-1);
-
+#if 0
+GtkAction *action;
+action = gtk_action_group_get_action (cloned, "lock");
+g_printerr ("lock sensitive: %d", gtk_action_get_sensitive (action));
+action = gtk_action_group_get_action (cloned, "unlock");
+g_printerr ("unlock sensitive: %d", gtk_action_get_sensitive (action));
+#endif
+ g_clear_object (&cloned);
g_clear_object (&icon);
g_free (label);
g_free (tooltip);
@@ -490,6 +621,91 @@ update_places_later (SeahorseSidebar *self)
self->update_places_sig = g_idle_add (on_idle_update_places, self);
}
+static GtkAction *
+lookup_relevant_action_for_iter (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gboolean *is_lock)
+{
+ GtkActionGroup *actions = NULL;
+ GtkAction *action;
+
+ gtk_tree_model_get (model, iter,
+ SIDEBAR_ACTIONS, &actions,
+ -1);
+
+ if (!actions)
+ return NULL;
+
+ action = gtk_action_group_get_action (actions, "unlock");
+ if (action != NULL &&
+ gtk_action_is_visible (action) &&
+ gtk_action_is_sensitive (action)) {
+ *is_lock = FALSE;
+ } else {
+ action = gtk_action_group_get_action (actions, "lock");
+ if (action != NULL &&
+ gtk_action_is_visible (action) &&
+ gtk_action_is_sensitive (action)) {
+ *is_lock = TRUE;
+ } else {
+ action = NULL;
+ }
+ }
+
+ if (action)
+ g_object_ref (action);
+ g_object_unref (actions);
+ return action;
+}
+
+static void
+on_cell_renderer_action_icon (GtkTreeViewColumn *column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ SeahorseSidebar *self = SEAHORSE_SIDEBAR (user_data);
+ gboolean highlight = FALSE;
+ GtkTreePath *path;
+ GdkPixbuf *pixbuf = NULL;
+ GtkAction *action;
+ gboolean is_lock = FALSE;
+
+ action = lookup_relevant_action_for_iter (model, iter, &is_lock);
+
+ if (action == NULL) {
+ g_object_set (cell,
+ "visible", FALSE,
+ "pixbuf", NULL,
+ NULL);
+ return;
+ }
+
+ ensure_sidebar_pixbufs (self);
+
+ pixbuf = NULL;
+ highlight = FALSE;
+
+ if (self->action_highlight_path) {
+ path = gtk_tree_model_get_path (model, iter);
+ highlight = gtk_tree_path_compare (path, self->action_highlight_path) == 0;
+ gtk_tree_path_free (path);
+ }
+
+ if (is_lock)
+ pixbuf = highlight ? self->pixbuf_unlock : self->pixbuf_unlock_l;
+ else
+ pixbuf = highlight ? self->pixbuf_lock : self->pixbuf_lock_l;
+
+ g_object_set (cell,
+ "visible", TRUE,
+ "pixbuf", pixbuf,
+ NULL);
+
+ g_object_unref (action);
+}
+
static void
on_cell_renderer_heading_visible (GtkTreeViewColumn *column,
GtkCellRenderer *cell,
@@ -556,23 +772,30 @@ on_cell_renderer_check (GtkTreeViewColumn *column,
GtkTreeIter *iter,
gpointer user_data)
{
+#if 0
SeahorseSidebar *self = SEAHORSE_SIDEBAR (user_data);
GcrCollection *collection;
RowType type;
+#endif
gboolean active;
gboolean inconsistent;
gboolean visible;
+#if 0
gtk_tree_model_get (model, iter,
SIDEBAR_ROW_TYPE, &type,
SIDEBAR_COLLECTION, &collection,
-1);
+#endif
active = FALSE;
inconsistent = FALSE;
+#if 0
if (type == TYPE_BACKEND) {
+#endif
visible = FALSE;
+#if 0
} else if (collection != NULL && g_hash_table_size (self->checked) > 0) {
active = g_hash_table_lookup (self->checked, collection) != NULL;
visible = TRUE;
@@ -580,6 +803,7 @@ on_cell_renderer_check (GtkTreeViewColumn *column,
visible = (gtk_widget_is_focus (GTK_WIDGET (self->tree_view)) &&
collection == self->selected);
}
+#endif
/* self->mnemonics_visible */
g_object_set (cell,
@@ -588,7 +812,9 @@ on_cell_renderer_check (GtkTreeViewColumn *column,
"inconsistent", inconsistent,
NULL);
+#if 0
g_clear_object (&collection);
+#endif
}
static gboolean
@@ -782,6 +1008,106 @@ on_tree_view_popup_menu (GtkWidget *widget,
g_clear_object (&collection);
}
+static void
+update_action_buttons_take_path (SeahorseSidebar *self,
+ GtkTreePath *path)
+{
+ GtkTreeIter iter;
+ GtkTreePath *old_path;
+ GtkTreeModel *model;
+
+ if (path == self->action_highlight_path) {
+ gtk_tree_path_free (path);
+ return;
+ }
+
+ if (path && self->action_highlight_path &&
+ gtk_tree_path_compare (self->action_highlight_path, path) == 0) {
+ gtk_tree_path_free (path);
+ return;
+ }
+
+ old_path = self->action_highlight_path;
+ self->action_highlight_path = path;
+
+ model = GTK_TREE_MODEL (self->store);
+ if (self->action_highlight_path) {
+ if (gtk_tree_model_get_iter (model, &iter, self->action_highlight_path))
+ gtk_tree_model_row_changed (model, self->action_highlight_path, &iter);
+ }
+
+ if (old_path) {
+ if (gtk_tree_model_get_iter (model, &iter, old_path))
+ gtk_tree_model_row_changed (model, old_path, &iter);
+ gtk_tree_path_free (old_path);
+ }
+}
+
+static gboolean
+over_action_button (SeahorseSidebar *self,
+ gint x,
+ gint y,
+ GtkTreePath **path)
+{
+ GtkTreeViewColumn *column;
+ gint width, x_offset, hseparator;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+
+ *path = NULL;
+
+ if (gtk_tree_view_get_path_at_pos (self->tree_view, x, y, path,
+ &column, NULL, NULL)) {
+
+ model = GTK_TREE_MODEL (self->store);
+ gtk_tree_model_get_iter (model, &iter, *path);
+
+ gtk_widget_style_get (GTK_WIDGET (self->tree_view),
+ "horizontal-separator", &hseparator,
+ NULL);
+
+ /* Reload cell attributes for this particular row */
+ gtk_tree_view_column_cell_set_cell_data (column,
+ model, &iter, FALSE, FALSE);
+
+ gtk_tree_view_column_cell_get_position (column,
+ self->action_cell_renderer,
+ &x_offset, &width);
+
+ /* This is kinda weird, but we have to do it to workaround gtk+ expanding
+ * the eject cell renderer (even thought we told it not to) and we then
+ * had to set it right-aligned */
+ x_offset += width - hseparator - ACTION_BUTTON_XPAD - self->action_button_size;
+
+ if (x - x_offset >= 0 && x - x_offset <= self->action_button_size)
+ return TRUE;
+ }
+
+ if (*path != NULL) {
+ gtk_tree_path_free (*path);
+ *path = NULL;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+on_tree_view_motion_notify_event (GtkWidget *widget,
+ GdkEventMotion *event,
+ gpointer user_data)
+{
+ SeahorseSidebar *self = SEAHORSE_SIDEBAR (user_data);
+ GtkTreePath *path = NULL;
+
+ if (over_action_button (self, event->x, event->y, &path)) {
+ update_action_buttons_take_path (self, path);
+ return TRUE;
+ }
+
+ update_action_buttons_take_path (self, NULL);
+ return FALSE;
+}
+
static gboolean
on_tree_view_button_press_event (GtkWidget *widget,
GdkEventButton *event,
@@ -815,6 +1141,45 @@ on_tree_view_button_press_event (GtkWidget *widget,
return TRUE;
}
+static gboolean
+on_tree_view_button_release_event (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data)
+{
+ SeahorseSidebar *self = SEAHORSE_SIDEBAR (user_data);
+ GtkTreePath *path;
+ GtkAction *action;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gboolean is_lock;
+ gboolean ret;
+ GtkWidget *window;
+
+ if (event->type != GDK_BUTTON_RELEASE)
+ return TRUE;
+
+ if (!over_action_button (self, event->x, event->y, &path))
+ return FALSE;
+
+ model = GTK_TREE_MODEL (self->store);
+
+ ret = gtk_tree_model_get_iter (model, &iter, path);
+ gtk_tree_path_free (path);
+
+ if (!ret)
+ return FALSE;
+
+ action = lookup_relevant_action_for_iter (model, &iter, &is_lock);
+ if (action == NULL)
+ return FALSE;
+
+ window = gtk_widget_get_toplevel (widget);
+ seahorse_action_activate_with_window (action, GTK_WINDOW (window));
+ g_object_unref (action);
+
+ return TRUE;
+}
+
static void
seahorse_sidebar_constructed (GObject *obj)
{
@@ -909,6 +1274,20 @@ seahorse_sidebar_constructed (GObject *obj)
self, NULL);
g_signal_connect (cell, "toggled", G_CALLBACK (on_checked_toggled), self);
+ /* lock/unlock icon renderer */
+ cell = gtk_cell_renderer_pixbuf_new ();
+ self->action_cell_renderer = cell;
+ g_object_set (cell,
+ "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE,
+ "stock-size", GTK_ICON_SIZE_MENU,
+ "xpad", ACTION_BUTTON_XPAD,
+ "xalign", 1.0,
+ NULL);
+ gtk_tree_view_column_pack_start (col, cell, FALSE);
+ gtk_tree_view_column_set_cell_data_func (col, cell,
+ on_cell_renderer_action_icon,
+ self, NULL);
+
gtk_tree_view_column_set_max_width (GTK_TREE_VIEW_COLUMN (col), 24);
gtk_tree_view_append_column (tree_view, col);
@@ -918,7 +1297,8 @@ seahorse_sidebar_constructed (GObject *obj)
gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (self->store));
g_signal_connect (tree_view, "popup-menu", G_CALLBACK (on_tree_view_popup_menu), self);
g_signal_connect (tree_view, "button-press-event", G_CALLBACK (on_tree_view_button_press_event), self);
-
+ g_signal_connect (tree_view, "motion-notify-event", G_CALLBACK (on_tree_view_motion_notify_event), self);
+ g_signal_connect (tree_view, "button-release-event", G_CALLBACK (on_tree_view_button_release_event), self);
gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (tree_view));
gtk_widget_show (GTK_WIDGET (tree_view));
self->tree_view = tree_view;
@@ -995,6 +1375,8 @@ seahorse_sidebar_dispose (GObject *obj)
g_list_free (places);
}
+ invalidate_sidebar_pixbufs (self);
+
G_OBJECT_CLASS (seahorse_sidebar_parent_class)->dispose (obj);
}
@@ -1014,6 +1396,9 @@ seahorse_sidebar_finalize (GObject *obj)
g_ptr_array_unref (self->backends);
g_object_unref (self->store);
+ if (self->action_highlight_path)
+ gtk_tree_path_free (self->action_highlight_path);
+
G_OBJECT_CLASS (seahorse_sidebar_parent_class)->finalize (obj);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]