1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /* e-source-combo-box.c
3  *
4  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this program; if not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "evolution-config.h"
20 
21 #include <libedataserverui/libedataserverui.h>
22 
23 #include "e-source-combo-box.h"
24 
25 #define E_SOURCE_COMBO_BOX_GET_PRIVATE(obj) \
26 	(G_TYPE_INSTANCE_GET_PRIVATE \
27 	((obj), E_TYPE_SOURCE_COMBO_BOX, ESourceComboBoxPrivate))
28 
29 struct _ESourceComboBoxPrivate {
30 	ESourceRegistry *registry;
31 	gchar *extension_name;
32 	GHashTable *hide_sources;
33 
34 	gulong source_added_handler_id;
35 	gulong source_removed_handler_id;
36 	gulong source_enabled_handler_id;
37 	gulong source_disabled_handler_id;
38 
39 	gboolean show_colors;
40 };
41 
42 enum {
43 	PROP_0,
44 	PROP_EXTENSION_NAME,
45 	PROP_REGISTRY,
46 	PROP_SHOW_COLORS
47 };
48 
49 enum {
50 	COLUMN_COLOR,		/* GDK_TYPE_RGBA */
51 	COLUMN_NAME,		/* G_TYPE_STRING */
52 	COLUMN_SENSITIVE,	/* G_TYPE_BOOLEAN */
53 	COLUMN_UID,		/* G_TYPE_STRING */
54 	NUM_COLUMNS
55 };
56 
G_DEFINE_TYPE(ESourceComboBox,e_source_combo_box,GTK_TYPE_COMBO_BOX)57 G_DEFINE_TYPE (ESourceComboBox, e_source_combo_box, GTK_TYPE_COMBO_BOX)
58 
59 static gboolean
60 source_combo_box_traverse (GNode *node,
61                            ESourceComboBox *combo_box)
62 {
63 	ESource *source;
64 	ESourceSelectable *extension = NULL;
65 	GtkTreeModel *model;
66 	GtkTreeIter iter;
67 	GString *indented;
68 	GdkRGBA rgba;
69 	const gchar *ext_name;
70 	const gchar *display_name;
71 	const gchar *uid;
72 	gboolean sensitive = FALSE;
73 	gboolean use_color = FALSE;
74 	guint depth;
75 
76 	/* Skip the root node. */
77 	if (G_NODE_IS_ROOT (node))
78 		return FALSE;
79 
80 	ext_name = e_source_combo_box_get_extension_name (combo_box);
81 
82 	source = E_SOURCE (node->data);
83 
84 	if (ext_name != NULL && e_source_has_extension (source, ext_name)) {
85 		extension = e_source_get_extension (source, ext_name);
86 		sensitive = TRUE;
87 
88 		if (g_hash_table_size (combo_box->priv->hide_sources) && E_IS_SOURCE_BACKEND (extension)) {
89 			ESourceBackend *backend = E_SOURCE_BACKEND (extension);
90 
91 			if (e_source_backend_get_backend_name (backend) &&
92 			    g_hash_table_contains (combo_box->priv->hide_sources, e_source_backend_get_backend_name (backend))) {
93 				return FALSE;
94 			}
95 		}
96 	}
97 
98 	uid = e_source_get_uid (source);
99 
100 	if (g_hash_table_contains (combo_box->priv->hide_sources, uid) || (e_source_get_parent (source) &&
101 	    g_hash_table_contains (combo_box->priv->hide_sources, e_source_get_parent (source)))) {
102 		return FALSE;
103 	}
104 
105 	display_name = e_source_get_display_name (source);
106 
107 	model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
108 	gtk_list_store_append (GTK_LIST_STORE (model), &iter);
109 
110 	indented = g_string_new (NULL);
111 
112 	depth = g_node_depth (node);
113 	g_warn_if_fail (depth > 1);
114 	while (--depth > 1)
115 		g_string_append (indented, "    ");
116 	g_string_append (indented, display_name);
117 
118 	if (E_IS_SOURCE_SELECTABLE (extension)) {
119 		const gchar *color_spec;
120 
121 		color_spec = e_source_selectable_get_color (extension);
122 		if (color_spec != NULL && *color_spec != '\0')
123 			use_color = gdk_rgba_parse (&rgba, color_spec);
124 	}
125 
126 	gtk_list_store_set (
127 		GTK_LIST_STORE (model), &iter,
128 		COLUMN_COLOR, use_color ? &rgba : NULL,
129 		COLUMN_NAME, indented->str,
130 		COLUMN_SENSITIVE, sensitive,
131 		COLUMN_UID, uid,
132 		-1);
133 
134 	g_string_free (indented, TRUE);
135 
136 	return FALSE;
137 }
138 
139 static void
source_combo_box_build_model(ESourceComboBox * combo_box)140 source_combo_box_build_model (ESourceComboBox *combo_box)
141 {
142 	ESourceRegistry *registry;
143 	GtkComboBox *gtk_combo_box;
144 	GtkTreeModel *model;
145 	GNode *root;
146 	const gchar *active_id;
147 	const gchar *extension_name;
148 
149 	registry = e_source_combo_box_get_registry (combo_box);
150 	extension_name = e_source_combo_box_get_extension_name (combo_box);
151 
152 	gtk_combo_box = GTK_COMBO_BOX (combo_box);
153 	model = gtk_combo_box_get_model (gtk_combo_box);
154 
155 	/* Constructor properties trigger this function before the
156 	 * list store is configured.  Detect it and return silently. */
157 	if (model == NULL)
158 		return;
159 
160 	/* Remember the active ID so we can try to restore it. */
161 	active_id = gtk_combo_box_get_active_id (gtk_combo_box);
162 
163 	gtk_list_store_clear (GTK_LIST_STORE (model));
164 
165 	/* If we have no registry, leave the combo box empty. */
166 	if (registry == NULL)
167 		return;
168 
169 	/* If we have no extension name, leave the combo box empty. */
170 	if (extension_name == NULL)
171 		return;
172 
173 	root = e_source_registry_build_display_tree (registry, extension_name);
174 
175 	g_node_traverse (
176 		root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
177 		(GNodeTraverseFunc) source_combo_box_traverse,
178 		combo_box);
179 
180 	e_source_registry_free_display_tree (root);
181 
182 	/* Restore the active ID, or else set it to something reasonable. */
183 	gtk_combo_box_set_active_id (gtk_combo_box, active_id);
184 	if (gtk_combo_box_get_active_id (gtk_combo_box) == NULL) {
185 		ESource *source;
186 
187 		source = e_source_registry_ref_default_for_extension_name (
188 			registry, extension_name);
189 		if (source != NULL) {
190 			e_source_combo_box_set_active (combo_box, source);
191 			g_object_unref (source);
192 		}
193 	}
194 
195 	if (!gtk_combo_box_get_active_id (gtk_combo_box)) {
196 		GtkTreeIter iter;
197 
198 		if (gtk_tree_model_get_iter_first (model, &iter)) {
199 			do {
200 				gboolean sensitive = FALSE;
201 
202 				gtk_tree_model_get (model, &iter, COLUMN_SENSITIVE, &sensitive, -1);
203 
204 				if (sensitive) {
205 					gchar *uid = NULL;
206 
207 					gtk_tree_model_get (model, &iter, COLUMN_UID, &uid, -1);
208 
209 					if (uid) {
210 						gtk_combo_box_set_active_id (gtk_combo_box, uid);
211 						g_free (uid);
212 						break;
213 					} else {
214 						g_free (uid);
215 					}
216 				}
217 			} while (gtk_tree_model_iter_next (model, &iter));
218 		}
219 	}
220 }
221 
222 static void
source_combo_box_source_added_cb(ESourceRegistry * registry,ESource * source,ESourceComboBox * combo_box)223 source_combo_box_source_added_cb (ESourceRegistry *registry,
224                                   ESource *source,
225                                   ESourceComboBox *combo_box)
226 {
227 	source_combo_box_build_model (combo_box);
228 }
229 
230 static void
source_combo_box_source_removed_cb(ESourceRegistry * registry,ESource * source,ESourceComboBox * combo_box)231 source_combo_box_source_removed_cb (ESourceRegistry *registry,
232                                     ESource *source,
233                                     ESourceComboBox *combo_box)
234 {
235 	source_combo_box_build_model (combo_box);
236 }
237 
238 static void
source_combo_box_source_enabled_cb(ESourceRegistry * registry,ESource * source,ESourceComboBox * combo_box)239 source_combo_box_source_enabled_cb (ESourceRegistry *registry,
240                                     ESource *source,
241                                     ESourceComboBox *combo_box)
242 {
243 	source_combo_box_build_model (combo_box);
244 }
245 
246 static void
source_combo_box_source_disabled_cb(ESourceRegistry * registry,ESource * source,ESourceComboBox * combo_box)247 source_combo_box_source_disabled_cb (ESourceRegistry *registry,
248                                      ESource *source,
249                                      ESourceComboBox *combo_box)
250 {
251 	source_combo_box_build_model (combo_box);
252 }
253 
254 static void
source_combo_box_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)255 source_combo_box_set_property (GObject *object,
256                                guint property_id,
257                                const GValue *value,
258                                GParamSpec *pspec)
259 {
260 	switch (property_id) {
261 		case PROP_EXTENSION_NAME:
262 			e_source_combo_box_set_extension_name (
263 				E_SOURCE_COMBO_BOX (object),
264 				g_value_get_string (value));
265 			return;
266 
267 		case PROP_REGISTRY:
268 			e_source_combo_box_set_registry (
269 				E_SOURCE_COMBO_BOX (object),
270 				g_value_get_object (value));
271 			return;
272 
273 		case PROP_SHOW_COLORS:
274 			e_source_combo_box_set_show_colors (
275 				E_SOURCE_COMBO_BOX (object),
276 				g_value_get_boolean (value));
277 			return;
278 	}
279 
280 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
281 }
282 
283 static void
source_combo_box_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)284 source_combo_box_get_property (GObject *object,
285                                guint property_id,
286                                GValue *value,
287                                GParamSpec *pspec)
288 {
289 	switch (property_id) {
290 		case PROP_EXTENSION_NAME:
291 			g_value_set_string (
292 				value,
293 				e_source_combo_box_get_extension_name (
294 				E_SOURCE_COMBO_BOX (object)));
295 			return;
296 
297 		case PROP_REGISTRY:
298 			g_value_set_object (
299 				value,
300 				e_source_combo_box_get_registry (
301 				E_SOURCE_COMBO_BOX (object)));
302 			return;
303 
304 		case PROP_SHOW_COLORS:
305 			g_value_set_boolean (
306 				value,
307 				e_source_combo_box_get_show_colors (
308 				E_SOURCE_COMBO_BOX (object)));
309 			return;
310 	}
311 
312 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
313 }
314 
315 static void
source_combo_box_dispose(GObject * object)316 source_combo_box_dispose (GObject *object)
317 {
318 	ESourceComboBoxPrivate *priv;
319 
320 	priv = E_SOURCE_COMBO_BOX_GET_PRIVATE (object);
321 
322 	if (priv->registry != NULL) {
323 		g_signal_handler_disconnect (
324 			priv->registry,
325 			priv->source_added_handler_id);
326 		g_signal_handler_disconnect (
327 			priv->registry,
328 			priv->source_removed_handler_id);
329 		g_signal_handler_disconnect (
330 			priv->registry,
331 			priv->source_enabled_handler_id);
332 		g_signal_handler_disconnect (
333 			priv->registry,
334 			priv->source_disabled_handler_id);
335 		g_object_unref (priv->registry);
336 		priv->registry = NULL;
337 	}
338 
339 	/* Chain up to parent's "dispose" method. */
340 	G_OBJECT_CLASS (e_source_combo_box_parent_class)->dispose (object);
341 }
342 
343 static void
source_combo_box_finalize(GObject * object)344 source_combo_box_finalize (GObject *object)
345 {
346 	ESourceComboBoxPrivate *priv;
347 
348 	priv = E_SOURCE_COMBO_BOX_GET_PRIVATE (object);
349 
350 	g_free (priv->extension_name);
351 	g_hash_table_destroy (priv->hide_sources);
352 
353 	/* Chain up to parent's "finalize" method. */
354 	G_OBJECT_CLASS (e_source_combo_box_parent_class)->finalize (object);
355 }
356 
357 static void
source_combo_box_constructed(GObject * object)358 source_combo_box_constructed (GObject *object)
359 {
360 	ESourceComboBox *combo_box;
361 	GtkCellRenderer *renderer;
362 	GtkCellLayout *layout;
363 	GtkListStore *store;
364 
365 	combo_box = E_SOURCE_COMBO_BOX (object);
366 
367 	/* Chain up to parent's constructed() method. */
368 	G_OBJECT_CLASS (e_source_combo_box_parent_class)->constructed (object);
369 
370 	store = gtk_list_store_new (
371 		NUM_COLUMNS,
372 		GDK_TYPE_RGBA,		/* COLUMN_COLOR */
373 		G_TYPE_STRING,		/* COLUMN_NAME */
374 		G_TYPE_BOOLEAN,		/* COLUMN_SENSITIVE */
375 		G_TYPE_STRING);		/* COLUMN_UID */
376 	gtk_combo_box_set_model (
377 		GTK_COMBO_BOX (combo_box),
378 		GTK_TREE_MODEL (store));
379 	g_object_unref (store);
380 
381 	gtk_combo_box_set_id_column (GTK_COMBO_BOX (combo_box), COLUMN_UID);
382 
383 	layout = GTK_CELL_LAYOUT (combo_box);
384 
385 	renderer = e_cell_renderer_color_new ();
386 	gtk_cell_layout_pack_start (layout, renderer, FALSE);
387 	gtk_cell_layout_set_attributes (
388 		layout, renderer,
389 		"rgba", COLUMN_COLOR,
390 		"sensitive", COLUMN_SENSITIVE,
391 		NULL);
392 
393 	e_binding_bind_property (
394 		combo_box, "show-colors",
395 		renderer, "visible",
396 		G_BINDING_SYNC_CREATE);
397 
398 	renderer = gtk_cell_renderer_text_new ();
399 	gtk_cell_layout_pack_start (layout, renderer, TRUE);
400 	gtk_cell_layout_set_attributes (
401 		layout, renderer,
402 		"text", COLUMN_NAME,
403 		"sensitive", COLUMN_SENSITIVE,
404 		NULL);
405 
406 	source_combo_box_build_model (combo_box);
407 }
408 
409 static void
e_source_combo_box_class_init(ESourceComboBoxClass * class)410 e_source_combo_box_class_init (ESourceComboBoxClass *class)
411 {
412 	GObjectClass *object_class = G_OBJECT_CLASS (class);
413 
414 	g_type_class_add_private (class, sizeof (ESourceComboBoxPrivate));
415 
416 	object_class->set_property = source_combo_box_set_property;
417 	object_class->get_property = source_combo_box_get_property;
418 	object_class->dispose = source_combo_box_dispose;
419 	object_class->finalize = source_combo_box_finalize;
420 	object_class->constructed = source_combo_box_constructed;
421 
422 	g_object_class_install_property (
423 		object_class,
424 		PROP_EXTENSION_NAME,
425 		g_param_spec_string (
426 			"extension-name",
427 			"Extension Name",
428 			"ESource extension name to filter",
429 			NULL,
430 			G_PARAM_READWRITE |
431 			G_PARAM_CONSTRUCT));
432 
433 	/* XXX Don't use G_PARAM_CONSTRUCT_ONLY here.  We need to allow
434 	 *     for this class to be instantiated by a GtkBuilder with no
435 	 *     special construct parameters, and then subsequently give
436 	 *     it an ESourceRegistry. */
437 	g_object_class_install_property (
438 		object_class,
439 		PROP_REGISTRY,
440 		g_param_spec_object (
441 			"registry",
442 			"Registry",
443 			"Data source registry",
444 			E_TYPE_SOURCE_REGISTRY,
445 			G_PARAM_READWRITE |
446 			G_PARAM_CONSTRUCT |
447 			G_PARAM_STATIC_STRINGS));
448 
449 	g_object_class_install_property (
450 		object_class,
451 		PROP_SHOW_COLORS,
452 		g_param_spec_boolean (
453 			"show-colors",
454 			"Show Colors",
455 			"Whether to show colors next to names",
456 			TRUE,
457 			G_PARAM_READWRITE |
458 			G_PARAM_CONSTRUCT |
459 			G_PARAM_STATIC_STRINGS));
460 }
461 
462 static void
e_source_combo_box_init(ESourceComboBox * combo_box)463 e_source_combo_box_init (ESourceComboBox *combo_box)
464 {
465 	combo_box->priv = E_SOURCE_COMBO_BOX_GET_PRIVATE (combo_box);
466 	combo_box->priv->hide_sources = g_hash_table_new_full (camel_strcase_hash, camel_strcase_equal, g_free, NULL);
467 }
468 
469 /**
470  * e_source_combo_box_new:
471  * @registry: an #ESourceRegistry, or %NULL
472  * @extension_name: an #ESource extension name
473  *
474  * Creates a new #ESourceComboBox widget that lets the user pick an #ESource
475  * from the provided #ESourceRegistry.  The displayed sources are restricted
476  * to those which have an @extension_name extension.
477  *
478  * Returns: a new #ESourceComboBox
479  *
480  * Since: 2.22
481  **/
482 GtkWidget *
e_source_combo_box_new(ESourceRegistry * registry,const gchar * extension_name)483 e_source_combo_box_new (ESourceRegistry *registry,
484                         const gchar *extension_name)
485 {
486 	if (registry != NULL)
487 		g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
488 
489 	return g_object_new (
490 		E_TYPE_SOURCE_COMBO_BOX, "registry", registry,
491 		"extension-name", extension_name, NULL);
492 }
493 
494 /**
495  * e_source_combo_box_get_registry:
496  * @combo_box: an #ESourceComboBox
497  *
498  * Returns the #ESourceRegistry used to populate @combo_box.
499  *
500  * Returns: the #ESourceRegistry, or %NULL
501  *
502  * Since: 3.6
503  **/
504 ESourceRegistry *
e_source_combo_box_get_registry(ESourceComboBox * combo_box)505 e_source_combo_box_get_registry (ESourceComboBox *combo_box)
506 {
507 	g_return_val_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box), NULL);
508 
509 	return combo_box->priv->registry;
510 }
511 
512 /**
513  * e_source_combo_box_set_registry:
514  * @combo_box: an #ESourceComboBox
515  * @registry: an #ESourceRegistry
516  *
517  * Sets the #ESourceRegistry used to populate @combo_box.
518  *
519  * This function is intended for cases where @combo_box is instantiated
520  * by a #GtkBuilder and has to be given an #ESourceRegistry after it is
521  * fully constructed.
522  *
523  * Since: 3.6
524  **/
525 void
e_source_combo_box_set_registry(ESourceComboBox * combo_box,ESourceRegistry * registry)526 e_source_combo_box_set_registry (ESourceComboBox *combo_box,
527                                  ESourceRegistry *registry)
528 {
529 	g_return_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box));
530 
531 	if (combo_box->priv->registry == registry)
532 		return;
533 
534 	if (registry != NULL) {
535 		g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
536 		g_object_ref (registry);
537 	}
538 
539 	if (combo_box->priv->registry != NULL) {
540 		g_signal_handler_disconnect (
541 			combo_box->priv->registry,
542 			combo_box->priv->source_added_handler_id);
543 		g_signal_handler_disconnect (
544 			combo_box->priv->registry,
545 			combo_box->priv->source_removed_handler_id);
546 		g_signal_handler_disconnect (
547 			combo_box->priv->registry,
548 			combo_box->priv->source_enabled_handler_id);
549 		g_signal_handler_disconnect (
550 			combo_box->priv->registry,
551 			combo_box->priv->source_disabled_handler_id);
552 		g_object_unref (combo_box->priv->registry);
553 	}
554 
555 	combo_box->priv->registry = registry;
556 
557 	combo_box->priv->source_added_handler_id = 0;
558 	combo_box->priv->source_removed_handler_id = 0;
559 	combo_box->priv->source_enabled_handler_id = 0;
560 	combo_box->priv->source_disabled_handler_id = 0;
561 
562 	if (registry != NULL) {
563 		gulong handler_id;
564 
565 		handler_id = g_signal_connect (
566 			registry, "source-added",
567 			G_CALLBACK (source_combo_box_source_added_cb),
568 			combo_box);
569 		combo_box->priv->source_added_handler_id = handler_id;
570 
571 		handler_id = g_signal_connect (
572 			registry, "source-removed",
573 			G_CALLBACK (source_combo_box_source_removed_cb),
574 			combo_box);
575 		combo_box->priv->source_removed_handler_id = handler_id;
576 
577 		handler_id = g_signal_connect (
578 			registry, "source-enabled",
579 			G_CALLBACK (source_combo_box_source_enabled_cb),
580 			combo_box);
581 		combo_box->priv->source_enabled_handler_id = handler_id;
582 
583 		handler_id = g_signal_connect (
584 			registry, "source-disabled",
585 			G_CALLBACK (source_combo_box_source_disabled_cb),
586 			combo_box);
587 		combo_box->priv->source_disabled_handler_id = handler_id;
588 	}
589 
590 	source_combo_box_build_model (combo_box);
591 
592 	g_object_notify (G_OBJECT (combo_box), "registry");
593 }
594 
595 /**
596  * e_source_combo_box_get_extension_name:
597  * @combo_box: an #ESourceComboBox
598  *
599  * Returns the extension name used to filter which data sources are
600  * shown in @combo_box.
601  *
602  * Returns: the #ESource extension name
603  *
604  * Since: 3.6
605  **/
606 const gchar *
e_source_combo_box_get_extension_name(ESourceComboBox * combo_box)607 e_source_combo_box_get_extension_name (ESourceComboBox *combo_box)
608 {
609 	g_return_val_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box), NULL);
610 
611 	return combo_box->priv->extension_name;
612 }
613 
614 /**
615  * e_source_combo_box_set_extension_name:
616  * @combo_box: an #ESourceComboBox
617  * @extension_name: an #ESource extension name
618  *
619  * Sets the extension name used to filter which data sources are shown in
620  * @combo_box.
621  *
622  * Since: 3.6
623  **/
624 void
e_source_combo_box_set_extension_name(ESourceComboBox * combo_box,const gchar * extension_name)625 e_source_combo_box_set_extension_name (ESourceComboBox *combo_box,
626                                        const gchar *extension_name)
627 {
628 	g_return_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box));
629 
630 	if (g_strcmp0 (combo_box->priv->extension_name, extension_name) == 0)
631 		return;
632 
633 	g_free (combo_box->priv->extension_name);
634 	combo_box->priv->extension_name = g_strdup (extension_name);
635 
636 	source_combo_box_build_model (combo_box);
637 
638 	g_object_notify (G_OBJECT (combo_box), "extension-name");
639 }
640 
641 /**
642  * e_source_combo_box_get_show_colors:
643  * @combo_box: an #ESourceComboBox
644  *
645  * Returns whether colors are shown next to data sources.
646  *
647  * Returns: %TRUE if colors are being shown
648  *
649  * Since: 3.6
650  **/
651 gboolean
e_source_combo_box_get_show_colors(ESourceComboBox * combo_box)652 e_source_combo_box_get_show_colors (ESourceComboBox *combo_box)
653 {
654 	g_return_val_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box), FALSE);
655 
656 	return combo_box->priv->show_colors;
657 }
658 
659 /**
660  * e_source_combo_box_set_show_colors:
661  * @combo_box: an #ESourceComboBox
662  * @show_colors: whether to show colors
663  *
664  * Sets whether to show colors next to data sources.
665  *
666  * Since: 3.6
667  **/
668 void
e_source_combo_box_set_show_colors(ESourceComboBox * combo_box,gboolean show_colors)669 e_source_combo_box_set_show_colors (ESourceComboBox *combo_box,
670                                     gboolean show_colors)
671 {
672 	g_return_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box));
673 
674 	if ((show_colors ? 1 : 0) == (combo_box->priv->show_colors ? 1 : 0))
675 		return;
676 
677 	combo_box->priv->show_colors = show_colors;
678 
679 	source_combo_box_build_model (combo_box);
680 
681 	g_object_notify (G_OBJECT (combo_box), "show-colors");
682 }
683 
684 /**
685  * e_source_combo_box_ref_active:
686  * @combo_box: an #ESourceComboBox
687  *
688  * Returns the #ESource corresponding to the currently active item,
689  * or %NULL if there is no active item.
690  *
691  * The returned #ESource is referenced for thread-safety and must be
692  * unreferenced with g_object_unref() when finished with it.
693  *
694  * Returns: an #ESource or %NULL
695  *
696  * Since: 3.6
697  **/
698 ESource *
e_source_combo_box_ref_active(ESourceComboBox * combo_box)699 e_source_combo_box_ref_active (ESourceComboBox *combo_box)
700 {
701 	ESourceRegistry *registry;
702 	GtkComboBox *gtk_combo_box;
703 	const gchar *active_id;
704 
705 	g_return_val_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box), NULL);
706 
707 	registry = e_source_combo_box_get_registry (combo_box);
708 
709 	gtk_combo_box = GTK_COMBO_BOX (combo_box);
710 	active_id = gtk_combo_box_get_active_id (gtk_combo_box);
711 
712 	if (active_id == NULL)
713 		return NULL;
714 
715 	return e_source_registry_ref_source (registry, active_id);
716 }
717 
718 /**
719  * e_source_combo_box_set_active:
720  * @combo_box: an #ESourceComboBox
721  * @source: an #ESource
722  *
723  * Sets the active item to the one corresponding to @source.
724  *
725  * Since: 2.22
726  **/
727 void
e_source_combo_box_set_active(ESourceComboBox * combo_box,ESource * source)728 e_source_combo_box_set_active (ESourceComboBox *combo_box,
729                                ESource *source)
730 {
731 	GtkComboBox *gtk_combo_box;
732 	const gchar *uid;
733 
734 	g_return_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box));
735 	g_return_if_fail (E_IS_SOURCE (source));
736 
737 	uid = e_source_get_uid (source);
738 
739 	gtk_combo_box = GTK_COMBO_BOX (combo_box);
740 	gtk_combo_box_set_active_id (gtk_combo_box, uid);
741 }
742 
743 /**
744  * e_source_combo_box_hide_sources:
745  * @combo_box: an #ESourceComboBox
746  * @...: a NULL-terminated list of UID-s of the sources to hide
747  *
748  * The UID-s can be also backend names. Apart of that, these are checked
749  * for both the ESource::uid and the ESource::parent.
750  *
751  * The next call replaces the list of source UID-s to be hidden.
752  *
753  * Since: 3.40
754  **/
755 void
e_source_combo_box_hide_sources(ESourceComboBox * combo_box,...)756 e_source_combo_box_hide_sources (ESourceComboBox *combo_box,
757 				  ...)
758 {
759 	const gchar *backend_name;
760 	va_list va;
761 
762 	g_return_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box));
763 
764 	g_hash_table_remove_all (combo_box->priv->hide_sources);
765 
766 	va_start (va, combo_box);
767 
768 	while (backend_name = va_arg (va, const gchar *), backend_name) {
769 		g_hash_table_insert (combo_box->priv->hide_sources, g_strdup (backend_name), NULL);
770 	}
771 
772 	va_end (va);
773 
774 	source_combo_box_build_model (combo_box);
775 }
776