~ubuntu-branches/ubuntu/precise/gnome-keyring/precise

« back to all changes in this revision

Viewing changes to gcr/gcr-list-selector.c

  • Committer: Bazaar Package Importer
  • Author(s): Chris Coulson, Chris Coulson, Mathieu Trudel-Lapierre
  • Date: 2011-08-10 12:29:33 UTC
  • mfrom: (1.1.70 upstream)
  • Revision ID: james.westby@ubuntu.com-20110810122933-0ezu9rqbnw956vwn
Tags: 3.1.4-0ubuntu1
[ Chris Coulson ]
* New upstream release
* Drop the multi-flavor (gtk2/gtk3) build - the new version supports
  only gtk3
  - update debian/rules
  - bump debian/compat to 7, else we need to add debian/tmp back to all
    the install files so that dh_install can find them (or continue to
    specify DEB_DH_INSTALL_SOURCEDIR in debian/rules)
  - Drop libgcr1 and libgcr-dev from debian/control.in
  - Remove debian/libgcr1.install and debian/libgcr-dev.install
  - Drop the libgtk2.0-dev build-depend
* Update for the libgck -> libgck-1 soname change
  - update debian/control
  - rename debian/libgck0.install => debian/libgck-1-0.install
  - update debian/libgck-1-0.install
  - rename debian/libgck0.symbols => debian/libgck-1-0.symbols
  - update debian/libgck-1-0.symbols
  - rename debian/libgck-dev.install => debian/libgck-1-dev.install
  - update debian/libgck-1-dev.install
* Update symbols for libgcr-3. Note that upstream removed some symbols
  without bumping the soname (in addition to adding symbols). However,
  these aren't actually used anywhere, and they have only ever existed
  in the current unstable series so we just ignore this for now :/
  - update debian/libgcr-3-1.symbols
* Drop debian/patches/05_onlyshowin_unity.patch - fixed upstream
* Add build-depend on libp11-kit-dev
* Install the contents of /usr/share/icons and /etc/pkcs11
  - update debian/gnome-keyring.install
* Revert an unintentional change of the libgcr soname to an older version
  - add debian/patches/05_revert_gcr_soname_bump.patch
  - update debian/patches/series

[ Mathieu Trudel-Lapierre ]
* debian/patches/99git_fs_caps_11a5d41.patch,
  debian/patches/99git_ipc_lock_caps_ad67edd.patch: dropped, included in
  release upstream tarball.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * gnome-keyring
 
3
 *
 
4
 * Copyright (C) 2011 Collabora Ltd.
 
5
 * Copyright (C) 2010 Stefan Walter
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or modify
 
8
 * it under the terms of the GNU Lesser General Public License as
 
9
 * published by the Free Software Foundation; either version 2.1 of
 
