1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
/* e-source-option-menu.c
4
* Copyright (C) 2007 Novell, Inc.
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of version 2 of the GNU Lesser General Public
8
* License as published by the Free Software Foundation.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* General Public License for more details.
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this program; if not, write to the
17
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
* Boston, MA 02111-1307, USA.
25
#include "e-source-combo-box.h"
26
#include "e-cell-renderer-color.h"
28
#define E_SOURCE_COMBO_BOX_GET_PRIVATE(obj) \
29
(G_TYPE_INSTANCE_GET_PRIVATE \
30
((obj), E_TYPE_SOURCE_COMBO_BOX, ESourceComboBoxPrivate))
32
struct _ESourceComboBoxPrivate {
33
ESourceList *source_list;
34
GHashTable *uid_index;
44
COLUMN_COLOR, /* GDK_TYPE_COLOR */
45
COLUMN_NAME, /* G_TYPE_STRING */
46
COLUMN_SENSITIVE, /* G_TYPE_BOOLEAN */
47
COLUMN_SOURCE, /* G_TYPE_OBJECT */
48
COLUMN_VISIBLE, /* G_TYPE_BOOLEAN */
52
static gpointer parent_class = NULL;
55
* compare_source_names
56
* Compares sources by name.
59
compare_source_names (gconstpointer a, gconstpointer b)
61
g_return_val_if_fail (E_IS_SOURCE (a), -1);
62
g_return_val_if_fail (E_IS_SOURCE (b), 1);
64
return g_utf8_collate (e_source_peek_name (E_SOURCE (a)), e_source_peek_name (E_SOURCE (b)));
69
* Creates copy of GSList of sources (do not increase reference count for data members),
70
* and sorts this list alphabetically by source names.
72
* @param sources List of sources.
73
* @return New GSList of sorted sources, should be freed by g_slist_free,
74
* but do not unref data members.
77
get_sorted_sources (GSList *sources)
79
GSList *res = NULL, *p;
84
for (p = sources; p != NULL; p = p->next)
85
res = g_slist_prepend (res, p->data);
87
res = g_slist_sort (res, compare_source_names);
93
source_list_changed_cb (ESourceList *source_list,
94
ESourceComboBox *source_combo_box)
96
ESourceComboBoxPrivate *priv;
97
GtkComboBox *combo_box;
106
gchar *indented_name;
107
gboolean visible = FALSE;
110
priv = source_combo_box->priv;
111
g_hash_table_remove_all (priv->uid_index);
113
combo_box = GTK_COMBO_BOX (source_combo_box);
114
gtk_combo_box_set_active (combo_box, -1);
116
model = gtk_combo_box_get_model (combo_box);
117
store = GTK_LIST_STORE (model);
118
gtk_list_store_clear (store);
120
for (groups = e_source_list_peek_groups (source_list);
121
groups != NULL; groups = groups->next) {
123
/* Only show source groups that have sources. */
124
if (e_source_group_peek_sources (groups->data) == NULL)
127
name = e_source_group_peek_name (groups->data);
128
gtk_list_store_append (store, &iter);
133
COLUMN_SENSITIVE, FALSE,
134
COLUMN_SOURCE, groups->data,
137
sources = get_sorted_sources (e_source_group_peek_sources (groups->data));
138
for (s = sources; s != NULL; s = s->next) {
139
const gchar *color_spec;
142
name = e_source_peek_name (s->data);
143
indented_name = g_strconcat (" ", name, NULL);
145
color_spec = e_source_peek_color_spec (s->data);
146
if (color_spec != NULL) {
147
gdk_color_parse (color_spec, &color);
151
gtk_list_store_append (store, &iter);
154
COLUMN_COLOR, color_spec ? &color : NULL,
155
COLUMN_NAME, indented_name,
156
COLUMN_SENSITIVE, TRUE,
157
COLUMN_SOURCE, s->data,
160
uid = e_source_peek_uid (s->data);
161
path = gtk_tree_model_get_path (model, &iter);
162
g_hash_table_insert (
163
priv->uid_index, g_strdup (uid),
164
gtk_tree_row_reference_new (model, path));
165
gtk_tree_path_free (path);
167
g_free (indented_name);
169
g_slist_free (sources);
172
/* Set the visible column based on whether we've seen a color. */
173
iter_valid = gtk_tree_model_get_iter_first (model, &iter);
176
store, &iter, COLUMN_VISIBLE, visible, -1);
177
iter_valid = gtk_tree_model_iter_next (model, &iter);
182
e_source_combo_box_constructor (GType type, guint n_construct_properties,
183
GObjectConstructParam *construct_properties)
185
GtkCellRenderer *renderer;
189
/* Chain up to parent's "constructor" method. */
190
object = G_OBJECT_CLASS (parent_class)->constructor (
191
type, n_construct_properties, construct_properties);
193
store = gtk_list_store_new (
195
GDK_TYPE_COLOR, /* COLUMN_COLOR */
196
G_TYPE_STRING, /* COLUMN_NAME */
197
G_TYPE_BOOLEAN, /* COLUMN_SENSITIVE */
198
G_TYPE_OBJECT, /* COLUMN_SOURCE */
199
G_TYPE_BOOLEAN); /* COLUMN_VISIBLE */
200
gtk_combo_box_set_model (
201
GTK_COMBO_BOX (object), GTK_TREE_MODEL (store));
203
renderer = e_cell_renderer_color_new ();
204
gtk_cell_layout_pack_start (
205
GTK_CELL_LAYOUT (object), renderer, FALSE);
206
gtk_cell_layout_set_attributes (
207
GTK_CELL_LAYOUT (object), renderer,
208
"color", COLUMN_COLOR,
209
"sensitive", COLUMN_SENSITIVE,
210
"visible", COLUMN_VISIBLE,
213
renderer = gtk_cell_renderer_text_new ();
214
gtk_cell_layout_pack_start (
215
GTK_CELL_LAYOUT (object), renderer, TRUE);
216
gtk_cell_layout_set_attributes (
217
GTK_CELL_LAYOUT (object), renderer,
219
"sensitive", COLUMN_SENSITIVE,
226
e_source_combo_box_set_property (GObject *object,
231
ESourceComboBoxPrivate *priv;
233
priv = E_SOURCE_COMBO_BOX_GET_PRIVATE (object);
235
switch (property_id) {
236
case PROP_SOURCE_LIST:
238
if (priv->source_list != NULL) {
239
g_signal_handler_disconnect (
240
priv->source_list, priv->handler_id);
241
g_object_unref (priv->source_list);
244
priv->source_list = g_value_dup_object (value);
246
/* Reset the tree store. */
247
source_list_changed_cb (
249
E_SOURCE_COMBO_BOX (object));
251
/* Watch for source list changes. */
252
priv->handler_id = g_signal_connect_object (
253
priv->source_list, "changed",
254
G_CALLBACK (source_list_changed_cb),
260
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
264
e_source_combo_box_get_property (GObject *object,
269
ESourceComboBoxPrivate *priv;
271
priv = E_SOURCE_COMBO_BOX_GET_PRIVATE (object);
273
switch (property_id) {
274
case PROP_SOURCE_LIST:
275
g_value_set_object (value, priv->source_list);
279
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
283
e_source_combo_box_dispose (GObject *object)
285
ESourceComboBoxPrivate *priv;
287
priv = E_SOURCE_COMBO_BOX_GET_PRIVATE (object);
289
if (priv->source_list != NULL) {
290
g_object_unref (priv->source_list);
291
priv->source_list = NULL;
294
g_hash_table_remove_all (priv->uid_index);
296
/* Chain up to parent's "dispose" method. */
297
G_OBJECT_CLASS (parent_class)->dispose (object);
301
e_source_combo_box_finalize (GObject *object)
303
ESourceComboBoxPrivate *priv;
305
priv = E_SOURCE_COMBO_BOX_GET_PRIVATE (object);
307
g_hash_table_destroy (priv->uid_index);
309
/* Chain up to parent's "finalize" method. */
310
G_OBJECT_CLASS (parent_class)->finalize (object);
314
e_source_combo_box_class_init (ESourceComboBoxClass *class)
316
GObjectClass *object_class = G_OBJECT_CLASS (class);
318
parent_class = g_type_class_peek_parent (class);
320
g_type_class_add_private (class, sizeof (ESourceComboBox));
322
object_class->constructor = e_source_combo_box_constructor;
323
object_class->set_property = e_source_combo_box_set_property;
324
object_class->get_property = e_source_combo_box_get_property;
325
object_class->dispose = e_source_combo_box_dispose;
326
object_class->finalize = e_source_combo_box_finalize;
328
g_object_class_install_property (
331
g_param_spec_object (
334
"List of sources to choose from",
340
e_source_combo_box_init (ESourceComboBox *source_combo_box)
342
source_combo_box->priv =
343
E_SOURCE_COMBO_BOX_GET_PRIVATE (source_combo_box);
345
source_combo_box->priv->uid_index =
346
g_hash_table_new_full (
347
g_str_hash, g_str_equal,
348
(GDestroyNotify) g_free,
349
(GDestroyNotify) gtk_tree_row_reference_free);
353
e_source_combo_box_get_type (void)
355
static GType type = 0;
357
if (G_UNLIKELY (type == 0)) {
358
static const GTypeInfo type_info = {
359
sizeof (ESourceComboBoxClass),
360
(GBaseInitFunc) NULL,
361
(GBaseFinalizeFunc) NULL,
362
(GClassInitFunc) e_source_combo_box_class_init,
363
(GClassFinalizeFunc) NULL,
364
NULL, /* class_data */
365
sizeof (ESourceComboBox),
367
(GInstanceInitFunc) e_source_combo_box_init,
368
NULL /* value_table */
371
type = g_type_register_static (
372
GTK_TYPE_COMBO_BOX, "ESourceComboBox", &type_info, 0);
379
* e_source_combo_box_new:
380
* @source_list: an #ESourceList
382
* Creates a new #ESourceComboBox widget that lets the user pick an #ESource
383
* from the provided #ESourceList.
385
* Returns: a new #ESourceComboBox
388
e_source_combo_box_new (ESourceList *source_list)
390
g_return_val_if_fail (E_IS_SOURCE_LIST (source_list), NULL);
392
return g_object_new (
393
E_TYPE_SOURCE_COMBO_BOX,
394
"source-list", source_list, NULL);
398
* e_source_combo_box_get_source_list:
399
* @source_combo_box: an #ESourceComboBox
401
* Returns the #ESourceList which is acting as a data source for
404
* Returns: an #ESourceList
407
e_source_combo_box_get_source_list (ESourceComboBox *source_combo_box)
409
ESourceList *source_list;
411
g_return_val_if_fail (E_IS_SOURCE_COMBO_BOX (source_combo_box), NULL);
413
g_object_get (source_combo_box, "source-list", &source_list, NULL);
419
* e_source_combo_box_set_source_list:
420
* @source_combo_box: an #ESourceComboBox
421
* @source_list: an #ESourceList
423
* Sets the source list used by @source_combo_box to be @source_list. This
424
* causes the contents of @source_combo_box to be regenerated.
427
e_source_combo_box_set_source_list (ESourceComboBox *source_combo_box,
428
ESourceList *source_list)
430
g_return_if_fail (E_IS_SOURCE_COMBO_BOX (source_combo_box));
431
g_return_if_fail (E_IS_SOURCE_LIST (source_list));
433
g_object_set (source_combo_box, "source-list", source_list, NULL);
437
* e_source_combo_box_get_active:
438
* @source_combo_box: an #ESourceComboBox
440
* Returns the #ESource corresponding to the currently active item, or %NULL
441
* if there is no active item.
443
* Returns: an #ESource or %NULL
446
e_source_combo_box_get_active (ESourceComboBox *source_combo_box)
448
GtkComboBox *combo_box;
452
g_return_val_if_fail (E_IS_SOURCE_COMBO_BOX (source_combo_box), NULL);
454
combo_box = GTK_COMBO_BOX (source_combo_box);
456
if (!gtk_combo_box_get_active_iter (combo_box, &iter))
460
gtk_combo_box_get_model (combo_box),
461
&iter, COLUMN_SOURCE, &source, -1);
467
* e_source_combo_box_set_active:
468
* @source_combo_box: an #ESourceComboBox
469
* @source: an #ESource
471
* Sets the active item to the one corresponding to @source.
474
e_source_combo_box_set_active (ESourceComboBox *source_combo_box,
477
g_return_if_fail (E_IS_SOURCE_COMBO_BOX (source_combo_box));
478
g_return_if_fail (E_IS_SOURCE (source));
480
e_source_combo_box_set_active_uid (
481
source_combo_box, e_source_peek_uid (source));
485
* e_source_combo_box_get_active_uid:
486
* @source_combo_box: an #ESourceComboBox
488
* Returns the unique ID of the #ESource corresponding to the currently
489
* active item, or %NULL if there is no active item.
491
* Returns: a unique ID string or %NULL
494
e_source_combo_box_get_active_uid (ESourceComboBox *source_combo_box)
498
g_return_val_if_fail (E_IS_SOURCE_COMBO_BOX (source_combo_box), NULL);
500
source = e_source_combo_box_get_active (source_combo_box);
504
return e_source_peek_uid (source);
508
* e_source_combo_box_set_active_uid:
509
* @source_combo_box: an #ESourceComboBox
510
* @uid: a unique ID of an #ESource
512
* Sets the active item to the one corresponding to @uid.
515
e_source_combo_box_set_active_uid (ESourceComboBox *source_combo_box,
518
ESourceComboBoxPrivate *priv;
519
GtkTreeRowReference *reference;
520
GtkComboBox *combo_box;
522
gboolean iter_was_set;
524
g_return_if_fail (E_IS_SOURCE_COMBO_BOX (source_combo_box));
525
g_return_if_fail (uid != NULL);
527
priv = source_combo_box->priv;
528
combo_box = GTK_COMBO_BOX (source_combo_box);
530
reference = g_hash_table_lookup (priv->uid_index, uid);
531
g_return_if_fail (gtk_tree_row_reference_valid (reference));
533
iter_was_set = gtk_tree_model_get_iter (
534
gtk_combo_box_get_model (combo_box), &iter,
535
gtk_tree_row_reference_get_path (reference));
536
g_return_if_fail (iter_was_set);
538
gtk_combo_box_set_active_iter (combo_box, &iter);