1 /*
2 * This program is free software; you can redistribute it and/or modify it
3 * under the terms of the GNU Lesser General Public License as published by
4 * the Free Software Foundation.
5 *
6 * This program is distributed in the hope that it will be useful, but
7 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
8 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9 * for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public License
12 * along with this program; if not, see <http://www.gnu.org/licenses/>.
13 *
14 *
15 * Authors:
16 * Not Zed <notzed@lostzed.mmc.com.au>
17 * Jeffrey Stedfast <fejj@ximian.com>
18 *
19 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
20 *
21 */
22
23 #include "evolution-config.h"
24
25 #include <string.h>
26 #include <stdlib.h>
27
28 #include "e-filter-element.h"
29 #include "e-filter-part.h"
30
31 typedef EFilterElement * (*EFilterElementFunc) (gpointer data);
32
33 struct _element_type {
34 gchar *name;
35
36 EFilterElementFunc create;
37 gpointer data;
38 };
39
G_DEFINE_TYPE(EFilterElement,e_filter_element,G_TYPE_OBJECT)40 G_DEFINE_TYPE (
41 EFilterElement,
42 e_filter_element,
43 G_TYPE_OBJECT)
44
45 static gboolean
46 filter_element_validate (EFilterElement *element,
47 EAlert **alert)
48 {
49 return TRUE;
50 }
51
52 static gint
filter_element_eq(EFilterElement * element_a,EFilterElement * element_b)53 filter_element_eq (EFilterElement *element_a,
54 EFilterElement *element_b)
55 {
56 return (g_strcmp0 (element_a->name, element_b->name) == 0);
57 }
58
59 static void
filter_element_xml_create(EFilterElement * element,xmlNodePtr node)60 filter_element_xml_create (EFilterElement *element,
61 xmlNodePtr node)
62 {
63 element->name = (gchar *) xmlGetProp (node, (xmlChar *) "name");
64 }
65
66 static EFilterElement *
filter_element_clone(EFilterElement * element)67 filter_element_clone (EFilterElement *element)
68 {
69 EFilterElement *clone;
70 xmlNodePtr node;
71
72 clone = g_object_new (G_OBJECT_TYPE (element), NULL);
73
74 node = e_filter_element_xml_encode (element);
75 e_filter_element_xml_decode (clone, node);
76 xmlFreeNodeList (node);
77
78 return clone;
79 }
80
81 /* This is somewhat hackish, implement all the base cases in here */
82 #include "e-filter-input.h"
83 #include "e-filter-option.h"
84 #include "e-filter-code.h"
85 #include "e-filter-color.h"
86 #include "e-filter-datespec.h"
87 #include "e-filter-int.h"
88 #include "e-filter-file.h"
89
90 static void
filter_element_copy_value(EFilterElement * dst_element,EFilterElement * src_element)91 filter_element_copy_value (EFilterElement *dst_element,
92 EFilterElement *src_element)
93 {
94 if (E_IS_FILTER_INPUT (src_element)) {
95 EFilterInput *src_input;
96
97 src_input = E_FILTER_INPUT (src_element);
98
99 if (E_IS_FILTER_INPUT (dst_element)) {
100 EFilterInput *dst_input;
101
102 dst_input = E_FILTER_INPUT (dst_element);
103
104 if (src_input->values)
105 e_filter_input_set_value (
106 dst_input,
107 src_input->values->data);
108
109 } else if (E_IS_FILTER_INT (dst_element)) {
110 EFilterInt *dst_int;
111
112 dst_int = E_FILTER_INT (dst_element);
113
114 dst_int->val = atoi (src_input->values->data);
115 }
116
117 } else if (E_IS_FILTER_COLOR (src_element)) {
118 EFilterColor *src_color;
119
120 src_color = E_FILTER_COLOR (src_element);
121
122 if (E_IS_FILTER_COLOR (dst_element)) {
123 EFilterColor *dst_color;
124
125 dst_color = E_FILTER_COLOR (dst_element);
126
127 dst_color->color = src_color->color;
128 }
129
130 } else if (E_IS_FILTER_DATESPEC (src_element)) {
131 EFilterDatespec *src_datespec;
132
133 src_datespec = E_FILTER_DATESPEC (src_element);
134
135 if (E_IS_FILTER_DATESPEC (dst_element)) {
136 EFilterDatespec *dst_datespec;
137
138 dst_datespec = E_FILTER_DATESPEC (dst_element);
139
140 dst_datespec->type = src_datespec->type;
141 dst_datespec->value = src_datespec->value;
142 }
143
144 } else if (E_IS_FILTER_INT (src_element)) {
145 EFilterInt *src_int;
146
147 src_int = E_FILTER_INT (src_element);
148
149 if (E_IS_FILTER_INT (dst_element)) {
150 EFilterInt *dst_int;
151
152 dst_int = E_FILTER_INT (dst_element);
153
154 dst_int->val = src_int->val;
155
156 } else if (E_IS_FILTER_INPUT (dst_element)) {
157 EFilterInput *dst_input;
158 gchar *values;
159
160 dst_input = E_FILTER_INPUT (dst_element);
161
162 values = g_strdup_printf ("%d", src_int->val);
163 e_filter_input_set_value (dst_input, values);
164 g_free (values);
165 }
166
167 } else if (E_IS_FILTER_OPTION (src_element)) {
168 EFilterOption *src_option;
169
170 src_option = E_FILTER_OPTION (src_element);
171
172 if (E_IS_FILTER_OPTION (dst_element)) {
173 EFilterOption *dst_option;
174
175 dst_option = E_FILTER_OPTION (dst_element);
176
177 if (src_option->current)
178 e_filter_option_set_current (
179 dst_option,
180 src_option->current->value);
181 }
182 }
183 }
184
185 static void
filter_element_finalize(GObject * object)186 filter_element_finalize (GObject *object)
187 {
188 EFilterElement *element = E_FILTER_ELEMENT (object);
189
190 xmlFree (element->name);
191
192 /* Chain up to parent's finalize () method. */
193 G_OBJECT_CLASS (e_filter_element_parent_class)->finalize (object);
194 }
195
196 static void
e_filter_element_class_init(EFilterElementClass * class)197 e_filter_element_class_init (EFilterElementClass *class)
198 {
199 GObjectClass *object_class;
200
201 object_class = G_OBJECT_CLASS (class);
202 object_class->finalize = filter_element_finalize;
203
204 class->validate = filter_element_validate;
205 class->eq = filter_element_eq;
206 class->xml_create = filter_element_xml_create;
207 class->clone = filter_element_clone;
208 class->copy_value = filter_element_copy_value;
209 }
210
211 static void
e_filter_element_init(EFilterElement * element)212 e_filter_element_init (EFilterElement *element)
213 {
214 }
215
216 /**
217 * filter_element_new:
218 *
219 * Create a new EFilterElement object.
220 *
221 * Return value: A new #EFilterElement object.
222 **/
223 EFilterElement *
e_filter_element_new(void)224 e_filter_element_new (void)
225 {
226 return g_object_new (E_TYPE_FILTER_ELEMENT, NULL);
227 }
228
229 gboolean
e_filter_element_validate(EFilterElement * element,EAlert ** alert)230 e_filter_element_validate (EFilterElement *element,
231 EAlert **alert)
232 {
233 EFilterElementClass *class;
234
235 g_return_val_if_fail (E_IS_FILTER_ELEMENT (element), FALSE);
236
237 class = E_FILTER_ELEMENT_GET_CLASS (element);
238 g_return_val_if_fail (class != NULL, FALSE);
239 g_return_val_if_fail (class->validate != NULL, FALSE);
240
241 return class->validate (element, alert);
242 }
243
244 gint
e_filter_element_eq(EFilterElement * element_a,EFilterElement * element_b)245 e_filter_element_eq (EFilterElement *element_a,
246 EFilterElement *element_b)
247 {
248 EFilterElementClass *class;
249
250 g_return_val_if_fail (E_IS_FILTER_ELEMENT (element_a), FALSE);
251 g_return_val_if_fail (E_IS_FILTER_ELEMENT (element_b), FALSE);
252
253 /* The elements must be the same type. */
254 if (G_OBJECT_TYPE (element_a) != G_OBJECT_TYPE (element_b))
255 return FALSE;
256
257 class = E_FILTER_ELEMENT_GET_CLASS (element_a);
258 g_return_val_if_fail (class != NULL, FALSE);
259 g_return_val_if_fail (class->eq != NULL, FALSE);
260
261 return class->eq (element_a, element_b);
262 }
263
264 /**
265 * filter_element_xml_create:
266 * @fe: filter element
267 * @node: xml node
268 *
269 * Create a new filter element based on an xml definition of
270 * that element.
271 **/
272 void
e_filter_element_xml_create(EFilterElement * element,xmlNodePtr node)273 e_filter_element_xml_create (EFilterElement *element,
274 xmlNodePtr node)
275 {
276 EFilterElementClass *class;
277
278 g_return_if_fail (E_IS_FILTER_ELEMENT (element));
279 g_return_if_fail (node != NULL);
280
281 class = E_FILTER_ELEMENT_GET_CLASS (element);
282 g_return_if_fail (class != NULL);
283 g_return_if_fail (class->xml_create != NULL);
284
285 class->xml_create (element, node);
286 }
287
288 /**
289 * filter_element_xml_encode:
290 * @fe: filter element
291 *
292 * Encode the values of a filter element into xml format.
293 *
294 * Return value:
295 **/
296 xmlNodePtr
e_filter_element_xml_encode(EFilterElement * element)297 e_filter_element_xml_encode (EFilterElement *element)
298 {
299 EFilterElementClass *class;
300
301 g_return_val_if_fail (E_IS_FILTER_ELEMENT (element), NULL);
302
303 class = E_FILTER_ELEMENT_GET_CLASS (element);
304 g_return_val_if_fail (class != NULL, NULL);
305 g_return_val_if_fail (class->xml_encode != NULL, NULL);
306
307 return class->xml_encode (element);
308 }
309
310 /**
311 * filter_element_xml_decode:
312 * @fe: filter element
313 * @node: xml node
314 *
315 * Decode the values of a fitler element from xml format.
316 *
317 * Return value:
318 **/
319 gint
e_filter_element_xml_decode(EFilterElement * element,xmlNodePtr node)320 e_filter_element_xml_decode (EFilterElement *element,
321 xmlNodePtr node)
322 {
323 EFilterElementClass *class;
324
325 g_return_val_if_fail (E_IS_FILTER_ELEMENT (element), FALSE);
326 g_return_val_if_fail (node != NULL, FALSE);
327
328 class = E_FILTER_ELEMENT_GET_CLASS (element);
329 g_return_val_if_fail (class != NULL, FALSE);
330 g_return_val_if_fail (class->xml_decode != NULL, FALSE);
331
332 return class->xml_decode (element, node);
333 }
334
335 /**
336 * filter_element_clone:
337 * @fe: filter element
338 *
339 * Clones the EFilterElement @fe.
340 *
341 * Return value:
342 **/
343 EFilterElement *
e_filter_element_clone(EFilterElement * element)344 e_filter_element_clone (EFilterElement *element)
345 {
346 EFilterElementClass *class;
347
348 g_return_val_if_fail (E_IS_FILTER_ELEMENT (element), NULL);
349
350 class = E_FILTER_ELEMENT_GET_CLASS (element);
351 g_return_val_if_fail (class != NULL, NULL);
352 g_return_val_if_fail (class->clone != NULL, NULL);
353
354 return class->clone (element);
355 }
356
357 /**
358 * e_filter_element_get_widget:
359 * @fe: filter element
360 *
361 * Create a widget to represent this element.
362 *
363 * Returns: (transfer full): a new GtkWidget
364 **/
365 GtkWidget *
e_filter_element_get_widget(EFilterElement * element)366 e_filter_element_get_widget (EFilterElement *element)
367 {
368 EFilterElementClass *class;
369
370 g_return_val_if_fail (E_IS_FILTER_ELEMENT (element), NULL);
371
372 class = E_FILTER_ELEMENT_GET_CLASS (element);
373 g_return_val_if_fail (class != NULL, NULL);
374 g_return_val_if_fail (class->get_widget != NULL, NULL);
375
376 return class->get_widget (element);
377 }
378
379 /**
380 * filter_element_build_code:
381 * @fe: filter element
382 * @out: output buffer
383 * @ff:
384 *
385 * Add the code representing this element to the output string @out.
386 **/
387 void
e_filter_element_build_code(EFilterElement * element,GString * out,EFilterPart * part)388 e_filter_element_build_code (EFilterElement *element,
389 GString *out,
390 EFilterPart *part)
391 {
392 EFilterElementClass *class;
393
394 g_return_if_fail (E_IS_FILTER_ELEMENT (element));
395 g_return_if_fail (out != NULL);
396 g_return_if_fail (E_IS_FILTER_PART (part));
397
398 class = E_FILTER_ELEMENT_GET_CLASS (element);
399 g_return_if_fail (class != NULL);
400
401 /* This method is optional. */
402 if (class->build_code != NULL)
403 class->build_code (element, out, part);
404 }
405
406 /**
407 * filter_element_format_sexp:
408 * @fe: filter element
409 * @out: output buffer
410 *
411 * Format the value(s) of this element in a method suitable for the context of
412 * sexp where it is used. Usually as space separated, double-quoted strings.
413 **/
414 void
e_filter_element_format_sexp(EFilterElement * element,GString * out)415 e_filter_element_format_sexp (EFilterElement *element,
416 GString *out)
417 {
418 EFilterElementClass *class;
419
420 g_return_if_fail (E_IS_FILTER_ELEMENT (element));
421 g_return_if_fail (out != NULL);
422
423 class = E_FILTER_ELEMENT_GET_CLASS (element);
424 g_return_if_fail (class != NULL);
425 g_return_if_fail (class->format_sexp != NULL);
426
427 class->format_sexp (element, out);
428 }
429
430 void
e_filter_element_set_data(EFilterElement * element,gpointer data)431 e_filter_element_set_data (EFilterElement *element,
432 gpointer data)
433 {
434 g_return_if_fail (E_IS_FILTER_ELEMENT (element));
435
436 element->data = data;
437 }
438
439 /* only copies the value, not the name/type */
440 void
e_filter_element_copy_value(EFilterElement * dst_element,EFilterElement * src_element)441 e_filter_element_copy_value (EFilterElement *dst_element,
442 EFilterElement *src_element)
443 {
444 EFilterElementClass *class;
445
446 g_return_if_fail (E_IS_FILTER_ELEMENT (dst_element));
447 g_return_if_fail (E_IS_FILTER_ELEMENT (src_element));
448
449 class = E_FILTER_ELEMENT_GET_CLASS (dst_element);
450 g_return_if_fail (class != NULL);
451 g_return_if_fail (class->copy_value != NULL);
452
453 class->copy_value (dst_element, src_element);
454 }
455
456 /**
457 * e_filter_element_describe:
458 * @fe: filter element
459 * @out: a #GString to add the description to
460 *
461 * Describes the @element in a human-readable way.
462 **/
463 void
e_filter_element_describe(EFilterElement * element,GString * out)464 e_filter_element_describe (EFilterElement *element,
465 GString *out)
466 {
467 EFilterElementClass *klass;
468
469 g_return_if_fail (E_IS_FILTER_ELEMENT (element));
470 g_return_if_fail (out != NULL);
471
472 klass = E_FILTER_ELEMENT_GET_CLASS (element);
473 g_return_if_fail (klass != NULL);
474 g_return_if_fail (klass->describe != NULL);
475
476 klass->describe (element, out);
477 }
478