10
 * the License, or (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful, but
 
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Lesser General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Lesser General Public
 
18
 * License along with this program; if not, write to the Free Software
 
19
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
20
 * 02111-1307, USA.
 
21
 *
 
22
 * Author: Stef Walter <stefw@collabora.co.uk>
 
23
 */
 
24
 
 
25
#include "config.h"
 
26
 
 
27
#include "gcr-collection-model.h"
 
28
#include "gcr-internal.h"
 
29
#include "gcr-list-selector.h"
 
30
#include "gcr-list-selector-private.h"
 
31
#include "gcr-live-search.h"
 
32
 
 
33
#include <glib/gi18n-lib.h>
 
34
 
 
35
#include <string.h>
 
36
 
 
37
/**
 
38
 * SECTION:gcr-list-selector
 
39
 * @title: GcrListSelector
 
40
 * @short_description: A selector widget to one or more certificates from a list.
 
41
 *
 
42
 * The #GcrListSelector can be used to select one or more certificates or keys.
 
43
 * Live search is available for quick filtering.
 
44
 */
 
45
 
 
46
/**
 
47
 * GcrListSelector:
 
48
 * @parent: Parent object
 
49
 *
 
50
 * A list selector widget.
 
51
 */
 
52
 
 
53
/**
 
54
 * GcrListSelectorClass:
 
55
 *
 
56
 * The class for #GcrListSelector.
 
57
 */
 
58
 
 
59
enum {
 
60
        PROP_0,
 
61
        PROP_COLLECTION
 
62
};
 
63
 
 
64
struct _GcrListSelectorPrivate {
 
65
        GcrCollection *collection;
 
66
        GcrCollectionModel *model;
 
67
 
 
68
        GtkTreeModelFilter *filter;
 
69
        GtkWidget *search_widget;
 
70
};
 
71
 
 
72
G_DEFINE_TYPE (GcrListSelector, gcr_list_selector, GTK_TYPE_TREE_VIEW);
 
73
 
 
74
static gboolean
 
75
object_is_visible (GcrListSelector *self, GObject *object)
 
76
{
 
77
        gchar *text;
 
78
        gboolean visible;
 
79
 
 
80
        if (g_object_class_find_property (G_OBJECT_GET_CLASS (object), "search-text"))
 
81
                g_object_get (object, "search-text", &text, NULL);
 
82
        else
 
83
                g_object_get (object, "label", &text, NULL);
 
84
 
 
85
        visible = _gcr_live_search_match (GCR_LIVE_SEARCH (self->pv->search_widget), text);
 
86
        g_free (text);
 
87
 
 
88
        return visible;
 
89
}
 
90
 
 
91
static gboolean
 
92
on_tree_filter_visible_func (GtkTreeModel *model, GtkTreeIter *iter,
 
93
                             gpointer user_data)
 
94
{
 
95
        GcrListSelector *self = GCR_LIST_SELECTOR (user_data);
 
96
        GObject *object;
 
97
 
 
98
        if (self->pv->search_widget == NULL ||
 
99
            !gtk_widget_get_visible (self->pv->search_widget))
 
100
                return TRUE;
 
101
 
 
102
        object = gcr_collection_model_object_for_iter (self->pv->model, iter);
 
103
        if (object != NULL)
 
104
                return object_is_visible (self, object);
 
105
 
 
106
        return FALSE;
 
107
}
 
108
 
 
109
static gboolean
 
110
on_tree_view_start_search (GtkTreeView *view, gpointer user_data)
 
111
{
 
112
        GcrListSelector *self = GCR_LIST_SELECTOR (view);
 
113
 
 
114
        if (self->pv->search_widget == NULL)
 
115
                return FALSE;
 
116
 
 
117
        if (gtk_widget_get_visible (self->pv->search_widget))
 
118
                gtk_widget_grab_focus (self->pv->search_widget);
 
119
        else
 
120
                gtk_widget_show (self->pv->search_widget);
 
121
 
 
122
        return TRUE;
 
123
}
 
124
 
 
125
static void
 
126
on_search_widget_text_notify (GcrLiveSearch *search, GParamSpec *pspec,
 
127
                              gpointer user_data)
 
128
{
 
129
        GcrListSelector *self = GCR_LIST_SELECTOR (user_data);
 
130
#if 0
 
131
        GtkTreeViewColumn *focus_column;
 
132
        GtkTreeModel *model;
 
133
        GtkTreeIter iter;
 
134
        GtkTreePath *path;
 
135
        gboolean set_cursor = FALSE;
 
136
#endif
 
137
 
 
138
        gtk_tree_model_filter_refilter (self->pv->filter);
 
139
 
 
140
#if 0
 
141
        /* Set cursor on the first object. */
 
142
 
 
143
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (self));
 
144
        gtk_tree_view_get_cursor (GTK_TREE_VIEW (view), &path, &focus_column);
 
145
 
 
146
        if (path == NULL) {
 
147
                path = gtk_tree_path_new_from_string ("0");
 
148
                set_cursor = TRUE;
 
149
        }
 
150
 
 
151
        if (set_cursor) {
 
152
                /* FIXME: Workaround for GTK bug #621651, we have to make sure
 
153
                 * the path is valid. */
 
154
                if (gtk_tree_model_get_iter (model, &iter, path)) {
 
155
                        gtk_tree_view_set_cursor (GTK_TREE_VIEW (view), path,
 
156
                                focus_column, FALSE);
 
157
                }
 
158
        }
 
159
 
 
160
        gtk_tree_path_free (path);
 
161
#endif
 
162
}
 
163
 
 
164
static void
 
165
on_search_widget_activate (GtkWidget *search, gpointer user_data)
 
