diff options
Diffstat (limited to 'shell/e-folder-list.c')
-rw-r--r-- | shell/e-folder-list.c | 603 |
1 files changed, 603 insertions, 0 deletions
diff --git a/shell/e-folder-list.c b/shell/e-folder-list.c new file mode 100644 index 0000000000..582a513ca7 --- /dev/null +++ b/shell/e-folder-list.c @@ -0,0 +1,603 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * e-folder-list.c + * Copyright 2000, 2001, Ximian, Inc. + * + * Authors: + * Chris Lahey <clahey@ximian.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License, version 2, as published by the Free Software Foundation. + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <config.h> +#include <libgnomeui/gnome-canvas-rect-ellipse.h> +#include "e-folder-list.h" +#include <gal/e-table/e-table-memory-store.h> +#include <gal/widgets/e-gui-utils.h> +#include <gal/widgets/e-option-menu.h> +#include <libgnome/gnome-i18n.h> +#include <gnome-xml/parser.h> +#include <gnome-xml/xmlmemory.h> +#include <gal/util/e-xml-utils.h> +#include <glade/glade.h> + +static GtkVBoxClass *parent_class = NULL; +#define PARENT_TYPE (gtk_vbox_get_type ()) + +enum { + CHANGED, + OPTION_MENU_CHANGED, + LAST_SIGNAL +}; + +static guint signals [LAST_SIGNAL] = { 0, }; + +/* The arguments we take */ +enum { + ARG_0, + ARG_TITLE, + ARG_POSSIBLE_TYPES, +}; + +struct _EFolderListPrivate { + GladeXML *gui; + + ETableScrolled *scrolled_table; + char *title; + GtkFrame *frame; + ETableMemoryStore *model; + EvolutionShellClient *client; + EOptionMenu *option_menu; + + char **possible_types; +}; + +static void +e_folder_list_changed (EFolderList *efl) +{ + gtk_signal_emit (GTK_OBJECT (efl), signals[CHANGED]); +} + +static void +e_folder_list_destroy (GtkObject *object) +{ + EFolderList *efl = E_FOLDER_LIST(object); + + if (efl->priv->gui) + gtk_object_unref(GTK_OBJECT(efl->priv->gui)); + + if (GTK_OBJECT_CLASS (parent_class)->destroy) + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + +static void +set_frame_label (EFolderList *efl) +{ + GtkFrame *frame = efl->priv->frame; + char *title = efl->priv->title; + if (frame) { + if (title) { + gtk_frame_set_label (frame, title); + gtk_frame_set_shadow_type (frame, GTK_SHADOW_ETCHED_IN); + } else { + gtk_frame_set_label (frame, ""); + gtk_frame_set_shadow_type (frame, GTK_SHADOW_NONE); + } + } +} + +static void +e_folder_list_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + EFolderList *efl = E_FOLDER_LIST(object); + + switch (arg_id) { + case ARG_TITLE: + g_free (efl->priv->title); + efl->priv->title = g_strdup (GTK_VALUE_STRING (*arg)); + set_frame_label (efl); + break; + case ARG_POSSIBLE_TYPES: + g_strfreev (efl->priv->possible_types); + efl->priv->possible_types = e_strdupv (GTK_VALUE_POINTER (*arg)); + break; + default: + break; + } +} + +static void +e_folder_list_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + EFolderList *efl = E_FOLDER_LIST(object); + + switch (arg_id) { + case ARG_TITLE: + GTK_VALUE_STRING (*arg) = g_strdup (efl->priv->title); + break; + case ARG_POSSIBLE_TYPES: + GTK_VALUE_POINTER (*arg) = e_strdupv ((const gchar **) efl->priv->possible_types); + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static void +e_folder_list_class_init (EFolderListClass *klass) +{ + GtkObjectClass *object_class; + GtkVBoxClass *vbox_class; + + object_class = (GtkObjectClass*) klass; + vbox_class = (GtkVBoxClass *) klass; + + glade_gnome_init(); + + parent_class = gtk_type_class (PARENT_TYPE); + + object_class->set_arg = e_folder_list_set_arg; + object_class->get_arg = e_folder_list_get_arg; + object_class->destroy = e_folder_list_destroy; + + klass->changed = NULL; + klass->option_menu_changed = NULL; + + signals [OPTION_MENU_CHANGED] = + gtk_signal_new ("option_menu_changed", + GTK_RUN_LAST, + E_OBJECT_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (EFolderListClass, option_menu_changed), + gtk_marshal_NONE__INT, + GTK_TYPE_NONE, 1, GTK_TYPE_INT); + + signals [CHANGED] = + gtk_signal_new ("changed", + GTK_RUN_LAST, + E_OBJECT_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (EFolderListClass, changed), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + + E_OBJECT_CLASS_ADD_SIGNALS (object_class, signals, LAST_SIGNAL); + + gtk_object_add_arg_type ("EFolderList::title", GTK_TYPE_STRING, + GTK_ARG_READWRITE, ARG_TITLE); + gtk_object_add_arg_type ("EFolderList::possible_types", GTK_TYPE_POINTER, + GTK_ARG_READWRITE, ARG_POSSIBLE_TYPES); +} + +#define SPEC "<ETableSpecification cursor-mode=\"line\"" \ + " selection-mode=\"browse\"" \ + " no-headers=\"true\"" \ + ">" \ + " <ETableColumn model_col=\"0\"" \ + " expansion=\"1.0\"" \ + " cell=\"string\"" \ + " minimum_width=\"32\"" \ + " resizable=\"true\"" \ + " _title=\"blah\"" \ + " compare=\"string\"" \ + " search=\"string\"/>" \ + " <ETableState>" \ + " <column source=\"0\"/>" \ + " <grouping>" \ + " <leaf column=\"0\" ascending=\"true\"/>" \ + " </grouping>" \ + " </ETableState>" \ + "</ETableSpecification>" + + +static ETableMemoryStoreColumnInfo columns[] = { + E_TABLE_MEMORY_STORE_STRING, + E_TABLE_MEMORY_STORE_STRING, + E_TABLE_MEMORY_STORE_STRING, + E_TABLE_MEMORY_STORE_TERMINATOR +}; + +GtkWidget * +create_custom_optionmenu (char *name, char *string1, char *string2, int int1, int int2); + +GtkWidget * +create_custom_optionmenu (char *name, char *string1, char *string2, int int1, int int2) +{ + return e_option_menu_new (NULL); +} + +GtkWidget * +create_custom_folder_list (char *name, char *string1, char *string2, int int1, int int2); + +GtkWidget * +create_custom_folder_list (char *name, char *string1, char *string2, int int1, int int2) +{ + ETableModel *model; + GtkWidget *scrolled; + model = e_table_memory_store_new (columns); + scrolled = e_table_scrolled_new (model, NULL, SPEC, NULL); + gtk_object_set_data (GTK_OBJECT (scrolled), "table-model", model); + return scrolled; +} + +static void +add_clicked (GtkButton *button, EFolderList *efl) +{ + GNOME_Evolution_Folder *folder; + + evolution_shell_client_user_select_folder (efl->priv->client, + GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (efl))), + _("Add a Folder"), + NULL, + (const gchar **) efl->priv->possible_types, + &folder); + + if (folder != NULL) { + e_table_memory_store_insert (efl->priv->model, -1, NULL, folder->displayName, folder->evolutionUri, folder->physicalUri); + e_folder_list_changed (efl); + } +} + +static void +make_list (int model_row, gpointer closure) +{ + GList **list = closure; + *list = g_list_prepend (*list, GINT_TO_POINTER (model_row)); +} + +static void +remove_row (gpointer data, gpointer user_data) +{ + ETableMemoryStore *etms = user_data; + int row = GPOINTER_TO_INT (data); + + e_table_memory_store_remove (etms, row); +} + +static void +remove_clicked (GtkButton *button, EFolderList *efl) +{ + GList *list = NULL; + ETable *table; + + table = e_table_scrolled_get_table (efl->priv->scrolled_table); + + e_table_selected_row_foreach (table, make_list, &list); + + g_list_foreach (list, remove_row, efl->priv->model); + + g_list_free (list); + + e_folder_list_changed (efl); +} + +static void +edit_clicked (GtkButton *button, EFolderList *efl) +{ + ETable *table; + GNOME_Evolution_Folder *folder; + int cursor_row; + + table = e_table_scrolled_get_table (efl->priv->scrolled_table); + cursor_row = e_table_get_cursor_row (table); + + if (cursor_row != -1) { + char *initial = e_table_model_value_at (E_TABLE_MODEL (efl->priv->model), 1, cursor_row); + evolution_shell_client_user_select_folder (efl->priv->client, + GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (efl))), + _("Edit this Folder"), + initial, + (const gchar **) efl->priv->possible_types, + &folder); + + if (folder != NULL) { + e_table_memory_store_remove (efl->priv->model, cursor_row); + e_table_memory_store_insert (efl->priv->model, -1, NULL, folder->displayName, folder->evolutionUri, folder->physicalUri); + e_folder_list_changed (efl); + } + } +} + +static void +optionmenu_changed (EOptionMenu *option_menu, int value, EFolderList *efl) +{ + gtk_signal_emit (GTK_OBJECT (efl), signals[OPTION_MENU_CHANGED], value); +} + +static void +update_buttons (EFolderList *efl) +{ + int cursor_row; + int selection_count; + ETable *table; + + table = e_table_scrolled_get_table (efl->priv->scrolled_table); + cursor_row = e_table_get_cursor_row (table); + selection_count = e_table_selected_count (table); + + + e_glade_xml_set_sensitive (efl->priv->gui, "button-edit", cursor_row != -1); + e_glade_xml_set_sensitive (efl->priv->gui, "button-remove", selection_count >= 1); +} + +static void +cursor_changed (ESelectionModel *selection_model, int row, int col, EFolderList *efl) +{ + update_buttons (efl); +} + +static void +selection_changed (ESelectionModel *selection_model, EFolderList *efl) +{ + update_buttons (efl); +} + +static void +e_folder_list_init (EFolderList *efl) +{ + GladeXML *gui; + ESelectionModel *selection_model; + + efl->priv = g_new (EFolderListPrivate, 1); + + gui = glade_xml_new (EVOLUTION_GLADEDIR "/e-folder-list.glade", NULL); + efl->priv->gui = gui; + + efl->priv->title = NULL; + efl->priv->frame = GTK_FRAME (glade_xml_get_widget(gui, "frame-toplevel")); + if (efl->priv->frame == NULL) + return; + + gtk_widget_reparent(GTK_WIDGET (efl->priv->frame), + GTK_WIDGET (efl)); + + efl->priv->option_menu = E_OPTION_MENU(glade_xml_get_widget (gui, "custom-optionmenu")); + e_folder_list_set_option_menu_strings (efl, NULL); + efl->priv->scrolled_table = E_TABLE_SCROLLED(glade_xml_get_widget(gui, "custom-folder-list")); + efl->priv->model = E_TABLE_MEMORY_STORE (gtk_object_get_data (GTK_OBJECT (efl->priv->scrolled_table), "table-model")); + + e_glade_xml_connect_widget (gui, "button-add", "clicked", + GTK_SIGNAL_FUNC (add_clicked), efl); + e_glade_xml_connect_widget (gui, "button-remove", "clicked", + GTK_SIGNAL_FUNC (remove_clicked), efl); + e_glade_xml_connect_widget (gui, "button-edit", "clicked", + GTK_SIGNAL_FUNC (edit_clicked), efl); + e_glade_xml_connect_widget (gui, "custom-optionmenu", "changed", + GTK_SIGNAL_FUNC (optionmenu_changed), efl); + + selection_model = e_table_get_selection_model (e_table_scrolled_get_table (efl->priv->scrolled_table)); + + gtk_signal_connect (GTK_OBJECT (selection_model), "selection_changed", + GTK_SIGNAL_FUNC (selection_changed), efl); + gtk_signal_connect (GTK_OBJECT (selection_model), "cursor_changed", + GTK_SIGNAL_FUNC (cursor_changed), efl); + + efl->priv->possible_types = NULL; + set_frame_label (efl); +} + +EFolderListItem * +e_folder_list_parse_xml (char *xml) +{ + xmlDoc *doc; + xmlNode *root; + xmlNode *node; + int i; + EFolderListItem *items; + + if (xml == NULL || *xml == 0) { + items = g_new (EFolderListItem, 1); + items[0].uri = NULL; + items[0].physical_uri = NULL; + items[0].display_name = NULL; + return items; + } + + doc = xmlParseMemory (xml, strlen (xml)); + + root = xmlDocGetRootElement (doc); + + for (node = root->xmlChildrenNode, i = 0; node; node = node->next, i++) + /* Intentionally empty */; + + items = g_new (EFolderListItem, i + 1); + + for (node = root->xmlChildrenNode, i = 0; node; node = node->next, i++) { + items[i].uri = e_xml_get_string_prop_by_name_with_default (node, "uri", ""); + items[i].physical_uri = e_xml_get_string_prop_by_name_with_default (node, "physical-uri", ""); + items[i].display_name = e_xml_get_string_prop_by_name_with_default (node, "display-name", ""); + } + items[i].uri = NULL; + items[i].physical_uri = NULL; + items[i].display_name = NULL; + + xmlFreeDoc (doc); + + return items; +} + +char * +e_folder_list_create_xml (EFolderListItem *items) +{ + xmlDoc *doc; + xmlNode *root; + char *xml; + xmlChar *temp; + int length; + int i; + + doc = xmlNewDoc ("1.0"); + + root = xmlNewDocNode (doc, NULL, "EvolutionFolderList", NULL); + + xmlDocSetRootElement (doc, root); + + for (i = 0; items[i].uri; i++) { + xmlNode *node = xmlNewChild (root, NULL, "folder", NULL); + e_xml_set_string_prop_by_name (node, "uri", items[i].uri); + e_xml_set_string_prop_by_name (node, "physical-uri", items[i].physical_uri); + e_xml_set_string_prop_by_name (node, "display-name", items[i].display_name); + } + + xmlDocDumpMemory (doc, &temp, &length); + + xml = g_strdup (temp); + + xmlFree (temp); + xmlFreeDoc (doc); + + return xml; +} + +void +e_folder_list_free_items (EFolderListItem *items) +{ + int i; + for (i = 0; items[i].uri; i++) { + g_free (items[i].uri); + g_free (items[i].physical_uri); + g_free (items[i].display_name); + } + g_free (items); +} + +GtkType +e_folder_list_get_type (void) +{ + static GtkType folder_list_type = 0; + + if (!folder_list_type) + { + static const GtkTypeInfo folder_list_info = + { + "EFolderList", + sizeof (EFolderList), + sizeof (EFolderListClass), + (GtkClassInitFunc) e_folder_list_class_init, + (GtkObjectInitFunc) e_folder_list_init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + folder_list_type = gtk_type_unique (PARENT_TYPE, &folder_list_info); + } + + return folder_list_type; +} + +GtkWidget* +e_folder_list_new (EvolutionShellClient *client, char *xml) +{ + GtkWidget *widget = GTK_WIDGET (gtk_type_new (e_folder_list_get_type ())); + e_folder_list_construct (E_FOLDER_LIST (widget), client, xml); + return widget; +} + +GtkWidget* +e_folder_list_construct (EFolderList *efl, EvolutionShellClient *client, char *xml) +{ + efl->priv->client = client; + e_folder_list_set_xml (efl, xml); + return GTK_WIDGET (efl); +} + +void +e_folder_list_set_items (EFolderList *efl, EFolderListItem *items) +{ + int i; + e_table_memory_store_clear (efl->priv->model); + for (i = 0; items[i].uri; i++) { + e_table_memory_store_insert (efl->priv->model, -1, NULL, items[i].display_name, items[i].uri, items[i].physical_uri); + } +} + +EFolderListItem * +e_folder_list_get_items (EFolderList *efl) +{ + EFolderListItem *items; + int count; + int i; + + count = e_table_model_row_count (E_TABLE_MODEL (efl->priv->model)); + + items = g_new (EFolderListItem, count + 1); + + for (i = 0; i < count; i++) { + items[i].display_name = g_strdup (e_table_model_value_at (E_TABLE_MODEL (efl->priv->model), 0, i)); + items[i].uri = g_strdup (e_table_model_value_at (E_TABLE_MODEL (efl->priv->model), 1, i)); + items[i].physical_uri = g_strdup (e_table_model_value_at (E_TABLE_MODEL (efl->priv->model), 2, i)); + } + items[i].uri = NULL; + items[i].physical_uri = NULL; + + return items; +} + +void +e_folder_list_set_xml (EFolderList *efl, char *xml) +{ + EFolderListItem *items; + + items = e_folder_list_parse_xml (xml); + e_folder_list_set_items (efl, items); + e_folder_list_free_items (items); +} + +char * +e_folder_list_get_xml (EFolderList *efl) +{ + EFolderListItem *items; + char *xml; + + items = e_folder_list_get_items (efl); + xml = e_folder_list_create_xml (items); + e_folder_list_free_items (items); + + return xml; +} + +void +e_folder_list_set_option_menu_strings_from_array (EFolderList *efl, gchar **strings) +{ + e_option_menu_set_strings_from_array (efl->priv->option_menu, strings); + if (strings && *strings) + gtk_widget_show (GTK_WIDGET (efl->priv->option_menu)); + else + gtk_widget_hide (GTK_WIDGET (efl->priv->option_menu)); +} + +void +e_folder_list_set_option_menu_strings (EFolderList *efl, gchar *first_label, ...) +{ + char **array; + + GET_STRING_ARRAY_FROM_ELLIPSIS (array, first_label); + + e_folder_list_set_option_menu_strings_from_array (efl, array); + + g_free (array); +} + +int +e_folder_list_get_option_menu_value (EFolderList *efl) +{ + return e_option_menu_get_value (efl->priv->option_menu); +} + +void +e_folder_list_set_option_menu_value (EFolderList *efl, int value) +{ + gtk_option_menu_set_history (GTK_OPTION_MENU (efl->priv->option_menu), value); +} |