No issues found
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2 of the License, or (at your option) version 3.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with the program; if not, see <http://www.gnu.org/licenses/>
14 *
15 *
16 * Authors:
17 * Jon Trowbridge <trow@ximian.com>
18 * Jeffrey Stedfast <fejj@ximian.com>
19 *
20 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
21 *
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <string.h>
29
30 #include "em-filter-source-element.h"
31 #include "e-mail-account-store.h"
32 #include "e-mail-ui-session.h"
33
34 #include <gtk/gtk.h>
35 #include <camel/camel.h>
36
37 #include <shell/e-shell.h>
38 #include <filter/e-filter-part.h>
39
40 #define EM_FILTER_SOURCE_ELEMENT_GET_PRIVATE(obj) \
41 (G_TYPE_INSTANCE_GET_PRIVATE \
42 ((obj), EM_TYPE_FILTER_SOURCE_ELEMENT, EMFilterSourceElementPrivate))
43
44 struct _EMFilterSourceElementPrivate {
45 EMailSession *session;
46 gchar *active_id;
47 };
48
49 G_DEFINE_TYPE (
50 EMFilterSourceElement,
51 em_filter_source_element,
52 E_TYPE_FILTER_ELEMENT)
53
54 enum {
55 PROP_0,
56 PROP_SESSION
57 };
58
59 static void
60 filter_source_element_source_changed (GtkComboBox *combo_box,
61 EMFilterSourceElement *fs)
62 {
63 const gchar *active_id;
64
65 active_id = gtk_combo_box_get_active_id (combo_box);
66
67 g_free (fs->priv->active_id);
68 fs->priv->active_id = g_strdup (active_id);
69 }
70
71 static void
72 filter_source_element_set_session (EMFilterSourceElement *element,
73 EMailSession *session)
74 {
75 g_return_if_fail (E_IS_MAIL_SESSION (session));
76 g_return_if_fail (element->priv->session == NULL);
77
78 element->priv->session = g_object_ref (session);
79 }
80
81 static void
82 filter_source_element_set_property (GObject *object,
83 guint property_id,
84 const GValue *value,
85 GParamSpec *pspec)
86 {
87 switch (property_id) {
88 case PROP_SESSION:
89 filter_source_element_set_session (
90 EM_FILTER_SOURCE_ELEMENT (object),
91 g_value_get_object (value));
92 return;
93 }
94
95 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
96 }
97
98 static void
99 filter_source_element_get_property (GObject *object,
100 guint property_id,
101 GValue *value,
102 GParamSpec *pspec)
103 {
104 switch (property_id) {
105 case PROP_SESSION:
106 g_value_set_object (
107 value,
108 em_filter_source_element_get_session (
109 EM_FILTER_SOURCE_ELEMENT (object)));
110 return;
111 }
112
113 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
114 }
115
116 static void
117 filter_source_element_dispose (GObject *object)
118 {
119 EMFilterSourceElementPrivate *priv;
120
121 priv = EM_FILTER_SOURCE_ELEMENT_GET_PRIVATE (object);
122
123 if (priv->session != NULL) {
124 g_object_unref (priv->session);
125 priv->session = NULL;
126 }
127
128 /* Chain up to parent's dispose() method. */
129 G_OBJECT_CLASS (em_filter_source_element_parent_class)->dispose (object);
130 }
131
132 static void
133 filter_source_element_finalize (GObject *object)
134 {
135 EMFilterSourceElementPrivate *priv;
136
137 priv = EM_FILTER_SOURCE_ELEMENT_GET_PRIVATE (object);
138
139 g_free (priv->active_id);
140
141 /* Chain up to parent's finalize() method. */
142 G_OBJECT_CLASS (em_filter_source_element_parent_class)->finalize (object);
143 }
144
145 static gint
146 filter_source_element_eq (EFilterElement *fe,
147 EFilterElement *cm)
148 {
149 EMFilterSourceElement *fs = (EMFilterSourceElement *) fe;
150 EMFilterSourceElement *cs = (EMFilterSourceElement *) cm;
151
152 return E_FILTER_ELEMENT_CLASS (em_filter_source_element_parent_class)->eq (fe, cm)
153 && g_strcmp0 (fs->priv->active_id, cs->priv->active_id) == 0;
154 }
155
156 static xmlNodePtr
157 filter_source_element_xml_encode (EFilterElement *fe)
158 {
159 xmlNodePtr value;
160
161 EMFilterSourceElement *fs = (EMFilterSourceElement *) fe;
162
163 value = xmlNewNode (NULL, (const guchar *) "value");
164 xmlSetProp (value, (const guchar *) "name", (guchar *) fe->name);
165 xmlSetProp (value, (const guchar *) "type", (const guchar *) "uid");
166
167 if (fs->priv->active_id != NULL)
168 xmlNewTextChild (
169 value, NULL, (const guchar *) "uid",
170 (guchar *) fs->priv->active_id);
171
172 return value;
173 }
174
175 static gint
176 filter_source_element_xml_decode (EFilterElement *fe,
177 xmlNodePtr node)
178 {
179 EMFilterSourceElement *fs = (EMFilterSourceElement *) fe;
180 EMailSession *session;
181 gchar *active_id = NULL;
182
183 session = em_filter_source_element_get_session (fs);
184
185 node = node->children;
186 while (node != NULL) {
187
188 if (strcmp ((gchar *) node->name, "uid") == 0) {
189 xmlChar *content;
190
191 content = xmlNodeGetContent (node);
192 active_id = g_strdup ((gchar *) content);
193 xmlFree (content);
194
195 break;
196 }
197
198 /* For backward-compatibility: We used to store
199 * sources by their URI string, which can change. */
200 if (strcmp ((gchar *) node->name, "uri") == 0) {
201 CamelService *service = NULL;
202 xmlChar *content;
203 CamelURL *url;
204
205 content = xmlNodeGetContent (node);
206 url = camel_url_new ((gchar *) content, NULL);
207 xmlFree (content);
208
209 if (url != NULL) {
210 service = camel_session_ref_service_by_url (
211 CAMEL_SESSION (session),
212 url, CAMEL_PROVIDER_STORE);
213 camel_url_free (url);
214 }
215
216 if (service != NULL) {
217 const gchar *uid;
218
219 uid = camel_service_get_uid (service);
220 active_id = g_strdup (uid);
221
222 g_object_unref (service);
223 }
224
225 break;
226 }
227
228 node = node->next;
229 }
230
231 if (active_id != NULL) {
232 g_free (fs->priv->active_id);
233 fs->priv->active_id = active_id;
234 } else
235 g_free (active_id);
236
237 return 0;
238 }
239
240 static EFilterElement *
241 filter_source_element_clone (EFilterElement *fe)
242 {
243 EMFilterSourceElement *fs = (EMFilterSourceElement *) fe;
244 EMFilterSourceElement *cpy;
245 EMailSession *session;
246
247 session = em_filter_source_element_get_session (fs);
248 cpy = (EMFilterSourceElement *) em_filter_source_element_new (session);
249 ((EFilterElement *) cpy)->name = (gchar *) xmlStrdup ((guchar *) fe->name);
250
251 cpy->priv->active_id = g_strdup (fs->priv->active_id);
252
253 return (EFilterElement *) cpy;
254 }
255
256 static void
257 filter_source_element_add_to_combo (GtkComboBox *combo_box,
258 CamelService *service,
259 ESourceRegistry *registry)
260 {
261 ESource *source;
262 ESourceMailIdentity *extension;
263 const gchar *extension_name;
264 const gchar *display_name;
265 const gchar *address;
266 const gchar *name;
267 const gchar *uid;
268 gchar *label;
269
270 source = e_source_registry_ref_source (
271 registry,
272 camel_service_get_uid (service));
273 if (!source)
274 return;
275
276 extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
277 if (e_source_has_extension (source, extension_name)) {
278 ESource *identity_source;
279 ESourceMailAccount *mail_account;
280
281 mail_account = e_source_get_extension (source, extension_name);
282 uid = e_source_mail_account_get_identity_uid (mail_account);
283
284 if (!uid || !*uid) {
285 g_object_unref (source);
286 return;
287 }
288
289 identity_source = e_source_registry_ref_source (registry, uid);
290 g_object_unref (source);
291 source = identity_source;
292
293 if (!source)
294 return;
295 }
296
297 /* use UID of the service, because that's the one used in camel-filter-driver */
298 uid = camel_service_get_uid (service);
299 display_name = e_source_get_display_name (source);
300
301 extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
302 if (!e_source_has_extension (source, extension_name)) {
303 g_object_unref (source);
304 return;
305 }
306
307 extension = e_source_get_extension (source, extension_name);
308
309 name = e_source_mail_identity_get_name (extension);
310 address = e_source_mail_identity_get_address (extension);
311
312 if (name == NULL || address == NULL) {
313 if (name == NULL && address == NULL)
314 label = g_strdup (display_name);
315 else
316 label = g_strdup_printf ("%s (%s)", name ? name : address, display_name);
317
318 } else if (g_strcmp0 (display_name, address) == 0)
319 label = g_strdup_printf ("%s <%s>", name, address);
320 else
321 label = g_strdup_printf ("%s <%s> (%s)", name, address, display_name);
322
323 gtk_combo_box_text_append (
324 GTK_COMBO_BOX_TEXT (combo_box), uid, label);
325
326 g_free (label);
327 g_object_unref (source);
328 }
329
330 static GtkWidget *
331 filter_source_element_get_widget (EFilterElement *fe)
332 {
333 EMFilterSourceElement *fs = (EMFilterSourceElement *) fe;
334 EMailSession *session;
335 ESourceRegistry *registry;
336 EMailAccountStore *account_store;
337 GtkTreeModel *model;
338 GtkTreeIter iter;
339 GtkWidget *widget;
340 GtkComboBox *combo_box;
341
342 widget = gtk_combo_box_text_new ();
343 combo_box = GTK_COMBO_BOX (widget);
344
345 session = em_filter_source_element_get_session (fs);
346 registry = e_mail_session_get_registry (session);
347 account_store = e_mail_ui_session_get_account_store (E_MAIL_UI_SESSION (session));
348
349 model = GTK_TREE_MODEL (account_store);
350 if (gtk_tree_model_get_iter_first (model, &iter)) {
351 CamelService *service;
352
353 do {
354 gboolean enabled = FALSE, builtin = TRUE;
355
356 service = NULL;
357
358 gtk_tree_model_get (
359 model, &iter,
360 E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE, &service,
361 E_MAIL_ACCOUNT_STORE_COLUMN_ENABLED, &enabled,
362 E_MAIL_ACCOUNT_STORE_COLUMN_BUILTIN, &builtin,
363 -1);
364
365 if (CAMEL_IS_STORE (service) && enabled && !builtin)
366 filter_source_element_add_to_combo (combo_box, service, registry);
367
368 if (service)
369 g_object_unref (service);
370 } while (gtk_tree_model_iter_next (model, &iter));
371 }
372
373 if (fs->priv->active_id != NULL) {
374 gtk_combo_box_set_active_id (combo_box, fs->priv->active_id);
375 } else {
376 const gchar *active_id;
377
378 gtk_combo_box_set_active (combo_box, 0);
379 active_id = gtk_combo_box_get_active_id (combo_box);
380
381 g_free (fs->priv->active_id);
382 fs->priv->active_id = g_strdup (active_id);
383 }
384
385 g_signal_connect (
386 widget, "changed",
387 G_CALLBACK (filter_source_element_source_changed), fs);
388
389 return widget;
390 }
391
392 static void
393 filter_source_element_build_code (EFilterElement *fe,
394 GString *out,
395 EFilterPart *ff)
396 {
397 /* We are doing nothing on purpose. */
398 }
399
400 static void
401 filter_source_element_format_sexp (EFilterElement *fe,
402 GString *out)
403 {
404 EMFilterSourceElement *fs = (EMFilterSourceElement *) fe;
405
406 camel_sexp_encode_string (out, fs->priv->active_id);
407 }
408
409 static void
410 em_filter_source_element_class_init (EMFilterSourceElementClass *class)
411 {
412 GObjectClass *object_class;
413 EFilterElementClass *filter_element_class;
414
415 g_type_class_add_private (class, sizeof (EMFilterSourceElementPrivate));
416
417 object_class = G_OBJECT_CLASS (class);
418 object_class->set_property = filter_source_element_set_property;
419 object_class->get_property = filter_source_element_get_property;
420 object_class->dispose = filter_source_element_dispose;
421 object_class->finalize = filter_source_element_finalize;
422
423 filter_element_class = E_FILTER_ELEMENT_CLASS (class);
424 filter_element_class->eq = filter_source_element_eq;
425 filter_element_class->xml_encode = filter_source_element_xml_encode;
426 filter_element_class->xml_decode = filter_source_element_xml_decode;
427 filter_element_class->clone = filter_source_element_clone;
428 filter_element_class->get_widget = filter_source_element_get_widget;
429 filter_element_class->build_code = filter_source_element_build_code;
430 filter_element_class->format_sexp = filter_source_element_format_sexp;
431
432 g_object_class_install_property (
433 object_class,
434 PROP_SESSION,
435 g_param_spec_object (
436 "session",
437 NULL,
438 NULL,
439 E_TYPE_MAIL_SESSION,
440 G_PARAM_READWRITE |
441 G_PARAM_CONSTRUCT_ONLY |
442 G_PARAM_STATIC_STRINGS));
443 }
444
445 static void
446 em_filter_source_element_init (EMFilterSourceElement *element)
447 {
448 element->priv = EM_FILTER_SOURCE_ELEMENT_GET_PRIVATE (element);
449 }
450
451 EFilterElement *
452 em_filter_source_element_new (EMailSession *session)
453 {
454 g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL);
455
456 return g_object_new (
457 EM_TYPE_FILTER_SOURCE_ELEMENT,
458 "session", session, NULL);
459 }
460
461 EMailSession *
462 em_filter_source_element_get_session (EMFilterSourceElement *element)
463 {
464 g_return_val_if_fail (EM_IS_FILTER_SOURCE_ELEMENT (element), NULL);
465
466 return element->priv->session;
467 }