aboutsummaryrefslogblamecommitdiffstats
path: root/filter/filter-arg-types.c
blob: 5d09b4817b18e7b81fc5f4042d84e78236ff998b (plain) (tree)





















                                                                       

                  

                                   

                             

































                                                                            
                                                                             
 





                                                        




                          
                                                













                                                      




                                                      
                                                 

                              


                         


                          
                                                                                     
 
                                       
                                       




                                                                    

                   
                                                             
         



                                                                                           

                            


                                                                             

                                             
                                                                           
                 

                                                           

                  





                                           







































                                                                                                     






















                                                                              
                                                               
                                                               
                                                                                 







































                                                                                  































                                                                            
                                                                               
 



                   
                                                          
 




                                     
                                                          


                            
                                                  
                              
                                                       
                 
                                    





                                       
                              

 
          
                                                  

                              


                         

                          
                                             
 
                                                                                             
 





                                                                     


                                 
                                                             
         



                                                                                           

                            

                                                                            
                                                                                
                                        
                                           

                                            
                                                     
                                            
                                                                      
                 

                                                      



                  



                                            































                                                                                                               





                                                           










                                                                                                     












                                                                         
                                               
 

                                         















                                                                       

                                                                 










                                                                                  








































                                                                                   




                                  


                                                                         
                                      
                                                 
















                                                                        
                                                                                   





                    
                                                                             
 





                                                        
















                                                      
          
                                                 
 
                                                       
                  
                           
 
                                                 
 


                         
                                                        

         

                                                                       
                                                                                            



                                                              
                                                                           







                                                                                


                                                   

 
           
                                        
 
                                                            


                                                                          

                            
                
 


                                                                             



                            

                                                                                 


                                   
                                                                                        
                              
                                                     
 
                                                            
 



                                                            

                                      

                                                    


                        
                              

                                   
                                                  



















                                                                                  
                              





                                              
                             



                                                                  





                                           
                                                            













                                                               
                                                   













                                                          
                                                           
                                   
                                                                 

                                           
                                                                                   









                                                                                                     
                                                            














                                                          
                                     
 





                                                                                     

                                                         






                                                                 

                                                                           




                                             




























                                                                                  
/*
 *  Copyright (C) 2000 Helix Code Inc.
 *
 *  Authors: Michael Zucchi <notzed@helixcode.com>
 *
 *  Implementations of the filter-arg types.
 *
 *  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 <gnome.h>

#include "evolution-shell-client.h"

#include "filter-arg-types.h"

/* ********************************************************************** */
/*                               String                                   */
/* ********************************************************************** */

/* Use for a superclass of any items which are simple strings */

static void filter_arg_string_class_init (FilterArgStringClass *class);
static void filter_arg_string_init       (FilterArgString      *gspaper);

static FilterArg *string_parent_class;

guint
filter_arg_string_get_type (void)
{
    static guint type = 0;
    
    if (!type) {
        GtkTypeInfo type_info = {
            "FilterArgString",
            sizeof (FilterArgString),
            sizeof (FilterArgStringClass),
            (GtkClassInitFunc) filter_arg_string_class_init,
            (GtkObjectInitFunc) filter_arg_string_init,
            (GtkArgSetFunc) NULL,
            (GtkArgGetFunc) NULL
        };
        
        type = gtk_type_unique (filter_arg_get_type (), &type_info);
    }
    
    return type;
}

static void
arg_string_write_html(FilterArg *argin, GtkHTML *html, GtkHTMLStream *stream)
{
    /* empty */
}

static void
arg_string_write_text(FilterArg *argin, GString *string)
{
    GList *l;
    char *a;

    l = argin->values;
    if (l == NULL) {
        g_string_append(string, "text");
    }
    while (l) {
        a = l->data;
        g_string_append(string, a);
        if (l->next) {
            g_string_append(string, ", ");
        }
        l = g_list_next(l);
    }
}

static void
arg_string_edit_values(FilterArg *arg)
{
    printf("edit string values!\n");
}