166
{
 
167
        GcrListSelector *self = GCR_LIST_SELECTOR (user_data);
 
168
        GtkTreePath *path;
 
169
        GtkTreeViewColumn *focus_column;
 
170
 
 
171
        gtk_tree_view_get_cursor (GTK_TREE_VIEW (self), &path, &focus_column);
 
172
        if (path != NULL) {
 
173
                gtk_tree_view_row_activated (GTK_TREE_VIEW (self), path, focus_column);
 
174
                gtk_tree_path_free (path);
 
175
 
 
176
                gtk_widget_hide (search);
 
177
        }
 
178
}
 
179
 
 
180
static gboolean
 
181
on_search_widget_key_navigation (GtkWidget *search, GdkEvent *event, gpointer user_data)
 
182
{
 
183
        GcrListSelector *self = GCR_LIST_SELECTOR (user_data);
 
184
        GdkEvent *new_event;
 
185
        gboolean ret = FALSE;
 
186
 
 
187
        new_event = gdk_event_copy (event);
 
188
        gtk_widget_grab_focus (GTK_WIDGET (self));
 
189
        ret = gtk_widget_event (GTK_WIDGET (self), new_event);
 
190
        gtk_widget_grab_focus (search);
 
191
 
 
192
        gdk_event_free (new_event);
 
193
 
 
194
        return ret;
 
195
}
 
196
 
 
197
static void
 
198
on_check_column_toggled (GtkCellRendererToggle *cell, gchar *path, gpointer user_data)
 
199
{
 
200
        GcrListSelector *self = GCR_LIST_SELECTOR (user_data);
 
201
        GtkTreeIter iter, model_iter;
 
202
 
 
203
        g_assert (path != NULL);
 
204
 
 
205
        if (gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (self->pv->filter), &iter, path)) {
 
206
                gtk_tree_model_filter_convert_iter_to_child_iter (self->pv->filter, &model_iter, &iter);
 
207
                gcr_collection_model_toggle_selected (self->pv->model, &model_iter);
 
208
        }
 
209
}
 
210
 
 
211
static void
 
212
gcr_list_selector_constructed (GObject *object)
 
213
{
 
214
        GcrListSelector *self = GCR_LIST_SELECTOR (object);
 
215
        GtkCellRenderer *cell;
 
216
        GtkTreeViewColumn *column;
 
217
        guint column_id;
 
218
 
 
219
        G_OBJECT_CLASS (gcr_list_selector_parent_class)->constructed (object);
 
220
 
 
221
        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (self), FALSE);
 
222
 
 
223
        self->pv->model = gcr_collection_model_new (self->pv->collection,
 
224
                                                    "icon", G_TYPE_ICON,
 
225
                                                    "markup", G_TYPE_STRING,
 
226
                                                    NULL);
 
227
 
 
228
        self->pv->filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (
 
229
                                                  GTK_TREE_MODEL (self->pv->model), NULL));
 
230
        gtk_tree_model_filter_set_visible_func (self->pv->filter,
 
231
                                                on_tree_filter_visible_func, self, NULL);
 
232
 
 
233
        gtk_tree_view_set_model (GTK_TREE_VIEW (self), GTK_TREE_MODEL (self->pv->filter));
 
234
 
 
235
        /* The check */
 
236
 
 
237
        cell = gtk_cell_renderer_toggle_new ();
 
238
        g_signal_connect (cell, "toggled", G_CALLBACK (on_check_column_toggled), self);
 
239
 
 
240
        column_id = gcr_collection_model_column_for_selected (self->pv->model);
 
241
        column = gtk_tree_view_column_new_with_attributes ("", cell, "active", column_id, NULL);
 
242
        gtk_tree_view_column_set_resizable (column, FALSE);
 
243
        gtk_tree_view_append_column (GTK_TREE_VIEW (self), column);
 
244
 
 
245
        column = gtk_tree_view_column_new ();
 
246
 
 
247
        /* The icon */
 
248
        cell = gtk_cell_renderer_pixbuf_new ();
 
249
        g_object_set (cell, "stock-size", GTK_ICON_SIZE_DND, NULL);
 
250
        gtk_tree_view_column_pack_start (column, cell, FALSE);
 
251
        gtk_tree_view_column_add_attribute (column, cell, "gicon", 0);
 
252
 
 
253
        /* The markup */
 
