aboutsummaryrefslogblamecommitdiffstats
path: root/filter/vfolder-rule.c
blob: 385a751f893e17d919d453e714295b986b36b8fe (plain) (tree)
1
2
3
4

                                                                           
  
                                  

















                                                                       
                   
 
                 


                              

                                

                                         
                        
                                  
 





                                         
                                   



















































                                                                            
                                           



























                                                          
                       




                                                                               

                                                          





                                                                

                                                           















                                                                  

                                                             











                                                                

                                                            
















                                                              




















                                                                                                           

                           


















                                                                   

                                                                    


































































                                                                                                   







                                                                     

                                                        




                                                       
                 









                                                                                   


                                                                         











                                                                      

                                                           





















                                                                            







                                           

                                                  





                                            
                   






















                                                                                                     



                                                                                   





                                                                                 























                                                                                                              

                                                                       
 




                                                                  
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
 *  Copyright (C) 2000 Ximian Inc.
 *
 *  Authors: Not Zed <notzed@lostzed.mmc.com.au>
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public License
 *  as published by the Free Software Foundation; either version 2 of
 *  the License, or (at your option) any later version.
 *
 *  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 Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public
 *  License along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <config.h>

#include <glib.h>
#include <gtk/gtkbox.h>
#include <gtk/gtklist.h>
#include <gtk/gtkoptionmenu.h>
#include <libgnome/gnome-defs.h>
#include <libgnome/gnome-i18n.h>
#include <libgnomeui/gnome-dialog.h>
#include <libgnomeui/gnome-dialog-util.h>
#include <glade/glade.h>
#include <gal/widgets/e-unicode.h>

#include "vfolder-context.h"
#include "vfolder-rule.h"
#include "shell/evolution-shell-client.h"

#define d(x) x

static gint validate(FilterRule *);
static xmlNodePtr xml_encode(FilterRule *);
static int xml_decode(FilterRule *, xmlNodePtr, struct _RuleContext *f);
/*static void build_code(FilterRule *, GString *out);*/
static GtkWidget *get_widget(FilterRule *fr, struct _RuleContext *f);

extern EvolutionShellClient *global_shell_client;

static void vfolder_rule_class_init (VfolderRuleClass *class);
static void vfolder_rule_init   (VfolderRule *gspaper);
static void vfolder_rule_finalise   (GtkObject *obj);

#define _PRIVATE(x) (((VfolderRule *)(x))->priv)

struct _VfolderRulePrivate {
};

static FilterRuleClass *parent_class;

guint
vfolder_rule_get_type (void)
{
    static guint type = 0;
    
    if (!type) {
        GtkTypeInfo type_info = {
            "VfolderRule",
            sizeof(VfolderRule),
            sizeof(VfolderRuleClass),
            (GtkClassInitFunc)vfolder_rule_class_init,
            (GtkObjectInitFunc)vfolder_rule_init,
            (GtkArgSetFunc)NULL,
            (GtkArgGetFunc)NULL
        };
        
        type = gtk_type_unique(filter_rule_get_type (), &type_info);
    }
    
    return type;
}

static void
vfolder_rule_class_init (VfolderRuleClass *class)
{
    GtkObjectClass *object_class;
    FilterRuleClass *filter_rule = (FilterRuleClass *)class;
    
    object_class = (GtkObjectClass *)class;
    parent_class = gtk_type_class(filter_rule_get_type ());

    object_class->finalize = vfolder_rule_finalise;

    /* override methods */
    filter_rule->validate   = validate;
    filter_rule->xml_encode = xml_encode;
    filter_rule->xml_decode = xml_decode;
    /*filter_rule->build_code = build_code;*/
    filter_rule->get_widget = get_widget;
}

static void
vfolder_rule_init (VfolderRule *o)
{
    o->priv = g_malloc0(sizeof(*o->priv));
}

static void
vfolder_rule_finalise(GtkObject *obj)
{
    VfolderRule *o = (VfolderRule *)obj;
    o = o;
        ((GtkObjectClass *)(parent_class))->finalize(obj);
}

/**
 * vfolder_rule_new:
 *
 * Create a new VfolderRule object.
 * 
 * Return value: A new #VfolderRule object.
 **/
VfolderRule *
vfolder_rule_new (void)
{
    VfolderRule *o = (VfolderRule *)gtk_type_new(vfolder_rule_get_type ());
    return o;
}

void
vfolder_rule_add_source (VfolderRule *vr, const char *uri)
{
    g_assert(IS_VFOLDER_RULE(vr));

    vr->sources = g_list_append(vr->sources, g_strdup(uri));
}