/* pop up a dialogue, asking for a new string value */
static int
arg_string_edit_value (FilterArg *arg, int index)
{
    GnomeDialog *dialogue;
    GtkWidget *hbox;
    GtkWidget *label;
    GtkWidget *entry;
    char *text = NULL;
    char *newtext;

    dialogue = (GnomeDialog *)gnome_dialog_new ("Edit value", "Ok", "Cancel", 0);

    hbox = gtk_hbox_new (FALSE, 0);
    label = gtk_label_new ("Text");
    gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
    entry = gtk_entry_new();
    gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
    if (index >= 0) {
        text = filter_arg_get_value (arg, index);
    }
    if (text) {
        gtk_entry_set_text (GTK_ENTRY (entry), text);
    }
    gtk_box_pack_start (GTK_BOX (dialogue->vbox), hbox, TRUE, TRUE, 0);
    gtk_widget_show_all (hbox);
    gtk_object_ref (GTK_OBJECT (entry));   /* so we can get the text back afterwards */
    if (gnome_dialog_run_and_close (dialogue) == 0) {
        GList *node;

        newtext = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
        gtk_object_unref (GTK_OBJECT (entry));
        if (index >= 0 && (node = g_list_find (arg->values, text))) {
            node->data = newtext;
        } else {
            arg->values = g_list_append (arg->values, newtext);
        }
        g_free (text);
        return g_list_index (arg->values, newtext);
    }
    return -1;
}

static xmlNodePtr
arg_string_values_get_xml(FilterArg *argin)
{
    xmlNodePtr value;
    GList *l;
    char *a;

    value = xmlNewNode(NULL, "optionvalue");
    xmlSetProp(value, "name", argin->name);

    l = argin->values;
    while (l) {
        xmlNodePtr cur;

        a = l->data;

        cur = xmlNewChild(value, NULL, "folder", NULL);
        if (a)
            xmlSetProp(cur, "folder", a);
        l = g_list_next(l);
    }

    return value;
}

static void
arg_string_values_add_xml(FilterArg *arg, xmlNodePtr node)
{
    xmlNodePtr n;

    n = node->childs;
    while (n) {
        if (!strcmp(n->name, "folder")) {
            filter_arg_string_add(arg, xmlGetProp(n, "folder"));
        } else {
            g_warning("Loading folders from xml, wrong node encountered: %s\n", n->name);
        }
        n = n->next;
    }
}

static char *
arg_string_get_value_as_string(FilterArg *argin, void *data)
{
    char *a = (char *)data;

    return a;
}

static void
arg_string_free_value(FilterArg *arg, void *a)
{
    g_free(a);
}

static void
filter_arg_string_class_init (FilterArgStringClass *class)
{
    GtkObjectClass *object_class;
    
    object_class = (GtkObjectClass *) class;
    if (string_parent_class == NULL)
        string_parent_class = gtk_type_class (gtk_object_get_type ());

    class->parent_class.write_html = arg_string_write_html;
    class->parent_class.write_text = arg_string_write_text;
    class->parent_class.edit_values = arg_string_edit_values;
    class->parent_class.edit_value = arg_string_edit_value;
    class->parent_class.free_value = arg_string_free_value;
    class->parent_class.get_value_as_string = arg_string_get_value_as_string;

    class->parent_class.values_get_xml = arg_string_values_get_xml;
    class->parent_class.values_add_xml = arg_string_values_add_xml;
}

static void
filter_arg_string_init (FilterArgString *arg)
{
    arg->arg.values = NULL;
}

/**
 * filter_arg_string_new:
 *
 * Create a new FilterArgString widget.
 * 
 * Return value: A new FilterArgString widget.
 **/
FilterArg *
filter_arg_string_new (char *name)
{
    FilterArg *a = FILTER_ARG ( gtk_type_new (filter_arg_string_get_type ()));
    a->name = g_strdup(name);
    return a;
}


void
filter_arg_string_add(FilterArg *arg, char *name)
{
    filter_arg_add(arg, g_strdup(name));
}

void
filter_arg_string_remove(FilterArg *arg, char *name)
{
    /* do it */
}


/* ********************************************************************** */
/*                               Address                                  */
/* ********************************************************************** */

static void filter_arg_address_class_init (FilterArgAddressClass *class);
static void filter_arg_address_init       (FilterArgAddress      *gspaper);

static FilterArg *parent_class;

guint
filter_arg_address_get_type (void)
{
    static guint type = 0;
    
    if (!type) {
        GtkTypeInfo type_info = {
            "FilterArgAddress",
            sizeof (FilterArgAddress),
            sizeof (FilterArgAddressClass),
            (GtkClassInitFunc) filter_arg_address_class_init,
            (GtkObjectInitFunc) filter_arg_address_init,
            (GtkArgSetFunc) NULL,
            (GtkArgGetFunc) NULL
        };
        
        type = gtk_type_unique (filter_arg_get_type (), &type_info);
    }
    
    return type;
}

static void
arg_address_write_html (FilterArg *argin, GtkHTML *html, GtkHTMLStream *stream)
{
    /* empty */
}

