4
* Copyright (C) 2006 Stefan Walter
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
* See the GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the
17
* Free Software Foundation, Inc.,
18
* 59 Temple Place, Suite 330,
19
* Boston, MA 02111-1307, USA.
26
#include "seahorse-object-model.h"
27
#include "seahorse-marshal.h"
29
#include "common/seahorse-bind.h"
41
static guint signals[LAST_SIGNAL] = { 0 };
43
typedef struct _SeahorseObjectModelPrivate {
46
} SeahorseObjectModelPrivate;
48
G_DEFINE_TYPE (SeahorseObjectModel, seahorse_object_model, GTK_TYPE_TREE_STORE);
50
#define SEAHORSE_OBJECT_MODEL_GET_PRIVATE(obj) \
51
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), SEAHORSE_TYPE_OBJECT_MODEL, SeahorseObjectModelPrivate))
53
/* Internal data stored at 0 in the tree store in order to keep track
54
* of the location, key-store and key.
57
SeahorseObjectModel *self;
58
GPtrArray *refs; /* GtkTreeRowReference pointers */
59
SeahorseObject *object; /* The key we're dealing with */
63
/* -----------------------------------------------------------------------------
68
key_notify (SeahorseObject *object, SeahorseObjectModel *self)
70
SeahorseObjectModelPrivate *pv = SEAHORSE_OBJECT_MODEL_GET_PRIVATE (self);
71
SeahorseObjectRow *skrow;
76
skrow = g_hash_table_lookup (pv->rows, object);
80
for (i = 0; i < skrow->refs->len; i++) {
82
path = gtk_tree_row_reference_get_path (g_ptr_array_index (skrow->refs, i));
84
gtk_tree_model_get_iter (GTK_TREE_MODEL (self), &iter, path);
85
g_signal_emit (self, signals[UPDATE_ROW], 0, object, &iter);
86
gtk_tree_path_free (path);
92
key_destroyed (gpointer data, GObject *was)
94
SeahorseObjectModelPrivate *pv = SEAHORSE_OBJECT_MODEL_GET_PRIVATE (data);
95
SeahorseObjectRow *skrow = g_hash_table_lookup (pv->rows, was);
98
skrow->binding = NULL;
99
g_hash_table_remove (pv->rows, was);
105
remove_each (SeahorseObject *object, gchar *path, SeahorseObjectModel *self)
110
static SeahorseObjectRow*
111
key_row_new (SeahorseObjectModel *self, SeahorseObject *object)
113
SeahorseObjectRow *skrow;
115
g_assert (SEAHORSE_IS_OBJECT_MODEL (self));
116
g_assert (SEAHORSE_IS_OBJECT (object));
118
skrow = g_new0 (SeahorseObjectRow, 1);
119
skrow->refs = g_ptr_array_new ();
121
skrow->object = object;
122
skrow->binding = seahorse_bind_objects (NULL, object, (SeahorseTransfer)key_notify, self);
124
g_object_weak_ref (G_OBJECT (object), key_destroyed, self);
130
key_row_free (SeahorseObjectRow *skrow)
132
SeahorseObjectModel *self = skrow->self;
133
SeahorseObjectModelPrivate *pv = SEAHORSE_OBJECT_MODEL_GET_PRIVATE (self);
134
GtkTreeRowReference *ref;
139
g_return_if_fail (pv->data_column != -1);
141
for (i = 0; i < skrow->refs->len; i++) {
143
ref = (GtkTreeRowReference*)g_ptr_array_index (skrow->refs, i);
145
path = gtk_tree_row_reference_get_path (ref);
147
gtk_tree_model_get_iter (GTK_TREE_MODEL (self), &iter, path);
148
gtk_tree_store_set (GTK_TREE_STORE (self), &iter,
149
pv->data_column, NULL, -1);
150
gtk_tree_path_free (path);
152
gtk_tree_row_reference_free (ref);
158
seahorse_bind_disconnect (skrow->binding);
160
g_object_weak_unref (G_OBJECT (skrow->object), key_destroyed, skrow->self);
162
g_ptr_array_free (skrow->refs, TRUE);
167
row_inserted (SeahorseObjectModel *self, GtkTreePath *path, GtkTreeIter *iter,
170
SeahorseObjectModelPrivate *pv = SEAHORSE_OBJECT_MODEL_GET_PRIVATE (self);
171
g_return_if_fail (pv->data_column != -1);
172
/* XXX: The following line causes problems with GtkTreeModelFilter */
173
/* gtk_tree_store_set (GTK_TREE_STORE (self), iter, pv->data_column, NULL, -1); */
176
/* -----------------------------------------------------------------------------
181
seahorse_object_model_init (SeahorseObjectModel *self)
183
SeahorseObjectModelPrivate *pv = SEAHORSE_OBJECT_MODEL_GET_PRIVATE (self);
184
pv->rows = g_hash_table_new_full (g_direct_hash, g_direct_equal,
185
NULL, (GDestroyNotify)key_row_free);
186
pv->data_column = -1;
187
g_signal_connect (self, "row-inserted", G_CALLBACK (row_inserted), NULL);
191
seahorse_object_model_set_property (GObject *gobject, guint prop_id,
192
const GValue *value, GParamSpec *pspec)
194
SeahorseObjectModel *self = SEAHORSE_OBJECT_MODEL (gobject);
195
SeahorseObjectModelPrivate *pv = SEAHORSE_OBJECT_MODEL_GET_PRIVATE (self);
198
case PROP_DATA_COLUMN:
199
g_assert (pv->data_column == -1);
200
pv->data_column = g_value_get_uint (value);
206
seahorse_object_model_get_property (GObject *gobject, guint prop_id,
207
GValue *value, GParamSpec *pspec)
209
SeahorseObjectModel *self = SEAHORSE_OBJECT_MODEL (gobject);
210
SeahorseObjectModelPrivate *pv = SEAHORSE_OBJECT_MODEL_GET_PRIVATE (self);
213
case PROP_DATA_COLUMN:
214
g_value_set_uint (value, pv->data_column);
220
seahorse_object_model_dispose (GObject *gobject)
222
SeahorseObjectModel *self = SEAHORSE_OBJECT_MODEL (gobject);
223
SeahorseObjectModelPrivate *pv = SEAHORSE_OBJECT_MODEL_GET_PRIVATE (self);
225
/* Release all our pointers and stuff */
226
g_hash_table_foreach_remove (pv->rows, (GHRFunc)remove_each, self);
227
G_OBJECT_CLASS (seahorse_object_model_parent_class)->dispose (gobject);
231
seahorse_object_model_finalize (GObject *gobject)
233
SeahorseObjectModel *self = SEAHORSE_OBJECT_MODEL (gobject);
234
SeahorseObjectModelPrivate *pv = SEAHORSE_OBJECT_MODEL_GET_PRIVATE (self);
237
g_hash_table_destroy (pv->rows);
240
G_OBJECT_CLASS (seahorse_object_model_parent_class)->finalize (gobject);
244
seahorse_object_model_class_init (SeahorseObjectModelClass *klass)
246
GObjectClass *gobject_class;
248
seahorse_object_model_parent_class = g_type_class_peek_parent (klass);
249
gobject_class = G_OBJECT_CLASS (klass);
251
gobject_class->dispose = seahorse_object_model_dispose;
252
gobject_class->finalize = seahorse_object_model_finalize;
253
gobject_class->set_property = seahorse_object_model_set_property;
254
gobject_class->get_property = seahorse_object_model_get_property;
256
g_object_class_install_property (gobject_class, PROP_DATA_COLUMN,
257
g_param_spec_uint ("data-column", "Column data is stored", "Column where internal data is stored",
258
0, ~0, 0, G_PARAM_READWRITE | G_PARAM_READWRITE));
260
signals[UPDATE_ROW] = g_signal_new ("update-row", SEAHORSE_TYPE_OBJECT_MODEL,
261
G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SeahorseObjectModelClass, update_row),
262
NULL, NULL, seahorse_marshal_VOID__OBJECT_POINTER, G_TYPE_NONE, 2, SEAHORSE_TYPE_OBJECT, G_TYPE_POINTER);
264
g_type_class_add_private (klass, sizeof (SeahorseObjectModelPrivate));
267
/* -----------------------------------------------------------------------------
273
seahorse_object_model_new (gint n_columns, GType *types)
275
SeahorseObjectModel *model;
277
model = g_object_new (SEAHORSE_TYPE_OBJECT_MODEL, NULL);
278
seahorse_object_model_set_column_types (model, n_columns, types);
284
seahorse_object_model_set_column_types (SeahorseObjectModel *self, gint n_columns,
287
SeahorseObjectModelPrivate *pv = SEAHORSE_OBJECT_MODEL_GET_PRIVATE (self);
290
g_return_if_fail (SEAHORSE_IS_OBJECT_MODEL (self));
292
itypes = g_new0(GType, n_columns + 1);
293
memcpy (itypes, types, n_columns * sizeof (GType));
295
itypes[n_columns] = G_TYPE_POINTER;
296
pv->data_column = n_columns;
297
gtk_tree_store_set_column_types (GTK_TREE_STORE (self), n_columns + 1, itypes);
303
seahorse_object_model_set_row_object (SeahorseObjectModel *self, GtkTreeIter *iter,
304
SeahorseObject *object)
306
SeahorseObjectModelPrivate *pv = SEAHORSE_OBJECT_MODEL_GET_PRIVATE (self);
307
SeahorseObjectRow *skrow;
312
g_return_if_fail (SEAHORSE_IS_OBJECT_MODEL (self));
313
g_return_if_fail (SEAHORSE_IS_OBJECT (object) || object == NULL);
314
g_return_if_fail (pv->data_column >= 0);
316
/* Add the row/key association */
319
/* Do we already have a row for this key? */
320
skrow = (SeahorseObjectRow*)g_hash_table_lookup (pv->rows, object);
322
skrow = key_row_new (self, object);
324
/* Put it in our row cache */
325
g_hash_table_replace (pv->rows, object, skrow);
328
path = gtk_tree_model_get_path (GTK_TREE_MODEL (self), iter);
329
g_ptr_array_add (skrow->refs, gtk_tree_row_reference_new (GTK_TREE_MODEL (self), path));
330
gtk_tree_path_free (path);
332
/* Remove the row/key association */
335
gtk_tree_model_get (GTK_TREE_MODEL (self), iter, pv->data_column, &skrow, -1);
338
ipath = gtk_tree_model_get_path (GTK_TREE_MODEL (self), iter);
339
g_return_if_fail (ipath != NULL);
341
for (i = 0; i < skrow->refs->len; i++) {
343
path = gtk_tree_row_reference_get_path (g_ptr_array_index (skrow->refs, i));
345
/* Check if they're the same or invalid, remove */
346
if (!path || gtk_tree_path_compare (path, ipath) == 0) {
347
gtk_tree_row_reference_free (g_ptr_array_index (skrow->refs, i));
348
g_ptr_array_remove_index_fast (skrow->refs, i);
353
gtk_tree_path_free (path);
356
/* If we no longer have rows associated with this key, then remove */
357
if (skrow->refs->len == 0)
358
g_hash_table_remove (pv->rows, skrow->object);
362
gtk_tree_store_set (GTK_TREE_STORE (self), iter,
363
pv->data_column, object ? skrow : NULL, -1);
366
key_notify (object, self);
370
seahorse_object_model_get_row_key (SeahorseObjectModel *self, GtkTreeIter *iter)
372
SeahorseObjectModelPrivate *pv = SEAHORSE_OBJECT_MODEL_GET_PRIVATE (self);
373
SeahorseObjectRow *skrow;
375
g_return_val_if_fail (SEAHORSE_IS_OBJECT_MODEL (self), NULL);
376
g_return_val_if_fail (pv->data_column >= 0, NULL);
378
gtk_tree_model_get (GTK_TREE_MODEL (self), iter, pv->data_column, &skrow, -1);
381
g_assert (SEAHORSE_IS_OBJECT (skrow->object));
382
return skrow->object;
386
seahorse_object_model_remove_rows_for_object (SeahorseObjectModel *self, SeahorseObject *object)
388
SeahorseObjectModelPrivate *pv = SEAHORSE_OBJECT_MODEL_GET_PRIVATE (self);
389
SeahorseObjectRow *skrow;
394
g_return_if_fail (SEAHORSE_IS_OBJECT_MODEL (self));
395
g_return_if_fail (SEAHORSE_IS_OBJECT (object));
396
g_return_if_fail (pv->data_column >= 0);
398
skrow = (SeahorseObjectRow*)g_hash_table_lookup (pv->rows, object);
402
for (i = 0; i < skrow->refs->len; i++) {
404
path = gtk_tree_row_reference_get_path (g_ptr_array_index (skrow->refs, i));
406
gtk_tree_model_get_iter (GTK_TREE_MODEL (self), &iter, path);
407
gtk_tree_store_remove (GTK_TREE_STORE (self), &iter);
408
gtk_tree_path_free (path);
412
/* We no longer have rows associated with this key, then remove */
413
g_hash_table_remove (pv->rows, object);
417
seahorse_object_model_get_rows_for_object (SeahorseObjectModel *self, SeahorseObject *object)
419
SeahorseObjectModelPrivate *pv = SEAHORSE_OBJECT_MODEL_GET_PRIVATE (self);
421
SeahorseObjectRow *skrow;
426
g_return_val_if_fail (SEAHORSE_IS_OBJECT_MODEL (self), NULL);
427
g_return_val_if_fail (SEAHORSE_IS_OBJECT (object), NULL);
429
skrow = (SeahorseObjectRow*)g_hash_table_lookup (pv->rows, object);
433
for (i = 0; i < skrow->refs->len; i++) {
435
path = gtk_tree_row_reference_get_path (g_ptr_array_index (skrow->refs, i));
437
iter = g_new0(GtkTreeIter, 1);
438
gtk_tree_model_get_iter (GTK_TREE_MODEL (self), iter, path);
439
rows = g_slist_prepend (rows, iter);
440
gtk_tree_path_free (path);
448
seahorse_object_model_free_rows (GSList *rows)
451
for (l = rows; l; l = g_slist_next (l))