254
        cell = gtk_cell_renderer_text_new ();
 
255
        gtk_tree_view_column_pack_start (column, cell, TRUE);
 
256
        gtk_tree_view_column_add_attribute (column, cell, "markup", 1);
 
257
 
 
258
        gtk_tree_view_append_column (GTK_TREE_VIEW (self), column);
 
259
}
 
260
 
 
261
static void
 
262
gcr_list_selector_init (GcrListSelector *self)
 
263
{
 
264
        self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCR_TYPE_LIST_SELECTOR, GcrListSelectorPrivate);
 
265
}
 
266
 
 
267
static void
 
268
gcr_list_selector_dispose (GObject *obj)
 
269
{
 
270
        GcrListSelector *self = GCR_LIST_SELECTOR (obj);
 
271
 
 
272
        if (self->pv->filter)
 
273
                g_object_unref (self->pv->filter);
 
274
        self->pv->filter = NULL;
 
275
 
 
276
        if (self->pv->model)
 
277
                g_object_unref (self->pv->model);
 
278
        self->pv->model = NULL;
 
279
 
 
280
        if (self->pv->collection)
 
281
                g_object_unref (self->pv->collection);
 
282
        self->pv->collection = NULL;
 
283
 
 
284
        _gcr_list_selector_set_live_search (self, NULL);
 
285
 
 
286
        G_OBJECT_CLASS (gcr_list_selector_parent_class)->dispose (obj);
 
287
}
 
288
 
 
289
static void
 
290
gcr_list_selector_finalize (GObject *obj)
 
291
{
 
292
        GcrListSelector *self = GCR_LIST_SELECTOR (obj);
 
293
 
 
294
        g_assert (!self->pv->collection);
 
295
        g_assert (!self->pv->model);
 
296
 
 
297
        G_OBJECT_CLASS (gcr_list_selector_parent_class)->finalize (obj);
 
298
}
 
299
 
 
300
static void
 
301
gcr_list_selector_set_property (GObject *obj, guint prop_id, const GValue *value,
 
302
                                 GParamSpec *pspec)
 
303
{
 
304
        GcrListSelector *self = GCR_LIST_SELECTOR (obj);
 
305
 
 
306
        switch (prop_id) {
 
307
        case PROP_COLLECTION:
 
308
                g_return_if_fail (!self->pv->collection);
 
309
                self->pv->collection = g_value_dup_object (value);
 
310
                g_return_if_fail (self->pv->collection);
 
311
                break;
 
312
        default:
 
313
                G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 
314
                break;
 
315
        }
 
316
}
 
317
 
 
318
static void
 
319
gcr_list_selector_get_property (GObject *obj, guint prop_id, GValue *value,
 
320
                                 GParamSpec *pspec)
 
321
{
 
322
        GcrListSelector *self = GCR_LIST_SELECTOR (obj);
 
323
 
 
324
        switch (prop_id) {
 
325
        case PROP_COLLECTION:
 
326
                g_value_set_object (value, gcr_list_selector_get_collection (self));
 
327
                break;
 
328
        default:
 
329
                G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 
330
                break;
 
331
        }
 
332
}
 
333
 
 
334
static void
 
335
gcr_list_selector_class_init (GcrListSelectorClass *klass)
 