static void
arg_address_write_text (FilterArg *argin, GString *string)
{
    GList *l;
    struct filter_arg_address *a;

    l = argin->values;
    if (l == NULL) {
        g_string_append (string, "email address");
    }
    while (l) {
        a = l->data;
        g_string_append (string, a->name);
        if (l->next) {
            g_string_append (string, ", ");
        }
        l = g_list_next (l);
    }
}

static void
arg_address_edit_values(FilterArg *arg)
{
    printf ("edit it!\n");
}

static int
arg_address_edit_value (FilterArg *arg, int index)
{
    GnomeDialog *dialogue;
    GtkWidget *hbox;
    GtkWidget *label;
    GtkWidget *entry;
    char *text = NULL;
    char *newtext;
    struct filter_arg_address *ad = NULL;

    dialogue = (GnomeDialog *)gnome_dialog_new ("Edit Address value", "Ok", "Cancel", 0);

    hbox = gtk_hbox_new (FALSE, 0);
    label = gtk_label_new ("Address");
    gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
    entry = gtk_entry_new ();
    gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
    if (index >= 0 && (ad = filter_arg_get_value (arg, index))) {
        text = ad->email;
    }
    if (text) {
        gtk_entry_set_text (GTK_ENTRY (entry), text);
    }
    gtk_box_pack_start (GTK_BOX (dialogue->vbox), hbox, TRUE, TRUE, 0);
    gtk_widget_show_all (hbox);
    gtk_object_ref (GTK_OBJECT (entry));   /* so we can get the text back afterwards */
    if (gnome_dialog_run_and_close (dialogue) == 0) {
        GList *node;

        newtext = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
        gtk_object_unref (GTK_OBJECT (entry));
        if (index >= 0 && ad && (node = g_list_find(arg->values, ad))) {
            ad = node->data;
            g_free (ad->email);
            ad->email = newtext;
        } else {
            ad = g_malloc0 (sizeof(*ad));
            ad->email = newtext;
            arg->values = g_list_append (arg->values, ad);
        }
        g_free (text);
        return g_list_index (arg->values, ad);
    }
    return -1;
}

static xmlNodePtr
arg_address_values_get_xml(FilterArg *argin)
{
    xmlNodePtr value;
    GList *l;
    struct filter_arg_address *a;

    /* hmm, perhaps this overhead should be in FilterArg, and this function just returns the base node?? */
    value = xmlNewNode(NULL, "optionvalue");
    xmlSetProp(value, "name", argin->name);

    l = argin->values;
    while (l) {
        xmlNodePtr cur;

        a = l->data;

        cur = xmlNewChild(value, NULL, "address", NULL);
        if (a->name)
            xmlSetProp(cur, "name", a->name);
        if (a->email)
            xmlSetProp(cur, "email", a->email);
        l = g_list_next(l);
    }

    return value;
}

static void
arg_address_values_add_xml(FilterArg *arg, xmlNodePtr node)
{
    xmlNodePtr n;

    n = node->childs;
    while (n) {
        if (!strcmp(n->name, "address")) {
            char *nm, *e;
            nm = xmlGetProp(n, "name");
            e = xmlGetProp(n, "email");
            filter_arg_address_add(arg, nm, e);
            free(nm);
            free(e);
        } else {
            g_warning("Loading address from xml, wrong node encountered: %s\n", n->name);
        }
        n = n->next;
    }
}

/* the search string is just the raw email address */
static char *
arg_address_get_value_as_string(FilterArg *argin, void *data)
{
    struct filter_arg_address *a = (struct filter_arg_address *)data;

    if (a->email == NULL
        || a->email[0] == '\0') {
        if (a->name == NULL
            || a->name[0] == '\0')
            return "";
        return a->name;
    } else
        return a->email;
}

static void
arg_address_free_value(FilterArg *arg, void *v)
{
    struct filter_arg_address *a = v;

    g_free(a->name);
    g_free(a->email);
    g_free(a);
}

static void
filter_arg_address_class_init (FilterArgAddressClass *class)
{
    GtkObjectClass *object_class;

    object_class = (GtkObjectClass *) class;
    if (parent_class == NULL)
        parent_class = gtk_type_class (gtk_object_get_type ());

    class->parent_class.write_html = arg_address_write_html;
    class->parent_class.write_text = arg_address_write_text;
    class->parent_class.edit_values= arg_address_edit_values;
    class->parent_class.edit_value= arg_address_edit_value;
    class->parent_class.free_value = arg_address_free_value;

    class->parent_class.values_get_xml = arg_address_values_get_xml;
    class->parent_class.values_add_xml = arg_address_values_add_xml;

    class->parent_class.get_value_as_string = arg_address_get_value_as_string;
}