const char *
vfolder_rule_find_source (VfolderRule *vr, const char *uri)
{
    GList *l;

    g_assert(IS_VFOLDER_RULE(vr));

    /* only does a simple string or address comparison, should
       probably do a decoded url comparison */
    l = vr->sources;
    while (l) {
        if (l->data == uri || !strcmp(l->data, uri))
            return l->data;
        l = g_list_next(l);
    }
    return NULL;
}

void
vfolder_rule_remove_source (VfolderRule *vr, const char *uri)
{
    char *found;

    g_assert(IS_VFOLDER_RULE(vr));

    found = (char *)vfolder_rule_find_source(vr, uri);
    if (found) {
        vr->sources = g_list_remove(vr->sources, found);
        g_free(found);
    }
}

const char *
vfolder_rule_next_source (VfolderRule *vr, const char *last)
{
    GList *node;

    if (last == NULL) {
        node = vr->sources;
    } else {
        node = g_list_find(vr->sources, (char *)last);
        if (node == NULL)
            node = vr->sources;
        else
            node = g_list_next(node);
    }
    if (node)
        return (const char *)node->data;
    return NULL;
}

static gint
validate (FilterRule *fr)
{
    /* We have to have at least one source set in the "specific" case.
       Do not translate this string! */
    if (fr && fr->source && !strcmp (fr->source, "specific") && VFOLDER_RULE (fr)->sources == NULL) {

        GtkWidget *gd;

        gd = gnome_ok_dialog (_("Oops.  You need to to specify at least one folder as a source."));
        gnome_dialog_run_and_close (GNOME_DIALOG (gd));

        return 0;
    }

    if (FILTER_RULE_CLASS (parent_class)->validate)
        return FILTER_RULE_CLASS (parent_class)->validate (fr);

    return 1;
}

static xmlNodePtr
xml_encode (FilterRule *fr)
{
    xmlNodePtr node, set, work;
    GList *l;
    VfolderRule *vr = (VfolderRule *)fr;

        node = ((FilterRuleClass *)(parent_class))->xml_encode(fr);
    g_assert(node != NULL);
    set = xmlNewNode(NULL, "sources");
    xmlAddChild(node, set);
    l = vr->sources;
    while (l) {
        work = xmlNewNode(NULL, "folder");
        xmlSetProp(work, "uri", l->data);
        xmlAddChild(set, work);
        l = g_list_next(l);
    }
    return node;
}

static int
xml_decode (FilterRule *fr, xmlNodePtr node, struct _RuleContext *f)
{
    xmlNodePtr set, work;
    int result;
    VfolderRule *vr = (VfolderRule *)fr;
    char *uri;
    
        result = ((FilterRuleClass *)(parent_class))->xml_decode(fr, node, f);
    if (result != 0)
        return result;

    set = node->childs;
    while (set) {
        if (!strcmp(set->name, "sources")) {
            work = set->childs;
            while (work) {
                if (!strcmp(work->name, "folder")) {
                    uri = xmlGetProp(work, "uri");
                    if (uri)
                        vr->sources = g_list_append(vr->sources, uri);
                }
                work = work->next;
            }
        }
        set = set->next;
    }
    return 0;
}

enum {
    BUTTON_ADD,
    BUTTON_REMOVE,
    BUTTON_LAST,
};

struct _source_data {
    RuleContext *f;
    VfolderRule *vr;
    const char *current;
    GtkList *list;
    GtkButton *buttons[BUTTON_LAST];
};

static void source_add(GtkWidget *widget, struct _source_data *data);
static void source_remove(GtkWidget *widget, struct _source_data *data);

static struct {
    char *name;
    GtkSignalFunc func;
} edit_buttons[] = {
    { "source_add", source_add },
    { "source_remove", source_remove },
};

static void
set_sensitive(struct _source_data *data)
{
    gtk_widget_set_sensitive((GtkWidget *)data->buttons[BUTTON_ADD], TRUE);
    gtk_widget_set_sensitive((GtkWidget *)data->buttons[BUTTON_REMOVE], data->current != NULL);
}

static void
select_source(GtkWidget *w, GtkWidget *child, struct _source_data *data)
{
    data->current = gtk_object_get_data((GtkObject *)child, "source");
    set_sensitive(data);
}

static void
select_source_with(GtkWidget *w, struct _source_data *data)
{
    char *source = gtk_object_get_data((GtkObject *)w, "source");

    filter_rule_set_source((FilterRule *)data->vr, source);
}

