No issues found
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 |
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 }