1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2 of the License, or (at your option) version 3.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with the program; if not, see <http://www.gnu.org/licenses/>
18 * Not Zed <notzed@lostzed.mmc.com.au>
19 * Jeffrey Stedfast <fejj@ximian.com>
21 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
28 #include <sys/types.h>
35 #include <glib/gstdio.h>
39 #include <glib/gi18n.h>
41 #include <libedataserver/e-xml-utils.h>
43 #include "e-util/e-alert-dialog.h"
44 #include "e-util/e-xml-utils.h"
46 #include "e-filter-code.h"
47 #include "e-filter-color.h"
48 #include "e-filter-datespec.h"
49 #include "e-filter-file.h"
50 #include "e-filter-input.h"
51 #include "e-filter-int.h"
52 #include "e-filter-option.h"
53 #include "e-filter-rule.h"
54 #include "e-rule-context.h"
56 #define E_RULE_CONTEXT_GET_PRIVATE(obj) \
57 (G_TYPE_INSTANCE_GET_PRIVATE \
58 ((obj), E_TYPE_RULE_CONTEXT, ERuleContextPrivate))
60 struct _ERuleContextPrivate
{
71 static guint signals
[LAST_SIGNAL
];
84 rule_context_set_error (ERuleContext
*context
,
87 g_free (context
->error
);
88 context
->error
= error
;
92 new_rule_response (GtkWidget
*dialog
,
94 ERuleContext
*context
)
96 if (button
== GTK_RESPONSE_OK
) {
97 EFilterRule
*rule
= g_object_get_data ((GObject
*) dialog
, "rule");
98 gchar
*user
= g_object_get_data ((GObject
*) dialog
, "path");
101 if (!e_filter_rule_validate (rule
, &alert
)) {
102 e_alert_run_dialog (GTK_WINDOW (dialog
), alert
);
103 g_object_unref (alert
);
107 if (e_rule_context_find_rule (context
, rule
->name
, rule
->source
)) {
108 e_alert_run_dialog_for_args ((GtkWindow
*)dialog
,
109 "filter:bad-name-notunique",
116 e_rule_context_add_rule (context
, rule
);
118 e_rule_context_save (context
, user
);
121 gtk_widget_destroy (dialog
);
125 revert_rule_remove (gpointer key
,
127 ERuleContext
*context
)
129 e_rule_context_remove_rule (context
, rule
);
130 g_object_unref (rule
);
134 revert_source_remove (gpointer key
,
135 struct _revert_data
*rest_data
,
136 ERuleContext
*context
)
138 g_hash_table_foreach (
139 rest_data
->rules
, (GHFunc
) revert_rule_remove
, context
);
140 g_hash_table_destroy (rest_data
->rules
);
145 source_hashf (const gchar
*a
)
147 return (a
!= NULL
) ? g_str_hash (a
) : 0;
151 source_eqf (const gchar
*a
,
154 return (g_strcmp0 (a
, b
) == 0);
158 free_part_set (struct _part_set_map
*map
)
165 free_rule_set (struct _rule_set_map
*map
)
172 rule_context_finalize (GObject
*obj
)
174 ERuleContext
*context
=(ERuleContext
*) obj
;
176 g_list_foreach (context
->rule_set_list
, (GFunc
)free_rule_set
, NULL
);
177 g_list_free (context
->rule_set_list
);
178 g_hash_table_destroy (context
->rule_set_map
);
180 g_list_foreach (context
->part_set_list
, (GFunc
)free_part_set
, NULL
);
181 g_list_free (context
->part_set_list
);
182 g_hash_table_destroy (context
->part_set_map
);
184 g_free (context
->error
);
186 g_list_foreach (context
->parts
, (GFunc
)g_object_unref
, NULL
);
187 g_list_free (context
->parts
);
189 g_list_foreach (context
->rules
, (GFunc
)g_object_unref
, NULL
);
190 g_list_free (context
->rules
);
192 G_OBJECT_CLASS (e_rule_context_parent_class
)->finalize (obj
);
196 rule_context_load (ERuleContext
*context
,
200 xmlNodePtr set
, rule
, root
;
201 xmlDocPtr systemdoc
, userdoc
;
202 struct _part_set_map
*part_map
;
203 struct _rule_set_map
*rule_map
;
205 rule_context_set_error (context
, NULL
);
207 systemdoc
= e_xml_parse_file (system
);
208 if (systemdoc
== NULL
) {
211 err_msg
= g_strdup_printf (
212 "Unable to load system rules '%s': %s",
213 system
, g_strerror (errno
));
214 g_warning ("%s: %s", G_STRFUNC
, err_msg
);
215 rule_context_set_error (context
, err_msg
);
216 /* no need to free err_msg here */
220 root
= xmlDocGetRootElement (systemdoc
);
221 if (root
== NULL
|| strcmp ((gchar
*)root
->name
, "filterdescription")) {
224 err_msg
= g_strdup_printf (
225 "Unable to load system rules '%s': "
226 "Invalid format", system
);
227 g_warning ("%s: %s", G_STRFUNC
, err_msg
);
228 rule_context_set_error (context
, err_msg
);
229 /* no need to free err_msg here */
230 xmlFreeDoc (systemdoc
);
233 /* doesn't matter if this doens't exist */
235 if (g_file_test (user
, G_FILE_TEST_IS_REGULAR
))
236 userdoc
= e_xml_parse_file (user
);
238 /* now parse structure */
240 set
= root
->children
;
242 part_map
= g_hash_table_lookup (context
->part_set_map
, set
->name
);
244 rule
= set
->children
;
246 if (!strcmp ((gchar
*)rule
->name
, "part")) {
247 EFilterPart
*part
= E_FILTER_PART (g_object_new (part_map
->type
, NULL
, NULL
));
249 if (e_filter_part_xml_create (part
, rule
, context
) == 0) {
250 part_map
->append (context
, part
);
252 g_object_unref (part
);
253 g_warning ("Cannot load filter part");
258 } else if ((rule_map
= g_hash_table_lookup (context
->rule_set_map
, set
->name
))) {
259 rule
= set
->children
;
261 if (!strcmp ((gchar
*)rule
->name
, "rule")) {
262 EFilterRule
*part
= E_FILTER_RULE (g_object_new (rule_map
->type
, NULL
, NULL
));
264 if (e_filter_rule_xml_decode (part
, rule
, context
) == 0) {
266 rule_map
->append (context
, part
);
268 g_object_unref (part
);
269 g_warning ("Cannot load filter part");
278 /* now load actual rules */
280 root
= xmlDocGetRootElement (userdoc
);
281 set
= root
?root
->children
:NULL
;
283 rule_map
= g_hash_table_lookup (context
->rule_set_map
, set
->name
);
285 rule
= set
->children
;
287 if (!strcmp ((gchar
*)rule
->name
, "rule")) {
288 EFilterRule
*part
= E_FILTER_RULE (g_object_new (rule_map
->type
, NULL
, NULL
));
290 if (e_filter_rule_xml_decode (part
, rule
, context
) == 0) {
291 rule_map
->append (context
, part
);
293 g_object_unref (part
);
294 g_warning ("Cannot load filter part");
304 xmlFreeDoc (userdoc
);
305 xmlFreeDoc (systemdoc
);
311 rule_context_save (ERuleContext
*context
,
315 xmlNodePtr root
, rules
, work
;
318 struct _rule_set_map
*map
;
321 doc
= xmlNewDoc ((xmlChar
*)"1.0");
322 /* FIXME: set character encoding to UTF-8? */
323 root
= xmlNewDocNode (doc
, NULL
, (xmlChar
*)"filteroptions", NULL
);
324 xmlDocSetRootElement (doc
, root
);
325 l
= context
->rule_set_list
;
328 rules
= xmlNewDocNode (doc
, NULL
, (xmlChar
*)map
->name
, NULL
);
329 xmlAddChild (root
, rules
);
331 while ((rule
= map
->next (context
, rule
, NULL
))) {
333 work
= e_filter_rule_xml_encode (rule
);
334 xmlAddChild (rules
, work
);
340 ret
= e_xml_save_file (user
, doc
);
348 rule_context_revert (ERuleContext
*context
,
351 xmlNodePtr set
, rule
;
352 /*struct _part_set_map *part_map;*/
353 struct _rule_set_map
*rule_map
;
354 struct _revert_data
*rest_data
;
355 GHashTable
*source_hash
;
359 rule_context_set_error (context
, NULL
);
361 userdoc
= e_xml_parse_file (user
);
363 /* clear out anythign we have? */
366 source_hash
= g_hash_table_new ((GHashFunc
)source_hashf
, (GCompareFunc
)source_eqf
);
368 /* setup stuff we have now */
369 /* Note that we assume there is only 1 set of rules in a given rule context,
370 although other parts of the code dont assume this */
372 while ((frule
= e_rule_context_next_rule (context
, frule
, NULL
))) {
373 rest_data
= g_hash_table_lookup (source_hash
, frule
->source
);
374 if (rest_data
== NULL
) {
375 rest_data
= g_malloc0 (sizeof (*rest_data
));
376 rest_data
->rules
= g_hash_table_new (g_str_hash
, g_str_equal
);
377 g_hash_table_insert (source_hash
, frule
->source
, rest_data
);
379 g_hash_table_insert (rest_data
->rules
, frule
->name
, frule
);
382 /* make what we have, match what we load */
383 set
= xmlDocGetRootElement (userdoc
);
384 set
= set
?set
->children
:NULL
;
386 rule_map
= g_hash_table_lookup (context
->rule_set_map
, set
->name
);
388 rule
= set
->children
;
390 if (!strcmp ((gchar
*)rule
->name
, "rule")) {
391 EFilterRule
*part
= E_FILTER_RULE (g_object_new (rule_map
->type
, NULL
, NULL
));
393 if (e_filter_rule_xml_decode (part
, rule
, context
) == 0) {
394 /* use the revert data to keep track of the right rank of this rule part */
395 rest_data
= g_hash_table_lookup (source_hash
, part
->source
);
396 if (rest_data
== NULL
) {
397 rest_data
= g_malloc0 (sizeof (*rest_data
));
398 rest_data
->rules
= g_hash_table_new (g_str_hash
, g_str_equal
);
399 g_hash_table_insert (source_hash
, part
->source
, rest_data
);
401 frule
= g_hash_table_lookup (rest_data
->rules
, part
->name
);
403 if (context
->priv
->frozen
== 0 && !e_filter_rule_eq (frule
, part
))
404 e_filter_rule_copy (frule
, part
);
406 g_object_unref (part
);
407 e_rule_context_rank_rule (context
, frule
, frule
->source
, rest_data
->rank
);
408 g_hash_table_remove (rest_data
->rules
, frule
->name
);
410 e_rule_context_add_rule (context
, part
);
411 e_rule_context_rank_rule (context
, part
, part
->source
, rest_data
->rank
);
415 g_object_unref (part
);
416 g_warning ("Cannot load filter part");
425 xmlFreeDoc (userdoc
);
427 /* remove any we still have that weren't in the file */
428 g_hash_table_foreach (source_hash
, (GHFunc
)revert_source_remove
, context
);
429 g_hash_table_destroy (source_hash
);
434 static EFilterElement
*
435 rule_context_new_element (ERuleContext
*context
,
438 if (!strcmp (type
, "string")) {
439 return (EFilterElement
*) e_filter_input_new ();
440 } else if (!strcmp (type
, "address")) {
441 /* FIXME: temporary ... need real address type */
442 return (EFilterElement
*) e_filter_input_new_type_name (type
);
443 } else if (!strcmp (type
, "code")) {
444 return (EFilterElement
*) e_filter_code_new (FALSE
);
445 } else if (!strcmp (type
, "rawcode")) {
446 return (EFilterElement
*) e_filter_code_new (TRUE
);
447 } else if (!strcmp (type
, "colour")) {
448 return (EFilterElement
*) e_filter_color_new ();
449 } else if (!strcmp (type
, "optionlist")) {
450 return (EFilterElement
*) e_filter_option_new ();
451 } else if (!strcmp (type
, "datespec")) {
452 return (EFilterElement
*) e_filter_datespec_new ();
453 } else if (!strcmp (type
, "command")) {
454 return (EFilterElement
*) e_filter_file_new_type_name (type
);
455 } else if (!strcmp (type
, "file")) {
456 return (EFilterElement
*) e_filter_file_new_type_name (type
);
457 } else if (!strcmp (type
, "integer")) {
458 return (EFilterElement
*) e_filter_int_new ();
459 } else if (!strcmp (type
, "regex")) {
460 return (EFilterElement
*) e_filter_input_new_type_name (type
);
461 } else if (!strcmp (type
, "completedpercent")) {
462 return (EFilterElement
*) e_filter_int_new_type (
463 "completedpercent", 0,100);
465 g_warning ("Unknown filter type '%s'", type
);
471 e_rule_context_class_init (ERuleContextClass
*class)
473 GObjectClass
*object_class
;
475 g_type_class_add_private (class, sizeof (ERuleContextPrivate
));
477 object_class
= G_OBJECT_CLASS (class);
478 object_class
->finalize
= rule_context_finalize
;
480 class->load
= rule_context_load
;
481 class->save
= rule_context_save
;
482 class->revert
= rule_context_revert
;
483 class->new_element
= rule_context_new_element
;
485 signals
[RULE_ADDED
] = g_signal_new (
489 G_STRUCT_OFFSET (ERuleContextClass
, rule_added
),
492 g_cclosure_marshal_VOID__POINTER
,
496 signals
[RULE_REMOVED
] = g_signal_new (
500 G_STRUCT_OFFSET (ERuleContextClass
, rule_removed
),
503 g_cclosure_marshal_VOID__POINTER
,
507 signals
[CHANGED
] = g_signal_new (
511 G_STRUCT_OFFSET (ERuleContextClass
, changed
),
514 g_cclosure_marshal_VOID__VOID
,
519 e_rule_context_init (ERuleContext
*context
)
521 context
->priv
= E_RULE_CONTEXT_GET_PRIVATE (context
);
523 context
->part_set_map
= g_hash_table_new (g_str_hash
, g_str_equal
);
524 context
->rule_set_map
= g_hash_table_new (g_str_hash
, g_str_equal
);
526 context
->flags
= E_RULE_CONTEXT_GROUPING
;
530 * e_rule_context_new:
532 * Create a new ERuleContext object.
534 * Return value: A new #ERuleContext object.
537 e_rule_context_new (void)
539 return g_object_new (E_TYPE_RULE_CONTEXT
, NULL
);
543 e_rule_context_add_part_set (ERuleContext
*context
,
544 const gchar
*setname
,
546 ERuleContextPartFunc append
,
547 ERuleContextNextPartFunc next
)
549 struct _part_set_map
*map
;
551 g_return_if_fail (E_IS_RULE_CONTEXT (context
));
552 g_return_if_fail (setname
!= NULL
);
553 g_return_if_fail (append
!= NULL
);
554 g_return_if_fail (next
!= NULL
);
556 g_return_if_fail (g_hash_table_lookup (context
->part_set_map
, setname
) == NULL
);
558 map
= g_malloc0 (sizeof (*map
));
559 map
->type
= part_type
;
560 map
->append
= append
;
562 map
->name
= g_strdup (setname
);
563 g_hash_table_insert (context
->part_set_map
, map
->name
, map
);
564 context
->part_set_list
= g_list_append (context
->part_set_list
, map
);
568 e_rule_context_add_rule_set (ERuleContext
*context
,
569 const gchar
*setname
,
571 ERuleContextRuleFunc append
,
572 ERuleContextNextRuleFunc next
)
574 struct _rule_set_map
*map
;
576 g_return_if_fail (E_IS_RULE_CONTEXT (context
));
577 g_return_if_fail (setname
!= NULL
);
578 g_return_if_fail (append
!= NULL
);
579 g_return_if_fail (next
!= NULL
);
581 g_return_if_fail (g_hash_table_lookup (context
->rule_set_map
, setname
) == NULL
);
583 map
= g_malloc0 (sizeof (*map
));
584 map
->type
= rule_type
;
585 map
->append
= append
;
587 map
->name
= g_strdup (setname
);
588 g_hash_table_insert (context
->rule_set_map
, map
->name
, map
);
589 context
->rule_set_list
= g_list_append (context
->rule_set_list
, map
);
593 * e_rule_context_load:
598 * Load a rule context from a system and user description file.
603 e_rule_context_load (ERuleContext
*context
,
607 ERuleContextClass
*class;
610 g_return_val_if_fail (E_IS_RULE_CONTEXT (context
), -1);
611 g_return_val_if_fail (system
!= NULL
, -1);
612 g_return_val_if_fail (user
!= NULL
, -1);
614 class = E_RULE_CONTEXT_GET_CLASS (context
);
615 g_return_val_if_fail (class->load
!= NULL
, -1);
617 context
->priv
->frozen
++;
618 result
= class->load (context
, system
, user
);
619 context
->priv
->frozen
--;
625 * e_rule_context_save:
629 * Save a rule context to disk.
634 e_rule_context_save (ERuleContext
*context
,
637 ERuleContextClass
*class;
639 g_return_val_if_fail (E_IS_RULE_CONTEXT (context
), -1);
640 g_return_val_if_fail (user
!= NULL
, -1);
642 class = E_RULE_CONTEXT_GET_CLASS (context
);
643 g_return_val_if_fail (class->save
!= NULL
, -1);
645 return class->save (context
, user
);
649 * e_rule_context_revert:
653 * Reverts a rule context from a user description file. Assumes the
654 * system description file is unchanged from when it was loaded.
659 e_rule_context_revert (ERuleContext
*context
,
662 ERuleContextClass
*class;
664 g_return_val_if_fail (E_RULE_CONTEXT (context
), 0);
665 g_return_val_if_fail (user
!= NULL
, 0);
667 class = E_RULE_CONTEXT_GET_CLASS (context
);
668 g_return_val_if_fail (class->revert
!= NULL
, 0);
670 return class->revert (context
, user
);
674 e_rule_context_find_part (ERuleContext
*context
,
677 g_return_val_if_fail (E_IS_RULE_CONTEXT (context
), NULL
);
678 g_return_val_if_fail (name
!= NULL
, NULL
);
680 return e_filter_part_find_list (context
->parts
, name
);
684 e_rule_context_create_part (ERuleContext
*context
,
689 g_return_val_if_fail (E_IS_RULE_CONTEXT (context
), NULL
);
690 g_return_val_if_fail (name
!= NULL
, NULL
);
692 part
= e_rule_context_find_part (context
, name
);
697 return e_filter_part_clone (part
);
701 e_rule_context_next_part (ERuleContext
*context
,
704 g_return_val_if_fail (E_IS_RULE_CONTEXT (context
), NULL
);
706 return e_filter_part_next_list (context
->parts
, last
);
710 e_rule_context_next_rule (ERuleContext
*context
,
714 g_return_val_if_fail (E_IS_RULE_CONTEXT (context
), NULL
);
716 return e_filter_rule_next_list (context
->rules
, last
, source
);
720 e_rule_context_find_rule (ERuleContext
*context
,
724 g_return_val_if_fail (E_IS_RULE_CONTEXT (context
), NULL
);
725 g_return_val_if_fail (name
!= NULL
, NULL
);
727 return e_filter_rule_find_list (context
->rules
, name
, source
);
731 e_rule_context_add_part (ERuleContext
*context
,
734 g_return_if_fail (E_IS_RULE_CONTEXT (context
));
735 g_return_if_fail (E_IS_FILTER_PART (part
));
737 context
->parts
= g_list_append (context
->parts
, part
);
741 e_rule_context_add_rule (ERuleContext
*context
,
744 g_return_if_fail (E_IS_RULE_CONTEXT (context
));
745 g_return_if_fail (E_IS_FILTER_RULE (rule
));
747 context
->rules
= g_list_append (context
->rules
, rule
);
749 if (context
->priv
->frozen
== 0) {
750 g_signal_emit (context
, signals
[RULE_ADDED
], 0, rule
);
751 g_signal_emit (context
, signals
[CHANGED
], 0);
755 /* Add a rule, with a gui, asking for confirmation first,
756 * and optionally save to path. */
758 e_rule_context_add_rule_gui (ERuleContext
*context
,
765 GtkWidget
*content_area
;
767 g_return_if_fail (E_IS_RULE_CONTEXT (context
));
768 g_return_if_fail (E_IS_FILTER_RULE (rule
));
770 widget
= e_filter_rule_get_widget (rule
, context
);
771 gtk_widget_show (widget
);
773 dialog
=(GtkDialog
*) gtk_dialog_new ();
774 gtk_dialog_add_buttons (dialog
,
775 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
776 GTK_STOCK_OK
, GTK_RESPONSE_OK
,
778 #if !GTK_CHECK_VERSION(2,90,7)
779 g_object_set (dialog
, "has-separator", FALSE
, NULL
);
782 gtk_window_set_title ((GtkWindow
*) dialog
, title
);
783 gtk_window_set_default_size ((GtkWindow
*) dialog
, 600, 400);
784 gtk_window_set_resizable ((GtkWindow
*) dialog
, TRUE
);
786 content_area
= gtk_dialog_get_content_area (dialog
);
787 gtk_box_pack_start (GTK_BOX (content_area
), widget
, TRUE
, TRUE
, 0);
789 g_object_set_data_full ((GObject
*) dialog
, "rule", rule
, g_object_unref
);
791 g_object_set_data_full ((GObject
*) dialog
, "path", g_strdup (path
), g_free
);
793 g_signal_connect (dialog
, "response", G_CALLBACK (new_rule_response
), context
);
795 g_object_ref (context
);
797 g_object_set_data_full ((GObject
*) dialog
, "context", context
, g_object_unref
);
799 gtk_widget_show ((GtkWidget
*) dialog
);
803 e_rule_context_remove_rule (ERuleContext
*context
,
806 g_return_if_fail (E_IS_RULE_CONTEXT (context
));
807 g_return_if_fail (E_IS_FILTER_RULE (rule
));
809 context
->rules
= g_list_remove (context
->rules
, rule
);
811 if (context
->priv
->frozen
== 0) {
812 g_signal_emit (context
, signals
[RULE_REMOVED
], 0, rule
);
813 g_signal_emit (context
, signals
[CHANGED
], 0);
818 e_rule_context_rank_rule (ERuleContext
*context
,
824 gint i
= 0, index
= 0;
826 g_return_if_fail (E_IS_RULE_CONTEXT (context
));
827 g_return_if_fail (E_IS_FILTER_RULE (rule
));
829 if (e_rule_context_get_rank_rule (context
, rule
, source
) == rank
)
832 context
->rules
= g_list_remove (context
->rules
, rule
);
833 node
= context
->rules
;
835 EFilterRule
*r
= node
->data
;
838 context
->rules
= g_list_insert (context
->rules
, rule
, index
);
839 if (context
->priv
->frozen
== 0)
840 g_signal_emit (context
, signals
[CHANGED
], 0);
846 if (source
== NULL
|| (r
->source
&& strcmp (r
->source
, source
) == 0))
852 context
->rules
= g_list_append (context
->rules
, rule
);
853 if (context
->priv
->frozen
== 0)
854 g_signal_emit (context
, signals
[CHANGED
], 0);
858 e_rule_context_get_rank_rule (ERuleContext
*context
,
865 g_return_val_if_fail (E_IS_RULE_CONTEXT (context
), -1);
866 g_return_val_if_fail (E_IS_FILTER_RULE (rule
), -1);
868 node
= context
->rules
;
870 EFilterRule
*r
= node
->data
;
875 if (source
== NULL
|| (r
->source
&& strcmp (r
->source
, source
) == 0))
885 e_rule_context_find_rank_rule (ERuleContext
*context
,
892 g_return_val_if_fail (E_IS_RULE_CONTEXT (context
), NULL
);
894 node
= context
->rules
;
896 EFilterRule
*r
= node
->data
;
898 if (source
== NULL
|| (r
->source
&& strcmp (r
->source
, source
) == 0)) {
911 e_rule_context_rename_uri (ERuleContext
*context
,
912 const gchar
*old_uri
,
913 const gchar
*new_uri
,
914 GCompareFunc compare
)
916 ERuleContextClass
*class;
918 g_return_val_if_fail (E_IS_RULE_CONTEXT (context
), NULL
);
919 g_return_val_if_fail (old_uri
!= NULL
, NULL
);
920 g_return_val_if_fail (new_uri
!= NULL
, NULL
);
921 g_return_val_if_fail (compare
!= NULL
, NULL
);
923 class = E_RULE_CONTEXT_GET_CLASS (context
);
925 /* This method is optional. */
926 if (class->rename_uri
== NULL
)
929 return class->rename_uri (context
, old_uri
, new_uri
, compare
);
933 e_rule_context_delete_uri (ERuleContext
*context
,
935 GCompareFunc compare
)
937 ERuleContextClass
*class;
939 g_return_val_if_fail (E_IS_RULE_CONTEXT (context
), NULL
);
940 g_return_val_if_fail (uri
!= NULL
, NULL
);
941 g_return_val_if_fail (compare
!= NULL
, NULL
);
943 class = E_RULE_CONTEXT_GET_CLASS (context
);
945 /* This method is optional. */
946 if (class->delete_uri
== NULL
)
949 return class->delete_uri (context
, uri
, compare
);
953 e_rule_context_free_uri_list (ERuleContext
*context
,
956 g_return_if_fail (E_IS_RULE_CONTEXT (context
));
958 /* TODO: should be virtual */
960 g_list_foreach (uris
, (GFunc
) g_free
, NULL
);
965 * e_rule_context_new_element:
969 * create a new filter element based on name.
974 e_rule_context_new_element (ERuleContext
*context
,
977 ERuleContextClass
*class;
979 g_return_val_if_fail (E_IS_RULE_CONTEXT (context
), NULL
);
980 g_return_val_if_fail (name
!= NULL
, NULL
);
982 class = E_RULE_CONTEXT_GET_CLASS (context
);
983 g_return_val_if_fail (class->new_element
!= NULL
, NULL
);
985 return class->new_element (context
, name
);