static void
filter_arg_address_init (FilterArgAddress *arg)
{
}

/**
 * filter_arg_address_new:
 *
 * Create a new FilterArgAddress widget.
 * 
 * Return value: A new FilterArgAddress widget.
 **/
FilterArg *
filter_arg_address_new (char *name)
{
    FilterArg *a = FILTER_ARG ( gtk_type_new (filter_arg_address_get_type ()));
    a->name = g_strdup(name);
    return a;
}

void
filter_arg_address_add(FilterArg *arg, char *name, char *email)
{
    struct filter_arg_address *a;

    a = g_malloc0(sizeof(*a));

    a->name = g_strdup(name);
    a->email = g_strdup(email);

    filter_arg_add(arg, a);
}

void
filter_arg_address_remove(FilterArg *arg, char *name, char *email)
{

}

/* ********************************************************************** */
/*                               Folder                                   */
/* ********************************************************************** */


#include <bonobo/bonobo-object.h>
#include <bonobo/bonobo-control.h>

#include "Evolution.h"

static void filter_arg_folder_class_init (FilterArgFolderClass *class);
static void filter_arg_folder_init       (FilterArgFolder      *gspaper);

static FilterArg *folder_parent_class;
extern EvolutionShellClient *global_shell_client;

guint
filter_arg_folder_get_type (void)
{
    static guint type = 0;
    
    if (!type) {
        GtkTypeInfo type_info = {
            "FilterArgFolder",
            sizeof (FilterArgFolder),
            sizeof (FilterArgFolderClass),
            (GtkClassInitFunc) filter_arg_folder_class_init,
            (GtkObjectInitFunc) filter_arg_folder_init,
            (GtkArgSetFunc) NULL,
            (GtkArgGetFunc) NULL
        };
        
        type = gtk_type_unique (filter_arg_string_get_type (), &type_info);
    }
    
    return type;
}

static void
arg_folder_write_html(FilterArg *argin, GtkHTML *html, GtkHTMLStream *stream)
{
    /* empty */
}

static void
arg_folder_write_text(FilterArg *argin, GString *string)
{
    GList *l;
    char *a;

    l = argin->values;
    if (l == NULL) {
        g_string_append(string, "folder");
    }
    while (l) {
        a = l->data;
        g_string_append(string, a);
        if (l->next) {
            g_string_append(string, ", ");
        }
        l = g_list_next(l);
    }
}

static int
arg_folder_edit_value (FilterArg *arg, int index)
{
    const char *allowed_types[] = { "mail", NULL };
    char *def;
    char *physical_uri;

    printf ("folder edit value %d\n", index);

    if (index < 0) {
        def = "";
    } else {
        def = filter_arg_get_value (arg, index);
    }

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

    if (physical_uri != NULL && physical_uri[0] != '\0') {
        GList *node;

        if (index >= 0 && (node = g_list_nth (arg->values, index)))
            node->data = physical_uri;
        else
            arg->values = g_list_append (arg->values, physical_uri);

        gtk_signal_emit_by_name (GTK_OBJECT (arg), "changed");
    } else {
        g_free (physical_uri);
    }

#warning "What do we really want to return here???"
    return 0;
}

