evolution-3.6.4/widgets/misc/e-mail-identity-combo-box.c

No issues found

Incomplete coverage

Tool Failure ID Location Function Message Data
clang-analyzer no-output-found e-mail-identity-combo-box.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
clang-analyzer no-output-found e-mail-identity-combo-box.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
  1 /*
  2  * e-mail-identity-combo-box.c
  3  *
  4  * This program is free software; you can redistribute it and/or
  5  * modify it under the terms of the GNU Lesser General Public
  6  * License as published by the Free Software Foundation; either
  7  * version 2 of the License, or (at your option) version 3.
  8  *
  9  * This program is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12  * Lesser General Public License for more details.
 13  *
 14  * You should have received a copy of the GNU Lesser General Public
 15  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 16  *
 17  */
 18 
 19 #include "e-mail-identity-combo-box.h"
 20 
 21 #define E_MAIL_IDENTITY_COMBO_BOX_GET_PRIVATE(obj) \
 22 	(G_TYPE_INSTANCE_GET_PRIVATE \
 23 	((obj), E_TYPE_MAIL_IDENTITY_COMBO_BOX, EMailIdentityComboBoxPrivate))
 24 
 25 #define SOURCE_IS_MAIL_IDENTITY(source) \
 26 	(e_source_has_extension ((source), E_SOURCE_EXTENSION_MAIL_IDENTITY))
 27 
 28 struct _EMailIdentityComboBoxPrivate {
 29 	ESourceRegistry *registry;
 30 	guint refresh_idle_id;
 31 };
 32 
 33 enum {
 34 	PROP_0,
 35 	PROP_REGISTRY
 36 };
 37 
 38 enum {
 39 	COLUMN_DISPLAY_NAME,
 40 	COLUMN_UID
 41 };
 42 
 43 G_DEFINE_TYPE (
 44 	EMailIdentityComboBox,
 45 	e_mail_identity_combo_box,
 46 	GTK_TYPE_COMBO_BOX)
 47 
 48 static gboolean
 49 mail_identity_combo_box_refresh_idle_cb (EMailIdentityComboBox *combo_box)
 50 {
 51 	/* The refresh function will clear the idle ID. */
 52 	e_mail_identity_combo_box_refresh (combo_box);
 53 
 54 	return FALSE;
 55 }
 56 
 57 static void
 58 mail_identity_combo_box_registry_changed (ESourceRegistry *registry,
 59                                           ESource *source,
 60                                           EMailIdentityComboBox *combo_box)
 61 {
 62 	/* If the ESource in question has a "Mail Identity" extension,
 63 	 * schedule a refresh of the tree model.  Otherwise ignore it.
 64 	 * We use an idle callback to limit how frequently we refresh
 65 	 * the tree model, in case the registry is emitting lots of
 66 	 * signals at once. */
 67 
 68 	if (!SOURCE_IS_MAIL_IDENTITY (source))
 69 		return;
 70 
 71 	if (combo_box->priv->refresh_idle_id > 0)
 72 		return;
 73 
 74 	combo_box->priv->refresh_idle_id = g_idle_add (
 75 		(GSourceFunc) mail_identity_combo_box_refresh_idle_cb,
 76 		combo_box);
 77 }
 78 
 79 static void
 80 mail_identity_combo_box_activate_default (EMailIdentityComboBox *combo_box)
 81 {
 82 	ESource *source;
 83 	ESourceRegistry *registry;
 84 
 85 	registry = e_mail_identity_combo_box_get_registry (combo_box);
 86 	source = e_source_registry_ref_default_mail_identity (registry);
 87 
 88 	if (source != NULL) {
 89 		const gchar *uid = e_source_get_uid (source);
 90 		gtk_combo_box_set_active_id (GTK_COMBO_BOX (combo_box), uid);
 91 		g_object_unref (source);
 92 	}
 93 }
 94 
 95 static void
 96 mail_identity_combo_box_set_registry (EMailIdentityComboBox *combo_box,
 97                                       ESourceRegistry *registry)
 98 {
 99 	g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
100 	g_return_if_fail (combo_box->priv->registry == NULL);
101 
102 	combo_box->priv->registry = g_object_ref (registry);
103 
104 	g_signal_connect (
105 		registry, "source-added",
106 		G_CALLBACK (mail_identity_combo_box_registry_changed),
107 		combo_box);
108 
109 	g_signal_connect (
110 		registry, "source-changed",
111 		G_CALLBACK (mail_identity_combo_box_registry_changed),
112 		combo_box);
113 
114 	g_signal_connect (
115 		registry, "source-removed",
116 		G_CALLBACK (mail_identity_combo_box_registry_changed),
117 		combo_box);
118 }
119 
120 static void
121 mail_identity_combo_box_set_property (GObject *object,
122                                       guint property_id,
123                                       const GValue *value,
124                                       GParamSpec *pspec)
125 {
126 	switch (property_id) {
127 		case PROP_REGISTRY:
128 			mail_identity_combo_box_set_registry (
129 				E_MAIL_IDENTITY_COMBO_BOX (object),
130 				g_value_get_object (value));
131 			return;
132 	}
133 
134 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
135 }
136 
137 static void
138 mail_identity_combo_box_get_property (GObject *object,
139                                       guint property_id,
140                                       GValue *value,
141                                       GParamSpec *pspec)
142 {
143 	switch (property_id) {
144 		case PROP_REGISTRY:
145 			g_value_set_object (
146 				value,
147 				e_mail_identity_combo_box_get_registry (
148 				E_MAIL_IDENTITY_COMBO_BOX (object)));
149 			return;
150 	}
151 
152 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
153 }
154 
155 static void
156 mail_identity_combo_box_dispose (GObject *object)
157 {
158 	EMailIdentityComboBoxPrivate *priv;
159 
160 	priv = E_MAIL_IDENTITY_COMBO_BOX_GET_PRIVATE (object);
161 
162 	if (priv->registry != NULL) {
163 		g_signal_handlers_disconnect_matched (
164 			priv->registry, G_SIGNAL_MATCH_DATA,
165 			0, 0, NULL, NULL, object);
166 		g_object_unref (priv->registry);
167 		priv->registry = NULL;
168 	}
169 
170 	if (priv->refresh_idle_id > 0) {
171 		g_source_remove (priv->refresh_idle_id);
172 		priv->refresh_idle_id = 0;
173 	}
174 
175 	/* Chain up to parent's dispose() method. */
176 	G_OBJECT_CLASS (e_mail_identity_combo_box_parent_class)->
177 		dispose (object);
178 }
179 
180 static void
181 mail_identity_combo_box_constructed (GObject *object)
182 {
183 	GtkListStore *list_store;
184 	GtkComboBox *combo_box;
185 	GtkCellLayout *cell_layout;
186 	GtkCellRenderer *cell_renderer;
187 
188 	/* Chain up to parent's constructed() method. */
189 	G_OBJECT_CLASS (e_mail_identity_combo_box_parent_class)->
190 		constructed (object);
191 
192 	combo_box = GTK_COMBO_BOX (object);
193 	cell_layout = GTK_CELL_LAYOUT (object);
194 
195 	list_store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
196 	gtk_combo_box_set_model (combo_box, GTK_TREE_MODEL (list_store));
197 	gtk_combo_box_set_id_column (combo_box, COLUMN_UID);
198 	g_object_unref (list_store);
199 
200 	cell_renderer = gtk_cell_renderer_text_new ();
201 	gtk_cell_layout_pack_start (cell_layout, cell_renderer, TRUE);
202 	gtk_cell_layout_add_attribute (
203 		cell_layout, cell_renderer, "text", COLUMN_DISPLAY_NAME);
204 
205 	e_mail_identity_combo_box_refresh (E_MAIL_IDENTITY_COMBO_BOX (object));
206 }
207 
208 static void
209 e_mail_identity_combo_box_class_init (EMailIdentityComboBoxClass *class)
210 {
211 	GObjectClass *object_class;
212 
213 	g_type_class_add_private (
214 		class, sizeof (EMailIdentityComboBoxPrivate));
215 
216 	object_class = G_OBJECT_CLASS (class);
217 	object_class->set_property = mail_identity_combo_box_set_property;
218 	object_class->get_property = mail_identity_combo_box_get_property;
219 	object_class->dispose = mail_identity_combo_box_dispose;
220 	object_class->constructed = mail_identity_combo_box_constructed;
221 
222 	g_object_class_install_property (
223 		object_class,
224 		PROP_REGISTRY,
225 		g_param_spec_object (
226 			"registry",
227 			"Registry",
228 			NULL,
229 			E_TYPE_SOURCE_REGISTRY,
230 			G_PARAM_READWRITE |
231 			G_PARAM_CONSTRUCT_ONLY |
232 			G_PARAM_STATIC_STRINGS));
233 }
234 
235 static void
236 e_mail_identity_combo_box_init (EMailIdentityComboBox *combo_box)
237 {
238 	combo_box->priv = E_MAIL_IDENTITY_COMBO_BOX_GET_PRIVATE (combo_box);
239 }
240 
241 GtkWidget *
242 e_mail_identity_combo_box_new (ESourceRegistry *registry)
243 {
244 	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
245 
246 	return g_object_new (
247 		E_TYPE_MAIL_IDENTITY_COMBO_BOX,
248 		"registry", registry, NULL);
249 }
250 
251 void
252 e_mail_identity_combo_box_refresh (EMailIdentityComboBox *combo_box)
253 {
254 	ESourceRegistry *registry;
255 	GtkTreeModel *tree_model;
256 	GtkComboBox *gtk_combo_box;
257 	ESource *source;
258 	GList *list, *link;
259 	GHashTable *address_table;
260 	const gchar *extension_name;
261 	const gchar *saved_uid;
262 
263 	g_return_if_fail (E_IS_MAIL_IDENTITY_COMBO_BOX (combo_box));
264 
265 	if (combo_box->priv->refresh_idle_id > 0) {
266 		g_source_remove (combo_box->priv->refresh_idle_id);
267 		combo_box->priv->refresh_idle_id = 0;
268 	}
269 
270 	gtk_combo_box = GTK_COMBO_BOX (combo_box);
271 	tree_model = gtk_combo_box_get_model (gtk_combo_box);
272 
273 	/* This is an interned string, which means it's safe
274 	 * to use even after clearing the combo box model. */
275 	saved_uid = gtk_combo_box_get_active_id (gtk_combo_box);
276 
277 	gtk_list_store_clear (GTK_LIST_STORE (tree_model));
278 
279 	extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
280 	registry = e_mail_identity_combo_box_get_registry (combo_box);
281 	list = e_source_registry_list_sources (registry, extension_name);
282 
283 	/* Build a hash table of GQueues by email address so we can
284 	 * spot duplicate email addresses.  Then if the GQueue for a
285 	 * given email address has multiple elements, we use a more
286 	 * verbose description in the combo box. */
287 
288 	address_table = g_hash_table_new_full (
289 		(GHashFunc) g_str_hash,
290 		(GEqualFunc) g_str_equal,
291 		(GDestroyNotify) g_free,
292 		(GDestroyNotify) g_queue_free);
293 
294 	for (link = list; link != NULL; link = g_list_next (link)) {
295 		ESourceMailIdentity *extension;
296 		GQueue *queue;
297 		const gchar *address;
298 
299 		source = E_SOURCE (link->data);
300 		extension = e_source_get_extension (source, extension_name);
301 		address = e_source_mail_identity_get_address (extension);
302 
303 		if (address == NULL)
304 			continue;
305 
306 		queue = g_hash_table_lookup (address_table, address);
307 		if (queue == NULL) {
308 			queue = g_queue_new ();
309 			g_hash_table_insert (
310 				address_table,
311 				g_strdup (address), queue);
312 		}
313 
314 		g_queue_push_tail (queue, source);
315 	}
316 
317 	for (link = list; link != NULL; link = g_list_next (link)) {
318 		ESourceMailIdentity *extension;
319 		GtkTreeIter iter;
320 		GQueue *queue;
321 		GString *string;
322 		const gchar *address;
323 		const gchar *display_name;
324 		const gchar *name;
325 		const gchar *uid;
326 
327 		source = E_SOURCE (link->data);
328 		if (!e_source_get_enabled (source))
329 			continue;
330 
331 		extension = e_source_get_extension (source, extension_name);
332 		name = e_source_mail_identity_get_name (extension);
333 		address = e_source_mail_identity_get_address (extension);
334 
335 		if (name == NULL || address == NULL)
336 			continue;
337 
338 		queue = g_hash_table_lookup (address_table, address);
339 
340 		display_name = e_source_get_display_name (source);
341 		uid = e_source_get_uid (source);
342 
343 		string = g_string_sized_new (512);
344 		g_string_append_printf (string, "%s <%s>", name, address);
345 
346 		/* Show the account name for duplicate email addresses. */
347 		if (queue != NULL && g_queue_get_length (queue) > 1)
348 			g_string_append_printf (string, " (%s)", display_name);
349 
350 		gtk_list_store_append (GTK_LIST_STORE (tree_model), &iter);
351 
352 		gtk_list_store_set (
353 			GTK_LIST_STORE (tree_model), &iter,
354 			COLUMN_DISPLAY_NAME, string->str,
355 			COLUMN_UID, uid, -1);
356 
357 		g_string_free (string, TRUE);
358 	}
359 
360 	g_hash_table_destroy (address_table);
361 
362 	g_list_free_full (list, (GDestroyNotify) g_object_unref);
363 
364 	/* Try and restore the previous selected source, or else pick
365 	 * the default identity of the default mail account.  If even
366 	 * that fails, just pick the first item. */
367 
368 	if (saved_uid != NULL)
369 		gtk_combo_box_set_active_id (gtk_combo_box, saved_uid);
370 
371 	if (gtk_combo_box_get_active_id (gtk_combo_box) == NULL)
372 		mail_identity_combo_box_activate_default (combo_box);
373 
374 	if (gtk_combo_box_get_active_id (gtk_combo_box) == NULL)
375 		gtk_combo_box_set_active (gtk_combo_box, 0);
376 }
377 
378 ESourceRegistry *
379 e_mail_identity_combo_box_get_registry (EMailIdentityComboBox *combo_box)
380 {
381 	g_return_val_if_fail (E_IS_MAIL_IDENTITY_COMBO_BOX (combo_box), NULL);
382 
383 	return combo_box->priv->registry;
384 }