aboutsummaryrefslogtreecommitdiffstats
path: root/filter/e-filter-rule.c
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2012-12-10 21:09:59 +0800
committerMatthew Barnes <mbarnes@redhat.com>2012-12-13 03:33:43 +0800
commitd09d8de870b6697c8a8b262e7e077b871a69b315 (patch)
tree3b718882e7a0bb0a996daf2967a033d91714c9b5 /filter/e-filter-rule.c
parentb61331ed03ac1c7a9b8614e25510040b9c60ae02 (diff)
downloadgsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar
gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.gz
gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.bz2
gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.lz
gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.xz
gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.zst
gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.zip
Consolidate base utility libraries into libeutil.
Evolution consists of entirely too many small utility libraries, which increases linking and loading time, places a burden on higher layers of the application (e.g. modules) which has to remember to link to all the small in-tree utility libraries, and makes it difficult to generate API documentation for these utility libraries in one Gtk-Doc module. Merge the following utility libraries under the umbrella of libeutil, and enforce a single-include policy on libeutil so we can reorganize the files as desired without disrupting its pseudo-public API. libemail-utils/libemail-utils.la libevolution-utils/libevolution-utils.la filter/libfilter.la widgets/e-timezone-dialog/libetimezonedialog.la widgets/menus/libmenus.la widgets/misc/libemiscwidgets.la widgets/table/libetable.la widgets/text/libetext.la This also merges libedataserverui from the Evolution-Data-Server module, since Evolution is its only consumer nowadays, and I'd like to make some improvements to those APIs without concern for backward-compatibility. And finally, start a Gtk-Doc module for libeutil. It's going to be a project just getting all the symbols _listed_ much less _documented_. But the skeletal structure is in place and I'm off to a good start.
Diffstat (limited to 'filter/e-filter-rule.c')
-rw-r--r--filter/e-filter-rule.c1242
1 files changed, 0 insertions, 1242 deletions
diff --git a/filter/e-filter-rule.c b/filter/e-filter-rule.c
deleted file mode 100644
index 548fe4cc87..0000000000
--- a/filter/e-filter-rule.c
+++ /dev/null
@@ -1,1242 +0,0 @@
-/*
- * 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>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-
-#include <gtk/gtk.h>
-#include <glib/gi18n.h>
-
-#include "libevolution-utils/e-alert-dialog.h"
-
-#include "e-filter-rule.h"
-#include "e-rule-context.h"
-
-#define E_FILTER_RULE_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_FILTER_RULE, EFilterRulePrivate))
-
-typedef struct _FilterPartData FilterPartData;
-typedef struct _FilterRuleData FilterRuleData;
-
-struct _EFilterRulePrivate {
- gint frozen;
-};
-
-struct _FilterPartData {
- EFilterRule *rule;
- ERuleContext *context;
- EFilterPart *part;
- GtkWidget *partwidget;
- GtkWidget *container;
-};
-
-struct _FilterRuleData {
- EFilterRule *rule;
- ERuleContext *context;
- GtkWidget *parts;
-};
-
-enum {
- CHANGED,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL];
-
-G_DEFINE_TYPE (
- EFilterRule,
- e_filter_rule,
- G_TYPE_OBJECT)
-
-static void
-filter_rule_grouping_changed_cb (GtkComboBox *combo_box,
- EFilterRule *rule)
-{
- rule->grouping = gtk_combo_box_get_active (combo_box);
-}
-
-static void
-filter_rule_threading_changed_cb (GtkComboBox *combo_box,
- EFilterRule *rule)
-{
- rule->threading = gtk_combo_box_get_active (combo_box);
-}
-
-static void
-part_combobox_changed (GtkComboBox *combobox,
- FilterPartData *data)
-{
- EFilterPart *part = NULL;
- EFilterPart *newpart;
- gint index, i;
-
- index = gtk_combo_box_get_active (combobox);
- for (i = 0, part = e_rule_context_next_part (data->context, part);
- part && i < index;
- i++, part = e_rule_context_next_part (data->context, part)) {
- /* traverse until reached index */
- }
-
- g_return_if_fail (part != NULL);
- g_return_if_fail (i == index);
-
- /* dont update if we haven't changed */
- if (!strcmp (part->title, data->part->title))
- return;
-
- /* here we do a widget shuffle, throw away the old widget/rulepart,
- * and create another */
- if (data->partwidget)
- gtk_container_remove (GTK_CONTAINER (data->container), data->partwidget);
-
- newpart = e_filter_part_clone (part);
- e_filter_part_copy_values (newpart, data->part);
- e_filter_rule_replace_part (data->rule, data->part, newpart);
- g_object_unref (data->part);
- data->part = newpart;
- data->partwidget = e_filter_part_get_widget (newpart);
- if (data->partwidget)
- gtk_box_pack_start (
- GTK_BOX (data->container),
- data->partwidget, TRUE, TRUE, 0);
-}
-
-static GtkWidget *
-get_rule_part_widget (ERuleContext *context,
- EFilterPart *newpart,
- EFilterRule *rule)
-{
- EFilterPart *part = NULL;
- GtkWidget *combobox;
- GtkWidget *hbox;
- GtkWidget *p;
- gint index = 0, current = 0;
- FilterPartData *data;
-
- data = g_malloc0 (sizeof (*data));
- data->rule = rule;
- data->context = context;
- data->part = newpart;
-
- hbox = gtk_hbox_new (FALSE, 0);
- /* only set to automatically clean up the memory */
- g_object_set_data_full ((GObject *) hbox, "data", data, g_free);
-
- p = e_filter_part_get_widget (newpart);
-
- data->partwidget = p;
- data->container = hbox;
-
- combobox = gtk_combo_box_text_new ();
-
- /* sigh, this is a little ugly */
- while ((part = e_rule_context_next_part (context, part))) {
- gtk_combo_box_text_append_text (
- GTK_COMBO_BOX_TEXT (combobox), _(part->title));
-
- if (!strcmp (newpart->title, part->title))
- current = index;
-
- index++;
- }
-
- gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), current);
- g_signal_connect (
- combobox, "changed",
- G_CALLBACK (part_combobox_changed), data);
- gtk_widget_show (combobox);
-
- gtk_box_pack_start (GTK_BOX (hbox), combobox, FALSE, FALSE, 0);
- if (p)
- gtk_box_pack_start (GTK_BOX (hbox), p, TRUE, TRUE, 0);
-
- gtk_widget_show_all (hbox);
-
- return hbox;
-}
-
-static void
-less_parts (GtkWidget *button,
- FilterRuleData *data)
-{
- EFilterPart *part;
- GtkWidget *rule;
- FilterPartData *part_data;
-
- if (g_list_length (data->rule->parts) < 1)
- return;
-
- rule = g_object_get_data ((GObject *) button, "rule");
- part_data = g_object_get_data ((GObject *) rule, "data");
-
- g_return_if_fail (part_data != NULL);
-
- part = part_data->part;
-
- /* remove the part from the list */
- e_filter_rule_remove_part (data->rule, part);
- g_object_unref (part);
-
- /* and from the display */
- gtk_container_remove (GTK_CONTAINER (data->parts), rule);
- gtk_container_remove (GTK_CONTAINER (data->parts), button);
-}
-
-static void
-attach_rule (GtkWidget *rule,
- FilterRuleData *data,
- EFilterPart *part,
- gint row)
-{
- GtkWidget *remove;
-
- gtk_table_attach (
- GTK_TABLE (data->parts), rule, 0, 1, row, row + 1,
- GTK_EXPAND | GTK_FILL, 0, 0, 0);
-
- remove = gtk_button_new_from_stock (GTK_STOCK_REMOVE);
- g_object_set_data ((GObject *) remove, "rule", rule);
- g_signal_connect (
- remove, "clicked",
- G_CALLBACK (less_parts), data);
- gtk_table_attach (
- GTK_TABLE (data->parts), remove, 1, 2, row, row + 1,
- 0, 0, 0, 0);
-
- gtk_widget_show (remove);
-}
-
-static void
-do_grab_focus_cb (GtkWidget *widget,
- gpointer data)
-{
- gboolean *done = (gboolean *) data;
-
- if (*done || !widget)
- return;
-
- if (gtk_widget_get_can_focus (widget) || GTK_IS_COMBO_BOX (widget)) {
- *done = TRUE;
- gtk_widget_grab_focus (widget);
- } else if (GTK_IS_CONTAINER (widget)) {
- gtk_container_foreach (GTK_CONTAINER (widget), do_grab_focus_cb, done);
- }
-}
-
-static void
-more_parts (GtkWidget *button,
- FilterRuleData *data)
-{
- EFilterPart *new;
-
- /* first make sure that the last part is ok */
- if (data->rule->parts) {
- EFilterPart *part;
- GList *l;
- EAlert *alert = NULL;
-
- l = g_list_last (data->rule->parts);
- part = l->data;
- if (!e_filter_part_validate (part, &alert)) {
- GtkWidget *toplevel;
- toplevel = gtk_widget_get_toplevel (button);
- e_alert_run_dialog (GTK_WINDOW (toplevel), alert);
- return;
- }
- }
-
- /* create a new rule entry, use the first type of rule */
- new = e_rule_context_next_part (data->context, NULL);
- if (new) {
- GtkWidget *w;
- guint rows;
-
- new = e_filter_part_clone (new);
- e_filter_rule_add_part (data->rule, new);
- w = get_rule_part_widget (data->context, new, data->rule);
-
- g_object_get (data->parts, "n-rows", &rows, NULL);
- gtk_table_resize (GTK_TABLE (data->parts), rows + 1, 2);
- attach_rule (w, data, new, rows);
-
- if (GTK_IS_CONTAINER (w)) {
- gboolean done = FALSE;
-
- gtk_container_foreach (GTK_CONTAINER (w), do_grab_focus_cb, &done);
- } else
- gtk_widget_grab_focus (w);
-
- /* also scroll down to see new part */
- w = (GtkWidget *) g_object_get_data (G_OBJECT (button), "scrolled-window");
- if (w) {
- GtkAdjustment *adjustment;
-
- adjustment = gtk_scrolled_window_get_vadjustment (
- GTK_SCROLLED_WINDOW (w));
- if (adjustment) {
- gdouble upper;
-
- upper = gtk_adjustment_get_upper (adjustment);
- gtk_adjustment_set_value (adjustment, upper);
- }
-
- }
- }
-}
-
-static void
-name_changed (GtkEntry *entry,
- EFilterRule *rule)
-{
- g_free (rule->name);
- rule->name = g_strdup (gtk_entry_get_text (entry));
-}
-
-GtkWidget *
-e_filter_rule_get_widget (EFilterRule *rule,
- ERuleContext *context)
-{
- EFilterRuleClass *class;
-
- g_return_val_if_fail (E_IS_FILTER_RULE (rule), NULL);
- g_return_val_if_fail (E_IS_RULE_CONTEXT (context), NULL);
-
- class = E_FILTER_RULE_GET_CLASS (rule);
- g_return_val_if_fail (class->get_widget != NULL, NULL);
-
- return class->get_widget (rule, context);
-}
-
-static void
-filter_rule_load_set (xmlNodePtr node,
- EFilterRule *rule,
- ERuleContext *context)
-{
- xmlNodePtr work;
- gchar *rulename;
- EFilterPart *part;
-
- work = node->children;
- while (work) {
- if (!strcmp ((gchar *) work->name, "part")) {
- rulename = (gchar *) xmlGetProp (work, (xmlChar *)"name");
- part = e_rule_context_find_part (context, rulename);
- if (part) {
- part = e_filter_part_clone (part);
- e_filter_part_xml_decode (part, work);
- e_filter_rule_add_part (rule, part);
- } else {
- g_warning ("cannot find rule part '%s'\n", rulename);
- }
- xmlFree (rulename);
- } else if (work->type == XML_ELEMENT_NODE) {
- g_warning ("Unknown xml node in part: %s", work->name);
- }
- work = work->next;
- }
-}
-
-static void
-filter_rule_finalize (GObject *object)
-{
- EFilterRule *rule = E_FILTER_RULE (object);
-
- g_free (rule->name);
- g_free (rule->source);
-
- g_list_foreach (rule->parts, (GFunc) g_object_unref, NULL);
- g_list_free (rule->parts);
-
- /* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (e_filter_rule_parent_class)->finalize (object);
-}
-
-static gint
-filter_rule_validate (EFilterRule *rule,
- EAlert **alert)
-{
- gint valid = TRUE;
- GList *parts;
-
- g_warn_if_fail (alert == NULL || *alert == NULL);
- if (!rule->name || !*rule->name) {
- if (alert)
- *alert = e_alert_new ("filter:no-name", NULL);
-
- return FALSE;
- }
-
- /* validate rule parts */
- parts = rule->parts;
- valid = parts != NULL;
- while (parts && valid) {
- valid = e_filter_part_validate ((EFilterPart *) parts->data, alert);
- parts = parts->next;
- }
-
- return valid;
-}
-
-static gint
-filter_rule_eq (EFilterRule *rule_a,
- EFilterRule *rule_b)
-{
- GList *link_a;
- GList *link_b;
-
- if (rule_a->enabled != rule_b->enabled)
- return FALSE;
-
- if (rule_a->grouping != rule_b->grouping)
- return FALSE;
-
- if (rule_a->threading != rule_b->threading)
- return FALSE;
-
- if (g_strcmp0 (rule_a->name, rule_b->name) != 0)
- return FALSE;
-
- if (g_strcmp0 (rule_a->source, rule_b->source) != 0)
- return FALSE;
-
- link_a = rule_a->parts;
- link_b = rule_b->parts;
-
- while (link_a != NULL && link_b != NULL) {
- EFilterPart *part_a = link_a->data;
- EFilterPart *part_b = link_b->data;
-
- if (!e_filter_part_eq (part_a, part_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;
-}
-
-static xmlNodePtr
-filter_rule_xml_encode (EFilterRule *rule)
-{
- xmlNodePtr node, set, work;
- GList *l;
-
- node = xmlNewNode (NULL, (xmlChar *)"rule");
-
- xmlSetProp (
- node, (xmlChar *)"enabled",
- (xmlChar *)(rule->enabled ? "true" : "false"));
-
- switch (rule->grouping) {
- case E_FILTER_GROUP_ALL:
- xmlSetProp (node, (xmlChar *)"grouping", (xmlChar *)"all");
- break;
- case E_FILTER_GROUP_ANY:
- xmlSetProp (node, (xmlChar *)"grouping", (xmlChar *)"any");
- break;
- }
-
- switch (rule->threading) {
- case E_FILTER_THREAD_NONE:
- break;
- case E_FILTER_THREAD_ALL:
- xmlSetProp (node, (xmlChar *)"threading", (xmlChar *)"all");
- break;
- case E_FILTER_THREAD_REPLIES:
- xmlSetProp (node, (xmlChar *)"threading", (xmlChar *)"replies");
- break;
- case E_FILTER_THREAD_REPLIES_PARENTS:
- xmlSetProp (node, (xmlChar *)"threading", (xmlChar *)"replies_parents");
- break;
- case E_FILTER_THREAD_SINGLE:
- xmlSetProp (node, (xmlChar *)"threading", (xmlChar *)"single");
- break;
- }
-
- if (rule->source) {
- xmlSetProp (node, (xmlChar *)"source", (xmlChar *) rule->source);
- } else {
- /* set to the default filter type */
- xmlSetProp (node, (xmlChar *)"source", (xmlChar *)"incoming");
- }
-
- if (rule->name) {
- gchar *escaped = g_markup_escape_text (rule->name, -1);
-
- work = xmlNewNode (NULL, (xmlChar *)"title");
- xmlNodeSetContent (work, (xmlChar *) escaped);
- xmlAddChild (node, work);
-
- g_free (escaped);
- }
-
- set = xmlNewNode (NULL, (xmlChar *)"partset");
- xmlAddChild (node, set);
- l = rule->parts;
- while (l) {
- work = e_filter_part_xml_encode ((EFilterPart *) l->data);
- xmlAddChild (set, work);
- l = l->next;
- }
-
- return node;
-}
-
-static gint
-filter_rule_xml_decode (EFilterRule *rule,
- xmlNodePtr node,
- ERuleContext *context)
-{
- xmlNodePtr work;
- gchar *grouping;
- gchar *source;
-
- g_free (rule->name);
- rule->name = NULL;
-
- grouping = (gchar *) xmlGetProp (node, (xmlChar *)"enabled");
- if (!grouping)
- rule->enabled = TRUE;
- else {
- rule->enabled = strcmp (grouping, "false") != 0;
- xmlFree (grouping);
- }
-
- grouping = (gchar *) xmlGetProp (node, (xmlChar *)"grouping");
- if (!strcmp (grouping, "any"))
- rule->grouping = E_FILTER_GROUP_ANY;
- else
- rule->grouping = E_FILTER_GROUP_ALL;
- xmlFree (grouping);
-
- rule->threading = E_FILTER_THREAD_NONE;
- if (context->flags & E_RULE_CONTEXT_THREADING
- && (grouping = (gchar *) xmlGetProp (node, (xmlChar *)"threading"))) {
- if (!strcmp (grouping, "all"))
- rule->threading = E_FILTER_THREAD_ALL;
- else if (!strcmp (grouping, "replies"))
- rule->threading = E_FILTER_THREAD_REPLIES;
- else if (!strcmp (grouping, "replies_parents"))
- rule->threading = E_FILTER_THREAD_REPLIES_PARENTS;
- else if (!strcmp (grouping, "single"))
- rule->threading = E_FILTER_THREAD_SINGLE;
- xmlFree (grouping);
- }
-
- g_free (rule->source);
- source = (gchar *) xmlGetProp (node, (xmlChar *)"source");
- if (source) {
- rule->source = g_strdup (source);
- xmlFree (source);
- } else {
- /* default filter type */
- rule->source = g_strdup ("incoming");
- }
-
- work = node->children;
- while (work) {
- if (!strcmp ((gchar *) work->name, "partset")) {
- filter_rule_load_set (work, rule, context);
- } else if (!strcmp ((gchar *) work->name, "title") ||
- !strcmp ((gchar *) work->name, "_title")) {
-
- if (!rule->name) {
- gchar *str, *decstr = NULL;
-
- str = (gchar *) xmlNodeGetContent (work);
- if (str) {
- decstr = g_strdup (_(str));
- xmlFree (str);
- }
- rule->name = decstr;
- }
- }
- work = work->next;
- }
-
- return 0;
-}
-
-static void
-filter_rule_build_code (EFilterRule *rule,
- GString *out)
-{
- switch (rule->threading) {
- case E_FILTER_THREAD_NONE:
- break;
- case E_FILTER_THREAD_ALL:
- g_string_append (out, " (match-threads \"all\" ");
- break;
- case E_FILTER_THREAD_REPLIES:
- g_string_append (out, " (match-threads \"replies\" ");
- break;
- case E_FILTER_THREAD_REPLIES_PARENTS:
- g_string_append (out, " (match-threads \"replies_parents\" ");
- break;
- case E_FILTER_THREAD_SINGLE:
- g_string_append (out, " (match-threads \"single\" ");
- break;
- }
-
- switch (rule->grouping) {
- case E_FILTER_GROUP_ALL:
- g_string_append (out, " (and\n ");
- break;
- case E_FILTER_GROUP_ANY:
- g_string_append (out, " (or\n ");
- break;
- default:
- g_warning ("Invalid grouping");
- }
-
- e_filter_part_build_code_list (rule->parts, out);
- g_string_append (out, ")\n");
-
- if (rule->threading != E_FILTER_THREAD_NONE)
- g_string_append (out, ")\n");
-}
-
-static void
-filter_rule_copy (EFilterRule *dest,
- EFilterRule *src)
-{
- GList *node;
-
- dest->enabled = src->enabled;
-
- g_free (dest->name);
- dest->name = g_strdup (src->name);
-
- g_free (dest->source);
- dest->source = g_strdup (src->source);
-
- dest->grouping = src->grouping;
- dest->threading = src->threading;
-
- if (dest->parts) {
- g_list_foreach (dest->parts, (GFunc) g_object_unref, NULL);
- g_list_free (dest->parts);
- dest->parts = NULL;
- }
-
- node = src->parts;
- while (node) {
- EFilterPart *part;
-
- part = e_filter_part_clone (node->data);
- dest->parts = g_list_append (dest->parts, part);
- node = node->next;
- }
-}
-
-static void
-ensure_scrolled_width_cb (GtkAdjustment *adj,
- GParamSpec *param_spec,
- GtkScrolledWindow *scrolled_window)
-{
- gtk_scrolled_window_set_min_content_width (
- scrolled_window,
- gtk_adjustment_get_upper (adj));
-}
-
-static void
-ensure_scrolled_height_cb (GtkAdjustment *adj,
- GParamSpec *param_spec,
- GtkScrolledWindow *scrolled_window)
-{
- GtkWidget *toplevel;
- GdkScreen *screen;
- gint toplevel_height, scw_height, require_scw_height = 0, max_height;
-
- toplevel = gtk_widget_get_toplevel (GTK_WIDGET (scrolled_window));
- if (!toplevel || !gtk_widget_is_toplevel (toplevel))
- return;
-
- scw_height = gtk_widget_get_allocated_height (GTK_WIDGET (scrolled_window));
-
- gtk_widget_get_preferred_height_for_width (gtk_bin_get_child (GTK_BIN (scrolled_window)),
- gtk_widget_get_allocated_width (GTK_WIDGET (scrolled_window)),
- &require_scw_height, NULL);
-
- if (scw_height >= require_scw_height) {
- if (require_scw_height > 0)
- gtk_scrolled_window_set_min_content_height (scrolled_window, require_scw_height);
- return;
- }
-
- if (!GTK_IS_WINDOW (toplevel) ||
- !gtk_widget_get_window (toplevel))
- return;
-
- screen = gtk_window_get_screen (GTK_WINDOW (toplevel));
- if (screen) {
- gint monitor;
- GdkRectangle workarea;
-
- monitor = gdk_screen_get_monitor_at_window (screen, gtk_widget_get_window (toplevel));
- if (monitor < 0)
- monitor = 0;
-
- gdk_screen_get_monitor_workarea (screen, monitor, &workarea);
-
- /* can enlarge up to 4 / 5 monitor's work area height */
- max_height = workarea.height * 4 / 5;
- } else {
- return;
- }
-
- toplevel_height = gtk_widget_get_allocated_height (toplevel);
- if (toplevel_height + require_scw_height - scw_height > max_height)
- return;
-
- gtk_scrolled_window_set_min_content_height (scrolled_window, require_scw_height);
-}
-
-static GtkWidget *
-filter_rule_get_widget (EFilterRule *rule,
- ERuleContext *context)
-{
- GtkGrid *hgrid, *vgrid, *inframe;
- GtkWidget *parts, *add, *label, *name, *w;
- GtkWidget *combobox;
- GtkWidget *scrolledwindow;
- GtkAdjustment *hadj, *vadj;
- GList *l;
- gchar *text;
- EFilterPart *part;
- FilterRuleData *data;
- gint rows, i;
-
- /* this stuff should probably be a table, but the
- * rule parts need to be a vbox */
- vgrid = GTK_GRID (gtk_grid_new ());
- gtk_grid_set_row_spacing (vgrid, 6);
- gtk_orientable_set_orientation (GTK_ORIENTABLE (vgrid), GTK_ORIENTATION_VERTICAL);
-
- label = gtk_label_new_with_mnemonic (_("R_ule name:"));
- name = gtk_entry_new ();
- gtk_widget_set_hexpand (name, TRUE);
- gtk_widget_set_halign (name, GTK_ALIGN_FILL);
- gtk_label_set_mnemonic_widget ((GtkLabel *) label, name);
-
- if (!rule->name) {
- rule->name = g_strdup (_("Untitled"));
- gtk_entry_set_text (GTK_ENTRY (name), rule->name);
- /* FIXME: do we want the following code in the future? */
- /*gtk_editable_select_region (GTK_EDITABLE (name), 0, -1);*/
- } else {
- gtk_entry_set_text (GTK_ENTRY (name), rule->name);
- }
-
- g_signal_connect (
- name, "realize",
- G_CALLBACK (gtk_widget_grab_focus), name);
-
- hgrid = GTK_GRID (gtk_grid_new ());
- gtk_grid_set_column_spacing (hgrid, 12);
-
- gtk_grid_attach (hgrid, label, 0, 0, 1, 1);
- gtk_grid_attach_next_to (hgrid, name, label, GTK_POS_RIGHT, 1, 1);
-
- gtk_container_add (GTK_CONTAINER (vgrid), GTK_WIDGET (hgrid));
-
- g_signal_connect (
- name, "changed",
- G_CALLBACK (name_changed), rule);
-
- hgrid = GTK_GRID (gtk_grid_new ());
- gtk_grid_set_column_spacing (hgrid, 12);
- gtk_container_add (GTK_CONTAINER (vgrid), GTK_WIDGET (hgrid));
-
- /* this is the parts table, it should probably be inside a scrolling list */
- rows = g_list_length (rule->parts);
- parts = gtk_table_new (rows, 2, FALSE);
-
- /* data for the parts part of the display */
- data = g_malloc0 (sizeof (*data));
- data->context = context;
- data->rule = rule;
- data->parts = parts;
-
- /* only set to automatically clean up the memory */
- g_object_set_data_full ((GObject *) vgrid, "data", data, g_free);
-
- if (context->flags & E_RULE_CONTEXT_GROUPING) {
- const gchar *thread_types[] = {
- N_("all the following conditions"),
- N_("any of the following conditions")
- };
-
- hgrid = GTK_GRID (gtk_grid_new ());
- gtk_grid_set_column_spacing (hgrid, 12);
-
- label = gtk_label_new_with_mnemonic (_("_Find items which match:"));
- combobox = gtk_combo_box_text_new ();
-
- for (i = 0; i < 2; i++) {
- gtk_combo_box_text_append_text (
- GTK_COMBO_BOX_TEXT (combobox),
- _(thread_types[i]));
- }
-
- gtk_label_set_mnemonic_widget ((GtkLabel *) label, combobox);
- gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), rule->grouping);
-
- gtk_grid_attach (hgrid, label, 0, 0, 1, 1);
- gtk_grid_attach_next_to (hgrid, combobox, label, GTK_POS_RIGHT, 1, 1);
-
- g_signal_connect (
- combobox, "changed",
- G_CALLBACK (filter_rule_grouping_changed_cb), rule);
-
- gtk_container_add (GTK_CONTAINER (vgrid), GTK_WIDGET (hgrid));
- } else {
- text = g_strdup_printf (
- "<b>%s</b>",
- _("Find items that meet the following conditions"));
- label = gtk_label_new (text);
- gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
- gtk_container_add (GTK_CONTAINER (vgrid), label);
- g_free (text);
- }
-
- hgrid = GTK_GRID (gtk_grid_new ());
- gtk_grid_set_column_spacing (hgrid, 12);
-
- if (context->flags & E_RULE_CONTEXT_THREADING) {
- const gchar *thread_types[] = {
- /* Translators: "None" for not including threads;
- * part of "Include threads: None" */
- N_("None"),
- N_("All related"),
- N_("Replies"),
- N_("Replies and parents"),
- N_("No reply or parent")
- };
-
- label = gtk_label_new_with_mnemonic (_("I_nclude threads:"));
- combobox = gtk_combo_box_text_new ();
-
- for (i = 0; i < 5; i++) {
- gtk_combo_box_text_append_text (
- GTK_COMBO_BOX_TEXT (combobox),
- _(thread_types[i]));
- }
-
- gtk_label_set_mnemonic_widget ((GtkLabel *) label, combobox);
- gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), rule->threading);
-
- gtk_grid_attach (hgrid, label, 0, 0, 1, 1);
- gtk_grid_attach_next_to (hgrid, combobox, label, GTK_POS_RIGHT, 1, 1);
-
- g_signal_connect (
- combobox, "changed",
- G_CALLBACK (filter_rule_threading_changed_cb), rule);
- }
-
- gtk_container_add (GTK_CONTAINER (vgrid), GTK_WIDGET (hgrid));
-
- hgrid = GTK_GRID (gtk_grid_new ());
- gtk_grid_set_column_spacing (hgrid, 3);
- gtk_widget_set_vexpand (GTK_WIDGET (hgrid), TRUE);
- gtk_widget_set_valign (GTK_WIDGET (hgrid), GTK_ALIGN_FILL);
-
- gtk_container_add (GTK_CONTAINER (vgrid), GTK_WIDGET (hgrid));
-
- label = gtk_label_new ("");
- gtk_grid_attach (hgrid, label, 0, 0, 1, 1);
-
- inframe = GTK_GRID (gtk_grid_new ());
- gtk_grid_set_row_spacing (inframe, 6);
- gtk_orientable_set_orientation (GTK_ORIENTABLE (inframe), GTK_ORIENTATION_VERTICAL);
- gtk_widget_set_hexpand (GTK_WIDGET (inframe), TRUE);
- gtk_widget_set_halign (GTK_WIDGET (inframe), GTK_ALIGN_FILL);
- gtk_widget_set_vexpand (GTK_WIDGET (inframe), TRUE);
- gtk_widget_set_valign (GTK_WIDGET (inframe), GTK_ALIGN_FILL);
- gtk_grid_attach_next_to (hgrid, GTK_WIDGET (inframe), label, GTK_POS_RIGHT, 1, 1);
-
- l = rule->parts;
- i = 0;
- while (l) {
- part = l->data;
- w = get_rule_part_widget (context, part, rule);
- attach_rule (w, data, part, i++);
- l = g_list_next (l);
- }
-
- hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 1.0, 1.0, 1.0, 1.0));
- vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 1.0, 1.0, 1.0, 1.0));
- scrolledwindow = gtk_scrolled_window_new (hadj, vadj);
-
- g_signal_connect (
- hadj, "notify::upper",
- G_CALLBACK (ensure_scrolled_width_cb), scrolledwindow);
- g_signal_connect (
- vadj, "notify::upper",
- G_CALLBACK (ensure_scrolled_height_cb), scrolledwindow);
-
- gtk_scrolled_window_set_policy (
- GTK_SCROLLED_WINDOW (scrolledwindow),
- GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
-
- gtk_scrolled_window_add_with_viewport (
- GTK_SCROLLED_WINDOW (scrolledwindow), parts);
-
- gtk_widget_set_vexpand (scrolledwindow, TRUE);
- gtk_widget_set_valign (scrolledwindow, GTK_ALIGN_FILL);
- gtk_widget_set_hexpand (scrolledwindow, TRUE);
- gtk_widget_set_halign (scrolledwindow, GTK_ALIGN_FILL);
- gtk_container_add (GTK_CONTAINER (inframe), scrolledwindow);
-
- hgrid = GTK_GRID (gtk_grid_new ());
- gtk_grid_set_column_spacing (hgrid, 3);
-
- add = gtk_button_new_with_mnemonic (_("A_dd Condition"));
- gtk_button_set_image (
- GTK_BUTTON (add), gtk_image_new_from_stock (
- GTK_STOCK_ADD, GTK_ICON_SIZE_BUTTON));
- g_signal_connect (
- add, "clicked",
- G_CALLBACK (more_parts), data);
- gtk_grid_attach (hgrid, add, 0, 0, 1, 1);
-
- gtk_container_add (GTK_CONTAINER (inframe), GTK_WIDGET (hgrid));
-
- gtk_widget_show_all (GTK_WIDGET (vgrid));
-
- g_object_set_data (G_OBJECT (add), "scrolled-window", scrolledwindow);
-
- return GTK_WIDGET (vgrid);
-}
-
-static void
-e_filter_rule_class_init (EFilterRuleClass *class)
-{
- GObjectClass *object_class;
-
- g_type_class_add_private (class, sizeof (EFilterRulePrivate));
-
- object_class = G_OBJECT_CLASS (class);
- object_class->finalize = filter_rule_finalize;
-
- class->validate = filter_rule_validate;
- class->eq = filter_rule_eq;
- class->xml_encode = filter_rule_xml_encode;
- class->xml_decode = filter_rule_xml_decode;
- class->build_code = filter_rule_build_code;
- class->copy = filter_rule_copy;
- class->get_widget = filter_rule_get_widget;
-
- signals[CHANGED] = g_signal_new (
- "changed",
- E_TYPE_FILTER_RULE,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EFilterRuleClass, changed),
- NULL,
- NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-}
-
-static void
-e_filter_rule_init (EFilterRule *rule)
-{
- rule->priv = E_FILTER_RULE_GET_PRIVATE (rule);
- rule->enabled = TRUE;
-}
-
-/**
- * filter_rule_new:
- *
- * Create a new EFilterRule object.
- *
- * Return value: A new #EFilterRule object.
- **/
-EFilterRule *
-e_filter_rule_new (void)
-{
- return g_object_new (E_TYPE_FILTER_RULE, NULL);
-}
-
-EFilterRule *
-e_filter_rule_clone (EFilterRule *rule)
-{
- EFilterRule *clone;
-
- g_return_val_if_fail (E_IS_FILTER_RULE (rule), NULL);
-
- clone = g_object_new (G_OBJECT_TYPE (rule), NULL);
- e_filter_rule_copy (clone, rule);
-
- return clone;
-}
-
-void
-e_filter_rule_set_name (EFilterRule *rule,
- const gchar *name)
-{
- g_return_if_fail (E_IS_FILTER_RULE (rule));
-
- if (g_strcmp0 (rule->name, name) == 0)
- return;
-
- g_free (rule->name);
- rule->name = g_strdup (name);
-
- e_filter_rule_emit_changed (rule);
-}
-
-void
-e_filter_rule_set_source (EFilterRule *rule,
- const gchar *source)
-{
- g_return_if_fail (E_IS_FILTER_RULE (rule));
-
- if (g_strcmp0 (rule->source, source) == 0)
- return;
-
- g_free (rule->source);
- rule->source = g_strdup (source);
-
- e_filter_rule_emit_changed (rule);
-}
-
-gint
-e_filter_rule_validate (EFilterRule *rule,
- EAlert **alert)
-{
- EFilterRuleClass *class;
-
- g_return_val_if_fail (E_IS_FILTER_RULE (rule), FALSE);
-
- class = E_FILTER_RULE_GET_CLASS (rule);
- g_return_val_if_fail (class->validate != NULL, FALSE);
-
- return class->validate (rule, alert);
-}
-
-gint
-e_filter_rule_eq (EFilterRule *rule_a,
- EFilterRule *rule_b)
-{
- EFilterRuleClass *class;
-
- g_return_val_if_fail (E_IS_FILTER_RULE (rule_a), FALSE);
- g_return_val_if_fail (E_IS_FILTER_RULE (rule_b), FALSE);
-
- class = E_FILTER_RULE_GET_CLASS (rule_a);
- g_return_val_if_fail (class->eq != NULL, FALSE);
-
- if (G_OBJECT_TYPE (rule_a) != G_OBJECT_TYPE (rule_b))
- return FALSE;
-
- return class->eq (rule_a, rule_b);
-}
-
-xmlNodePtr
-e_filter_rule_xml_encode (EFilterRule *rule)
-{
- EFilterRuleClass *class;
-
- g_return_val_if_fail (E_IS_FILTER_RULE (rule), NULL);
-
- class = E_FILTER_RULE_GET_CLASS (rule);
- g_return_val_if_fail (class->xml_encode != NULL, NULL);
-
- return class->xml_encode (rule);
-}
-
-gint
-e_filter_rule_xml_decode (EFilterRule *rule,
- xmlNodePtr node,
- ERuleContext *context)
-{
- EFilterRuleClass *class;
- gint result;
-
- g_return_val_if_fail (E_IS_FILTER_RULE (rule), FALSE);
- g_return_val_if_fail (node != NULL, FALSE);
- g_return_val_if_fail (E_IS_RULE_CONTEXT (context), FALSE);
-
- class = E_FILTER_RULE_GET_CLASS (rule);
- g_return_val_if_fail (class->xml_decode != NULL, FALSE);
-
- rule->priv->frozen++;
- result = class->xml_decode (rule, node, context);
- rule->priv->frozen--;
-
- e_filter_rule_emit_changed (rule);
-
- return result;
-}
-
-void
-e_filter_rule_copy (EFilterRule *dst_rule,
- EFilterRule *src_rule)
-{
- EFilterRuleClass *class;
-
- g_return_if_fail (E_IS_FILTER_RULE (dst_rule));
- g_return_if_fail (E_IS_FILTER_RULE (src_rule));
-
- class = E_FILTER_RULE_GET_CLASS (dst_rule);
- g_return_if_fail (class->copy != NULL);
-
- class->copy (dst_rule, src_rule);
-
- e_filter_rule_emit_changed (dst_rule);
-}
-
-void
-e_filter_rule_add_part (EFilterRule *rule,
- EFilterPart *part)
-{
- g_return_if_fail (E_IS_FILTER_RULE (rule));
- g_return_if_fail (E_IS_FILTER_PART (part));
-
- rule->parts = g_list_append (rule->parts, part);
-
- e_filter_rule_emit_changed (rule);
-}
-
-void
-e_filter_rule_remove_part (EFilterRule *rule,
- EFilterPart *part)
-{
- g_return_if_fail (E_IS_FILTER_RULE (rule));
- g_return_if_fail (E_IS_FILTER_PART (part));
-
- rule->parts = g_list_remove (rule->parts, part);
-
- e_filter_rule_emit_changed (rule);
-}
-
-void
-e_filter_rule_replace_part (EFilterRule *rule,
- EFilterPart *old_part,
- EFilterPart *new_part)
-{
- GList *link;
-
- g_return_if_fail (E_IS_FILTER_RULE (rule));
- g_return_if_fail (E_IS_FILTER_PART (old_part));
- g_return_if_fail (E_IS_FILTER_PART (new_part));
-
- link = g_list_find (rule->parts, old_part);
- if (link != NULL)
- link->data = new_part;
- else
- rule->parts = g_list_append (rule->parts, new_part);
-
- e_filter_rule_emit_changed (rule);
-}
-
-void
-e_filter_rule_build_code (EFilterRule *rule,
- GString *out)
-{
- EFilterRuleClass *class;
-
- g_return_if_fail (E_IS_FILTER_RULE (rule));
- g_return_if_fail (out != NULL);
-
- class = E_FILTER_RULE_GET_CLASS (rule);
- g_return_if_fail (class->build_code != NULL);
-
- class->build_code (rule, out);
-}
-
-void
-e_filter_rule_emit_changed (EFilterRule *rule)
-{
- g_return_if_fail (E_IS_FILTER_RULE (rule));
-
- if (rule->priv->frozen == 0)
- g_signal_emit (rule, signals[CHANGED], 0);
-}
-
-EFilterRule *
-e_filter_rule_next_list (GList *list,
- EFilterRule *last,
- const gchar *source)
-{
- GList *link = list;
-
- if (last != NULL) {
- link = g_list_find (link, last);
- if (link == NULL)
- link = list;
- else
- link = g_list_next (link);
- }
-
- if (source != NULL) {
- while (link != NULL) {
- EFilterRule *rule = link->data;
-
- if (g_strcmp0 (rule->source, source) == 0)
- break;
-
- link = g_list_next (link);
- }
- }
-
- return (link != NULL) ? link->data : NULL;
-}
-
-EFilterRule *
-e_filter_rule_find_list (GList *list,
- const gchar *name,
- const gchar *source)
-{
- GList *link;
-
- g_return_val_if_fail (name != NULL, FALSE);
-
- for (link = list; link != NULL; link = g_list_next (link)) {
- EFilterRule *rule = link->data;
-
- if (strcmp (rule->name, name) == 0)
- if (source == NULL || (rule->source != NULL &&
- strcmp (rule->source, source) == 0))
- return rule;
- }
-
- return NULL;
-}
-
-#ifdef FOR_TRANSLATIONS_ONLY
-
-static gchar *list[] = {
- N_("Incoming"), N_("Outgoing")
-};
-#endif