static void
source_add(GtkWidget *widget, struct _source_data *data)
{
    const char *allowed_types[] = { "mail", NULL };
    char *def, *uri;
    GtkListItem *item;
    GList *l;
    gchar *s;

    def = "";
    evolution_shell_client_user_select_folder (global_shell_client,
                           _("Select Folder"),
                           def, allowed_types, NULL, &uri);

    if (uri != NULL && uri[0] != '\0') {
        data->vr->sources = g_list_append(data->vr->sources, uri);

        l = NULL;
        s = e_utf8_to_gtk_string ((GtkWidget *) data->list, uri);
        item = (GtkListItem *)gtk_list_item_new_with_label (s);
        g_free (s);
        gtk_object_set_data((GtkObject *)item, "source", uri);
        gtk_widget_show((GtkWidget *)item);
        l = g_list_append(NULL, item);
        gtk_list_append_items(data->list, l);
        gtk_list_select_child(data->list, (GtkWidget *)item);
        data->current = uri;
    } else {
        g_free(uri);
    }
    set_sensitive(data);
}

static void
source_remove(GtkWidget *widget, struct _source_data *data)
{
    const char *source;
    int index = 0;
    GList *l;
    GtkListItem *item;

    source = NULL;
    while ((source = vfolder_rule_next_source(data->vr, source))) {
        if (data->current == source) {
            vfolder_rule_remove_source(data->vr, source);
            item = g_list_nth_data(data->list->children, index);
            l = g_list_append(NULL, item);
            gtk_list_remove_items(data->list, l);
            g_list_free(l);
            data->current = NULL;
            break;
        }
        index++;
    }
    set_sensitive(data);
}

/* DO NOT internationalise these strings */
const char *source_names[] = {
    "specific",
    "local",
    "remote_active",
    "local_remote_active"
};

static GtkWidget *
get_widget(FilterRule *fr, struct _RuleContext *f)
{
    GtkWidget *widget, *frame, *w;
    GladeXML *gui;
    const char *source;
    VfolderRule *vr = (VfolderRule *)fr;
    struct _source_data *data;
    int i, row;
    GList *l;

        widget = ((FilterRuleClass *)(parent_class))->get_widget(fr, f);

    data = g_malloc0(sizeof(*data));
    data->f = f;
    data->vr = vr;

    gui = glade_xml_new(FILTER_GLADEDIR "/filter.glade", "vfolder_source_frame");
        frame = glade_xml_get_widget (gui, "vfolder_source_frame");

    gtk_object_set_data_full((GtkObject *)frame, "data", data, g_free);

    for (i=0;i<BUTTON_LAST;i++) {
        data->buttons[i] = (GtkButton *)w = glade_xml_get_widget (gui, edit_buttons[i].name);
        gtk_signal_connect((GtkObject *)w, "clicked", edit_buttons[i].func, data);
    }

        w = glade_xml_get_widget (gui, "source_list");
    data->list = (GtkList *)w;
    l = NULL;
    source = NULL;
    while ((source = vfolder_rule_next_source(vr, source))) {
        GtkListItem *item;
        gchar *s = e_utf8_to_gtk_string ((GtkWidget *) data->list, source);
        item = (GtkListItem *)gtk_list_item_new_with_label (s);
        g_free (s);
        gtk_object_set_data((GtkObject *)item, "source", (void *)source);
        gtk_widget_show((GtkWidget *)item);
        l = g_list_append(l, item);
    }
    gtk_list_append_items(data->list, l);
    gtk_signal_connect((GtkObject *)w, "select_child", select_source, data);

        w = glade_xml_get_widget (gui, "source_option");
    l = GTK_MENU_SHELL (GTK_OPTION_MENU (w)->menu)->children;
    i = 0;
    row = 0;
    while (l) {
        GtkWidget *b = GTK_WIDGET (l->data);

        /* make sure that the glade is in sync with the source list! */
        if (i < sizeof (source_names) / sizeof (source_names[0])) {
            gtk_object_set_data (GTK_OBJECT (b), "source", (char *)source_names[i]);
            if (fr->source && strcmp(source_names[i], fr->source) == 0) {
                row = i;
            }
        } else {
            g_warning("Glade file " FILTER_GLADEDIR "/filter.glade out of sync with editor code");
        }
        gtk_signal_connect (GTK_OBJECT (b), "activate", select_source_with, data);
        
        i++;
        l = l->next;
    }

    gtk_option_menu_set_history(GTK_OPTION_MENU(w), row);
    if (fr->source == NULL)
        filter_rule_set_source (fr, (char *)source_names[row]);

    set_sensitive(data);

    gtk_box_pack_start(GTK_BOX(widget), frame, TRUE, TRUE, 3);
    return widget;
}