static void
arg_folder_edit_values(FilterArg *argin)
{
    /*FilterArgFolder *arg = (FilterArgFolder *)argin;*/
    GList *l;
    char *a, *start, *ptr, *ptrend, *ptrgap;
    char outbuf[128], *outptr; /* FIXME: dont use a bounded buffer! */
    GtkWidget *dialogue;
    GtkWidget *text;
    guint i;

    dialogue = gnome_dialog_new ("Edit addresses", "Ok", "Cancel", NULL);
    text = gtk_text_new (NULL, NULL);
    gtk_object_ref (GTK_OBJECT (text));

    l = argin->values;
    while (l) {
        a = l->data;
        gtk_text_insert(GTK_TEXT (text), NULL, NULL, NULL, a, strlen(a));
        gtk_text_insert(GTK_TEXT (text), NULL, NULL, NULL, "\n", 1);
        l = g_list_next(l);
    }

    gtk_box_pack_start(GTK_BOX (GNOME_DIALOG(dialogue)->vbox), text, TRUE, TRUE, 2);
    gtk_widget_show(text);
    gtk_text_set_editable(GTK_TEXT (text), TRUE);

    gnome_dialog_run_and_close(GNOME_DIALOG (dialogue));

    for (i = 0; i < g_list_length (argin->values); i++)
        g_free (g_list_nth_data (argin->values, i));
    g_list_free (argin->values);
    
    argin->values = NULL;
    ptr = GTK_TEXT(text)->text.ch;
    ptrend = ptr + GTK_TEXT(text)->text_end;
    ptrgap = ptr + GTK_TEXT(text)->gap_position;

    start = ptr;
    outptr = outbuf;
    while (ptr < ptrend) {
        printf("%c", *ptr);
        if (*ptr == '\n') {
            int len = outptr - outbuf;
            char *new;

            printf("(len = %d)", len);

            if (len>0) {
                new = g_malloc(len+1);
                new[len]=0;
                memcpy(new, outbuf, len);
                printf("(appending '%s')", new);
                argin->values = g_list_append(argin->values, new);
            }
            outptr = outbuf;
        } else {
            *outptr++ = *ptr;
        }
        ptr++;
        if (ptr==ptrgap) {
            ptr += GTK_TEXT(text)->gap_size;
        }
    }
    if (outptr > outbuf) {
        int len = outptr-outbuf;
        char *new;

        printf("(lastlen = %d)", len);
        
        new = g_malloc(len+1);
        new[len] = 0;
        memcpy(new, start, len);
        argin->values = g_list_append(argin->values, new);
    }
    printf("\n");
}

static xmlNodePtr
arg_folder_values_get_xml(FilterArg *argin)
{
    xmlNodePtr value;
    /*FilterArgFolder *arg = (FilterArgFolder *)argin;*/
    GList *l;
    char *a;

    value = xmlNewNode(NULL, "optionvalue");
    xmlSetProp(value, "name", argin->name);

    l = argin->values;
    while (l) {
        xmlNodePtr cur;

        a = l->data;

        cur = xmlNewChild(value, NULL, "folder", NULL);
        if (a)
            xmlSetProp(cur, "name", a);
        l = g_list_next(l);
    }

    return value;
}

static void
arg_folder_values_add_xml(FilterArg *arg, xmlNodePtr node)
{
    xmlNodePtr n;

    n = node->childs;
    while (n) {
        if (!strcmp(n->name, "folder")) {
            char *name = xmlGetProp(n, "name");
            if (name) {
                filter_arg_folder_add(arg, name);
                free(name);
            } else
                g_warning("no xml prop 'name' on '%s'\n", n->name);
        } else {
            g_warning("Loading folders from xml, wrong node encountered: %s\n", n->name);
        }
        n = n->next;
    }
}

static char *
arg_folder_get_value_as_string(FilterArg *argin, void *data)
{
    /*FilterArgFolder *arg = (FilterArgFolder *)argin;*/
    char *a = (char *)data;

    return a;
}

static void
arg_folder_free_value(FilterArg *arg, void *a)
{
    g_free(a);
}

static void
filter_arg_folder_class_init (FilterArgFolderClass *class)
{
    GtkObjectClass *object_class;
    FilterArgClass *filter_class;

    object_class = (GtkObjectClass *) class;
    filter_class = (FilterArgClass *) class;
    if (folder_parent_class == NULL)
        folder_parent_class = gtk_type_class (filter_arg_string_get_type ());

    /* FIXME: only need to over-ride the edit values right? */
    filter_class->edit_value = arg_folder_edit_value;

    filter_class->write_html = arg_folder_write_html;
    filter_class->write_text = arg_folder_write_text;
    filter_class->edit_values = arg_folder_edit_values;
    filter_class->free_value = arg_folder_free_value;

    filter_class->values_get_xml = arg_folder_values_get_xml;
    filter_class->values_add_xml = arg_folder_values_add_xml;

    filter_class->get_value_as_string = arg_folder_get_value_as_string;
}

static void
filter_arg_folder_init (FilterArgFolder *arg)
{
}

/**
 * filter_arg_folder_new:
 *
 * Create a new FilterArgFolder widget.
 * 
 * Return value: A new FilterArgFolder widget.
 **/
FilterArg *
filter_arg_folder_new (char *name)
{
    FilterArg *a = FILTER_ARG ( gtk_type_new (filter_arg_folder_get_type ()));
    a->name = g_strdup(name);
    return a;
}


void
filter_arg_folder_add(FilterArg *arg, char *name)
{
    filter_arg_add(arg, g_strdup(name));
}

void
filter_arg_folder_remove(FilterArg *arg, char *name)
{
    /* do it */
}