aboutsummaryrefslogtreecommitdiffstats
path: root/filter/e-filter-part.c
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2009-10-25 21:17:23 +0800
committerMatthew Barnes <mbarnes@redhat.com>2009-10-27 21:25:01 +0800
commit2b16aef84141800099f859e72d05e1e6bf8e02dd (patch)
treeb7168d8e9a4157a1f6733b0c667dd6239c5e0055 /filter/e-filter-part.c
parent58166e645971a4812fef23702f45cacc8e64e419 (diff)
downloadgsoc2013-evolution-2b16aef84141800099f859e72d05e1e6bf8e02dd.tar
gsoc2013-evolution-2b16aef84141800099f859e72d05e1e6bf8e02dd.tar.gz
gsoc2013-evolution-2b16aef84141800099f859e72d05e1e6bf8e02dd.tar.bz2
gsoc2013-evolution-2b16aef84141800099f859e72d05e1e6bf8e02dd.tar.lz
gsoc2013-evolution-2b16aef84141800099f859e72d05e1e6bf8e02dd.tar.xz
gsoc2013-evolution-2b16aef84141800099f859e72d05e1e6bf8e02dd.tar.zst
gsoc2013-evolution-2b16aef84141800099f859e72d05e1e6bf8e02dd.zip
Cleanup and rename filter classes.
Diffstat (limited to 'filter/e-filter-part.c')
-rw-r--r--filter/e-filter-part.c532
1 files changed, 532 insertions, 0 deletions
diff --git a/filter/e-filter-part.c b/filter/e-filter-part.c
new file mode 100644
index 0000000000..37e2bf61df
--- /dev/null
+++ b/filter/e-filter-part.c
@@ -0,0 +1,532 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jepartrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include "e-filter-file.h"
+#include "e-filter-part.h"
+#include "e-rule-context.h"
+
+static gpointer parent_class;
+
+static void
+filter_part_finalize (GObject *object)
+{
+ EFilterPart *part = E_FILTER_PART (object);
+
+ g_list_foreach (part->elements, (GFunc) g_object_unref, NULL);
+ g_list_free (part->elements);
+
+ g_free (part->name);
+ g_free (part->title);
+ g_free (part->code);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+filter_part_class_init (EFilterPartClass *class)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (class);
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = filter_part_finalize;
+}
+
+GType
+e_filter_part_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EFilterPartClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) filter_part_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EFilterPart),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) NULL,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ G_TYPE_OBJECT, "EFilterPart", &type_info, 0);
+ }
+
+ return type;
+}
+
+/**
+ * e_filter_part_new:
+ *
+ * Create a new EFilterPart object.
+ *
+ * Return value: A new #EFilterPart object.
+ **/
+EFilterPart *
+e_filter_part_new (void)
+{
+ return g_object_new (E_TYPE_FILTER_PART, NULL);
+}
+
+gboolean
+e_filter_part_validate (EFilterPart *part,
+ GtkWindow *error_parent)
+{
+ GList *link;
+
+ g_return_val_if_fail (E_IS_FILTER_PART (part), FALSE);
+
+ /* The part is valid if all of its elements are valid. */
+ for (link = part->elements; link != NULL; link = g_list_next (link)) {
+ EFilterElement *element = link->data;
+
+ if (!e_filter_element_validate (element, error_parent))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gint
+e_filter_part_eq (EFilterPart *part_a,
+ EFilterPart *part_b)
+{
+ GList *link_a, *link_b;
+
+ g_return_val_if_fail (E_IS_FILTER_PART (part_a), FALSE);
+ g_return_val_if_fail (E_IS_FILTER_PART (part_b), FALSE);
+
+ if (g_strcmp0 (part_a->name, part_b->name) != 0)
+ return FALSE;
+
+ if (g_strcmp0 (part_a->title, part_b->title) != 0)
+ return FALSE;
+
+ if (g_strcmp0 (part_a->code, part_b->code) != 0)
+ return FALSE;
+
+ link_a = part_a->elements;
+ link_b = part_b->elements;
+
+ while (link_a != NULL && link_b != NULL) {
+ EFilterElement *element_a = link_a->data;
+ EFilterElement *element_b = link_b->data;
+
+ if (!e_filter_element_eq (element_a, element_b))
+ return FALSE;
+
+ link_a = g_list_next (link_a);
+ link_b = g_list_next (link_b);
+ }
+
+ if (link_a != NULL || link_b != NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+gint
+e_filter_part_xml_create (EFilterPart *part,
+ xmlNodePtr node,
+ ERuleContext *context)
+{
+ xmlNodePtr n;
+ gchar *type, *str;
+ EFilterElement *el;
+
+ g_return_val_if_fail (E_IS_FILTER_PART (part), FALSE);
+ g_return_val_if_fail (node != NULL, FALSE);
+ g_return_val_if_fail (E_IS_RULE_CONTEXT (context), FALSE);
+
+ str = (gchar *)xmlGetProp (node, (xmlChar *)"name");
+ part->name = g_strdup (str);
+ if (str)
+ xmlFree (str);
+
+ n = node->children;
+ while (n) {
+ if (!strcmp ((gchar *)n->name, "input")) {
+ type = (gchar *)xmlGetProp (n, (xmlChar *)"type");
+ if (type != NULL
+ && (el = e_rule_context_new_element (context, type)) != NULL) {
+ e_filter_element_xml_create (el, n);
+ xmlFree (type);
+ part->elements = g_list_append (part->elements, el);
+ } else {
+ g_warning ("Invalid xml format, missing/unknown input type");
+ }
+ } else if (!strcmp ((gchar *)n->name, "title") || !strcmp ((gchar *)n->name, "_title")) {
+ if (!part->title) {
+ str = (gchar *)xmlNodeGetContent (n);
+ part->title = g_strdup (str);
+ if (str)
+ xmlFree (str);
+ }
+ } else if (!strcmp ((gchar *)n->name, "code")) {
+ if (!part->code) {
+ str = (gchar *)xmlNodeGetContent (n);
+ part->code = g_strdup (str);
+ if (str)
+ xmlFree (str);
+ }
+ } else if (n->type == XML_ELEMENT_NODE) {
+ g_warning ("Unknown part element in xml: %s\n", n->name);
+ }
+ n = n->next;
+ }
+
+ return 0;
+}
+
+xmlNodePtr
+e_filter_part_xml_encode (EFilterPart *part)
+{
+ xmlNodePtr node;
+ GList *link;
+
+ g_return_val_if_fail (E_IS_FILTER_PART (part), NULL);
+
+ node = xmlNewNode (NULL, (xmlChar *)"part");
+ xmlSetProp (node, (xmlChar *)"name", (xmlChar *)part->name);
+
+ for (link = part->elements; link != NULL; link = g_list_next (link)) {
+ EFilterElement *element = link->data;
+ xmlNodePtr value;
+
+ value = e_filter_element_xml_encode (element);
+ xmlAddChild (node, value);
+ }
+
+ return node;
+}
+
+gint
+e_filter_part_xml_decode (EFilterPart *part,
+ xmlNodePtr node)
+{
+ xmlNodePtr child;
+
+ g_return_val_if_fail (E_IS_FILTER_PART (part), -1);
+ g_return_val_if_fail (node != NULL, -1);
+
+ for (child = node->children; child != NULL; child = child->next) {
+ EFilterElement *element;
+ xmlChar *name;
+
+ if (strcmp ((gchar *) child->name, "value") != 0)
+ continue;
+
+ name = xmlGetProp (child, (xmlChar *) "name");
+ element = e_filter_part_find_element (part, (gchar *) name);
+ xmlFree (name);
+
+ if (element != NULL)
+ e_filter_element_xml_decode (element, child);
+ }
+
+ return 0;
+}
+
+EFilterPart *
+e_filter_part_clone (EFilterPart *part)
+{
+ EFilterPart *clone;
+ GList *link;
+
+ g_return_val_if_fail (E_IS_FILTER_PART (part), NULL);
+
+ clone = g_object_new (G_OBJECT_TYPE (part), NULL, NULL);
+ clone->name = g_strdup (part->name);
+ clone->title = g_strdup (part->title);
+ clone->code = g_strdup (part->code);
+
+ for (link = part->elements; link != NULL; link = g_list_next (link)) {
+ EFilterElement *element = link->data;
+ EFilterElement *clone_element;
+
+ clone_element = e_filter_element_clone (element);
+ clone->elements = g_list_append (clone->elements, clone_element);
+ }
+
+ return clone;
+}
+
+/* only copies values of matching parts in the right order */
+void
+e_filter_part_copy_values (EFilterPart *dst_part,
+ EFilterPart *src_part)
+{
+ GList *dst_link, *src_link;
+
+ g_return_if_fail (E_IS_FILTER_PART (dst_part));
+ g_return_if_fail (E_IS_FILTER_PART (src_part));
+
+ /* NOTE: we go backwards, it just works better that way */
+
+ /* for each source type, search the dest type for
+ a matching type in the same order */
+ src_link = g_list_last (src_part->elements);
+ dst_link = g_list_last (dst_part->elements);
+
+ while (src_link != NULL && dst_link != NULL) {
+ EFilterElement *src_element = src_link->data;
+ GList *link = dst_link;
+
+ while (link != NULL) {
+ EFilterElement *dst_element = link->data;
+ GType dst_type = G_OBJECT_TYPE (dst_element);
+ GType src_type = G_OBJECT_TYPE (src_element);
+
+ if (dst_type == src_type) {
+ e_filter_element_copy_value (
+ dst_element, src_element);
+ dst_link = g_list_previous (link);
+ break;
+ }
+
+ link = g_list_previous (link);
+ }
+
+ src_link = g_list_previous (src_link);
+ }
+}
+
+EFilterElement *
+e_filter_part_find_element (EFilterPart *part,
+ const gchar *name)
+{
+ GList *link;
+
+ g_return_val_if_fail (E_IS_FILTER_PART (part), NULL);
+
+ if (name == NULL)
+ return NULL;
+
+ for (link = part->elements; link != NULL; link = g_list_next (link)) {
+ EFilterElement *element = link->data;
+
+ if (g_strcmp0 (element->name, name) == 0)
+ return element;
+ }
+
+ return NULL;
+}
+
+GtkWidget *
+e_filter_part_get_widget (EFilterPart *part)
+{
+ GtkWidget *hbox;
+ GList *link;
+
+ g_return_val_if_fail (E_IS_FILTER_PART (part), NULL);
+
+ hbox = gtk_hbox_new (FALSE, 3);
+
+ for (link = part->elements; link != NULL; link = g_list_next (link)) {
+ EFilterElement *element = link->data;
+ GtkWidget *widget;
+
+ widget = e_filter_element_get_widget (element);
+ if (widget != NULL)
+ gtk_box_pack_start (
+ GTK_BOX (hbox), widget,
+ E_IS_FILTER_FILE (element),
+ E_IS_FILTER_FILE (element), 3);
+ }
+
+ gtk_widget_show_all (hbox);
+
+ return hbox;
+}
+
+/**
+ * e_filter_part_build_code:
+ * @part:
+ * @out:
+ *
+ * Outputs the code of a part.
+ **/
+void
+e_filter_part_build_code (EFilterPart *part,
+ GString *out)
+{
+ GList *link;
+
+ g_return_if_fail (E_IS_FILTER_PART (part));
+ g_return_if_fail (out != NULL);
+
+ if (part->code != NULL)
+ e_filter_part_expand_code (part, part->code, out);
+
+ for (link = part->elements; link != NULL; link = g_list_next (link)) {
+ EFilterElement *element = link->data;
+ e_filter_element_build_code (element, out, part);
+ }
+}
+
+/**
+ * e_filter_part_build_code_list:
+ * @l:
+ * @out:
+ *
+ * Construct a list of the filter parts code into
+ * a single string.
+ **/
+void
+e_filter_part_build_code_list (GList *list,
+ GString *out)
+{
+ GList *link;
+
+ g_return_if_fail (out != NULL);
+
+ for (link = list; link != NULL; link = g_list_next (link)) {
+ EFilterPart *part = link->data;
+
+ e_filter_part_build_code (part, out);
+ g_string_append (out, "\n ");
+ }
+}
+
+/**
+ * e_filter_part_find_list:
+ * @l:
+ * @name:
+ *
+ * Find a filter part stored in a list.
+ *
+ * Return value:
+ **/
+EFilterPart *
+e_filter_part_find_list (GList *list,
+ const gchar *name)
+{
+ GList *link;
+
+ g_return_val_if_fail (name != NULL, NULL);
+
+ for (link = list; link != NULL; link = g_list_next (link)) {
+ EFilterPart *part = link->data;
+
+ if (!g_strcmp0 (part->name, name) == 0)
+ return part;
+ }
+
+ return NULL;
+}
+
+/**
+ * e_filter_part_next_list:
+ * @l:
+ * @last: The last item retrieved, or NULL to start
+ * from the beginning of the list.
+ *
+ * Iterate through a filter part list.
+ *
+ * Return value: The next value in the list, or NULL if the
+ * list is expired.
+ **/
+EFilterPart *
+e_filter_part_next_list (GList *list,
+ EFilterPart *last)
+{
+ GList *link = list;
+
+ if (last != NULL) {
+ link = g_list_find (list, last);
+ if (link == NULL)
+ link = list;
+ else
+ link = link->next;
+ }
+
+ return (link != NULL) ? link->data : NULL;
+}
+
+/**
+ * e_filter_part_expand_code:
+ * @part:
+ * @str:
+ * @out:
+ *
+ * Expands the variables in string @str based on the values of the part.
+ **/
+void
+e_filter_part_expand_code (EFilterPart *part,
+ const gchar *source,
+ GString *out)
+{
+ const gchar *newstart, *start, *end;
+ gchar *name = alloca (32);
+ gint len, namelen = 32;
+
+ g_return_if_fail (E_IS_FILTER_PART (part));
+ g_return_if_fail (source != NULL);
+ g_return_if_fail (out != NULL);
+
+ start = source;
+
+ while (start && (newstart = strstr (start, "${"))
+ && (end = strstr (newstart+2, "}")) ) {
+ EFilterElement *element;
+
+ len = end - newstart - 2;
+ if (len + 1 > namelen) {
+ namelen = (len + 1) * 2;
+ name = g_alloca (namelen);
+ }
+ memcpy (name, newstart+2, len);
+ name[len] = 0;
+
+ element = e_filter_part_find_element (part, name);
+ if (element != NULL) {
+ g_string_append_printf (out, "%.*s", (gint)(newstart-start), start);
+ e_filter_element_format_sexp (element, out);
+#if 0
+ } else if ((val = g_hash_table_lookup (part->globals, name))) {
+ g_string_append_printf (out, "%.*s", newstart-start, start);
+ e_sexp_encode_string (out, val);
+#endif
+ } else {
+ g_string_append_printf (out, "%.*s", (gint)(end-start+1), start);
+ }
+ start = end + 1;
+ }
+
+ g_string_append (out, start);
+}