336
{
 
337
        GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
338
 
 
339
        gobject_class->constructed = gcr_list_selector_constructed;
 
340
        gobject_class->dispose = gcr_list_selector_dispose;
 
341
        gobject_class->finalize = gcr_list_selector_finalize;
 
342
        gobject_class->set_property = gcr_list_selector_set_property;
 
343
        gobject_class->get_property = gcr_list_selector_get_property;
 
344
 
 
345
        g_type_class_add_private (gobject_class, sizeof (GcrListSelectorPrivate));
 
346
 
 
347
        /**
 
348
         * GcrListSelector:collection:
 
349
         *
 
350
         * The collection which contains the objects to display in the selector.
 
351
         */
 
352
        g_object_class_install_property (gobject_class, PROP_COLLECTION,
 
353
                   g_param_spec_object ("collection", "Collection", "Collection to select from",
 
354
                                        GCR_TYPE_COLLECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
355
 
 
356
        _gcr_initialize ();
 
357
}
 
358
 
 
359
/* -----------------------------------------------------------------------------
 
360
 * PUBLIC
 
361
 */
 
362
 
 
363
/**
 
364
 * gcr_selector_new:
 
365
 * @collection: The collection that contains the objects to display
 
366
 *
 
367
 * Create a new #GcrTreeSelector.
 
368
 *
 
369
 * Returns: A newly allocated selector, which should be released with
 
370
 *     g_object_unref().
 
371
 */
 
372
GcrListSelector*
 
373
gcr_list_selector_new (GcrCollection *collection)
 
374
{
 
375
        return g_object_new (GCR_TYPE_LIST_SELECTOR,
 
376
                             "collection", collection,
 
377
                             NULL);
 
378
}
 
379
 
 
380
/**
 
381
 * gcr_list_selector_get_collection:
 
382
 * @self: The selector
 
383
 *
 
384
 * Get the collection that this selector is displaying objects from.
 
385
 *
 
386
 * Returns: The collection, owned by the selector.
 
387
 */
 
388
GcrCollection*
 
389
gcr_list_selector_get_collection (GcrListSelector *self)
 
390
{
 
391
        g_return_val_if_fail (GCR_IS_LIST_SELECTOR (self), NULL);
 
392
        return self->pv->collection;
 
393
}
 
394
 
 
395
/**
 
396
 * gcr_list_selector_get_selected:
 
397
 * @self: The selector
 
398
 *
 
399
 * Get a list of selected objects.
 
400
 *
 
401
 * Returns: The list of selected objects, to be released with g_list_free().
 
402
 */
 
403
GList*
 
404
gcr_list_selector_get_selected (GcrListSelector *self)
 
405
{
 
406
        g_return_val_if_fail (GCR_IS_LIST_SELECTOR (self), NULL);
 
407
        return gcr_collection_model_get_selected_objects (self->pv->model);
 
408
}
 
409
 
 
410
/**
 
411
 * gcr_list_selector_set_selected:
 
412
 * @self: The selector
 
413
 * @selected: The list of objects to select.
 
414
 *
 
415
 * Select certain objects in the selector.
 
416
 */
 
417
void
 
418
gcr_list_selector_set_selected (GcrListSelector *self, GList *selected)
 
419
{
 
420
        g_return_if_fail (GCR_IS_LIST_SELECTOR (self));
 
421
        gcr_collection_model_set_selected_objects (self->pv->model, selected);
 
422
}
 
423
 
 
424
 
 
425
void
 
426
_gcr_list_selector_set_live_search (GcrListSelector *self, GcrLiveSearch *search)
 
427
{
 
428
        g_return_if_fail (GCR_IS_LIST_SELECTOR (self));
 
429
 
 
430
        /* remove old handlers if old search was not null */
 
431
        if (self->pv->search_widget != NULL) {
 
432
                g_signal_handlers_disconnect_by_func (self, on_tree_view_start_search, NULL);
 
433
 
 
434
                g_signal_handlers_disconnect_by_func (self->pv->search_widget,
 
435
                        on_search_widget_text_notify, self);
 
436
                g_signal_handlers_disconnect_by_func (self->pv->search_widget,
 
437
                        on_search_widget_activate, self);
 
438
                g_signal_handlers_disconnect_by_func (self->pv->search_widget,
 
439
                        on_search_widget_key_navigation, self);
 
440
                g_object_unref (self->pv->search_widget);
 
441
                self->pv->search_widget = NULL;
 
442
        }
 
443
 
 
444
        /* connect handlers if new search is not null */
 
445
        if (search != NULL) {
 
446
                self->pv->search_widget = g_object_ref (search);
 
447
 
 
448
                g_signal_connect (self, "start-interactive-search",
 
449
                                  G_CALLBACK (on_tree_view_start_search), NULL);
 
450
 
 
451
                g_signal_connect (self->pv->search_widget, "notify::text",
 
452
                        G_CALLBACK (on_search_widget_text_notify), self);
 
453
                g_signal_connect (self->pv->search_widget, "activate",
 
454
                        G_CALLBACK (on_search_widget_activate), self);
 
455
                g_signal_connect (self->pv->search_widget, "key-navigation",
 
456
                        G_CALLBACK (on_search_widget_key_navigation), self);
 
457
        }
 
458
}