diff options
Diffstat (limited to 'mail')
-rw-r--r-- | mail/ChangeLog | 11 | ||||
-rw-r--r-- | mail/Makefile.am | 4 | ||||
-rw-r--r-- | mail/mail-types.h | 1 | ||||
-rw-r--r-- | mail/subscribe-control-factory.c | 189 | ||||
-rw-r--r-- | mail/subscribe-control-factory.h | 21 | ||||
-rw-r--r-- | mail/subscribe-control.c | 387 | ||||
-rw-r--r-- | mail/subscribe-control.h | 60 |
7 files changed, 673 insertions, 0 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog index b6870cefd4..0244838e78 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,14 @@ +2000-09-27 Chris Toshok <toshok@helixcode.com> + + * mail-types.h: add SubscribeControl typedef. + + * Makefile.am (evolution_mail_SOURCES): add the subscribe stuff. + + * subscribe-control-factory.h + * subscribe-control-factory.c + * subscribe-control.c: + * subscribe-control.h: Mostly mocked up subscribe ui. + 2000-09-27 Jeffrey Stedfast <fejj@helixcode.com> Note: We need a configuration option to specify whether to log filtering actions or not. diff --git a/mail/Makefile.am b/mail/Makefile.am index 83ae9cf4be..d2d44b3fdd 100644 --- a/mail/Makefile.am +++ b/mail/Makefile.am @@ -78,6 +78,10 @@ evolution_mail_SOURCES = \ message-thread.c \ message-thread.h \ session.c \ + subscribe-control.c \ + subscribe-control.h \ + subscribe-control-factory.c \ + subscribe-control-factory.h \ mail.h evolution_mail_LDADD = \ diff --git a/mail/mail-types.h b/mail/mail-types.h index c5b690563d..9f72b23800 100644 --- a/mail/mail-types.h +++ b/mail/mail-types.h @@ -29,6 +29,7 @@ extern "C" { typedef struct _FolderBrowser FolderBrowser; +typedef struct _SubscribeControl SubscribeControl; typedef struct _MessageList MessageList; typedef struct _MailDisplay MailDisplay; diff --git a/mail/subscribe-control-factory.c b/mail/subscribe-control-factory.c new file mode 100644 index 0000000000..c49b6471a8 --- /dev/null +++ b/mail/subscribe-control-factory.c @@ -0,0 +1,189 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * subscribe-control-factory.c: A Bonobo Control factory for Subscribe Controls + * + * Author: + * Chris Toshok (toshok@helixcode.com) + * + * (C) 2000 Helix Code, Inc. + */ + +#include <config.h> + +#include <gnome.h> +#include <bonobo/bonobo-main.h> +#include <bonobo/bonobo-object.h> +#include <bonobo/bonobo-generic-factory.h> +#include <bonobo/bonobo-control.h> +#include <bonobo/bonobo-ui-component.h> + +#include <gal/util/e-util.h> +#include <gal/widgets/e-gui-utils.h> + +#include "subscribe-control-factory.h" + +#include "subscribe-control.h" +#include "mail.h" +#include "shell/Evolution.h" +#include "mail-config.h" +#include "mail-ops.h" + +/* The Subscribe BonoboControls we have. */ +static GList *control_list = NULL; + +/* + * Add with 'subscribe_control' + */ +static BonoboUIVerb verbs [] = { + /* Edit Menu */ + BONOBO_UI_VERB ("EditSelectAll", subscribe_select_all), + BONOBO_UI_VERB ("EditUnSelectAll", subscribe_unselect_all), + + /* Folder Menu */ + BONOBO_UI_VERB ("SubscribeFolder", subscribe_folder), + BONOBO_UI_VERB ("UnsubscribeFolder", unsubscribe_folder), + + BONOBO_UI_VERB_END +}; + +static void +set_pixmap (Bonobo_UIContainer container, + const char *xml_path, + const char *icon) +{ + char *path; + GdkPixbuf *pixbuf; + + path = g_concat_dir_and_file (EVOLUTION_DATADIR "/images/evolution/buttons", icon); + + pixbuf = gdk_pixbuf_new_from_file (path); + g_return_if_fail (pixbuf != NULL); + + bonobo_ui_util_set_pixbuf (container, xml_path, pixbuf); + + gdk_pixbuf_unref (pixbuf); + + g_free (path); +} + +static void +update_pixmaps (Bonobo_UIContainer container) +{ + set_pixmap (container, "/Toolbar/SubscribeFolder", "fetch-mail.png"); + set_pixmap (container, "/Toolbar/UnsubscribeFolder", "compose-message.png"); +} + +static void +control_activate (BonoboControl *control, BonoboUIHandler *uih, + SubscribeControl *fb) +{ + GtkWidget *subscribe_control; + BonoboUIComponent *component; + Bonobo_UIContainer container; + + container = bonobo_control_get_remote_ui_handler (control); + bonobo_ui_handler_set_container (uih, container); + bonobo_object_release_unref (container, NULL); + + g_assert (container == bonobo_ui_compat_get_container (uih)); + g_return_if_fail (container != CORBA_OBJECT_NIL); + + subscribe_control = bonobo_control_get_widget (control); + + component = bonobo_ui_compat_get_component (uih); + bonobo_ui_component_add_verb_list_with_data ( + component, verbs, subscribe_control); + + bonobo_ui_container_freeze (container, NULL); + + bonobo_ui_util_set_ui ( + component, container, + EVOLUTION_DATADIR, "evolution-subscribe.xml", + "evolution-mail"); + + update_pixmaps (container); + + bonobo_ui_container_thaw (container, NULL); +} + +static void +control_deactivate (BonoboControl *control, + BonoboUIHandler *uih, + SubscribeControl *subscribe) +{ + g_warning ("In subscribe control_deactivate"); + bonobo_ui_component_rm ( + bonobo_ui_compat_get_component (uih), + bonobo_ui_compat_get_container (uih), "/", NULL); + + bonobo_ui_handler_unset_container (uih); +} + +static void +control_activate_cb (BonoboControl *control, + gboolean activate, + gpointer user_data) +{ + BonoboUIHandler *uih; + + uih = bonobo_control_get_ui_handler (control); + g_assert (uih); + + if (activate) + control_activate (control, uih, user_data); + else + control_deactivate (control, uih, user_data); +} + +static void +control_destroy_cb (BonoboControl *control, + gpointer user_data) +{ + GtkWidget *subscribe_control = user_data; + + control_list = g_list_remove (control_list, control); + + gtk_object_destroy (GTK_OBJECT (subscribe_control)); +} + +BonoboControl * +subscribe_control_factory_new_control (const char *uri, + const Evolution_Shell shell) +{ + BonoboControl *control; + GtkWidget *subscribe_control; + + subscribe_control = subscribe_control_new (shell); + if (subscribe_control == NULL) + return NULL; + + if (!subscribe_control_set_uri (SUBSCRIBE_CONTROL (subscribe_control), uri)) { + gtk_object_sink (GTK_OBJECT (subscribe_control)); + return NULL; + } + + gtk_widget_show (subscribe_control); + + control = bonobo_control_new (subscribe_control); + + if (control == NULL) { + gtk_object_destroy (GTK_OBJECT (subscribe_control)); + return NULL; + } + + gtk_signal_connect (GTK_OBJECT (control), "activate", + control_activate_cb, subscribe_control); + + gtk_signal_connect (GTK_OBJECT (control), "destroy", + control_destroy_cb, subscribe_control); + + control_list = g_list_prepend (control_list, control); + + return control; +} + +GList * +subscribe_control_factory_get_control_list (void) +{ + return control_list; +} diff --git a/mail/subscribe-control-factory.h b/mail/subscribe-control-factory.h new file mode 100644 index 0000000000..7c1eaa0b18 --- /dev/null +++ b/mail/subscribe-control-factory.h @@ -0,0 +1,21 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * subscribe-control-factory.h: A Bonobo Control factory for Subscribe Controls + * + * Author: + * Chris Toshok (toshok@helixcode.com) + * + * (C) 2000 Helix Code, Inc. + */ + +#ifndef _SUBSCRIBE_CONTROL_FACTORY_H +#define _SUBSCRIBE_CONTROL_FACTORY_H + +#include <bonobo.h> +#include "Evolution.h" + +BonoboControl *subscribe_control_factory_new_control (const char *uri, + const Evolution_Shell shell); +GList *subscribe_control_factory_get_control_list (void); + +#endif /* _SUBSCRIBE_CONTROL_FACTORY_H */ diff --git a/mail/subscribe-control.c b/mail/subscribe-control.c new file mode 100644 index 0000000000..6bc674261b --- /dev/null +++ b/mail/subscribe-control.c @@ -0,0 +1,387 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * subscribe-control.c: Subscribe control top level component + * + * Author: + * Chris Toshok (toshok@helixcode.com) + * + * (C) 2000 Helix Code, Inc. + */ +#include <config.h> +#include <gnome.h> +#include "subscribe-control.h" +#include "e-util/e-html-utils.h" +#include <gtkhtml/gtkhtml.h> +#include <gal/util/e-util.h> +#include <gal/e-table/e-cell-text.h> +#include <gal/e-table/e-cell-tree.h> +#include <gal/e-table/e-cell-toggle.h> +#include <gal/e-table/e-table-scrolled.h> +#include <gal/e-table/e-tree-simple.h> + +#include "art/mark.xpm" + +#define PARENT_TYPE (gtk_table_get_type ()) + +#define ETABLE_SPEC "<ETableSpecification> \ + <columns-shown> \ + <column> 1 </column> \ + <column> 0 </column> \ + <column> 2 </column> \ + </columns-shown> \ + <grouping></grouping> \ +</ETableSpecification>" + +enum { + COL_FOLDER_NAME, + COL_FOLDER_SUBSCRIBED, + COL_FOLDER_DESCRIPTION, + COL_LAST +}; + +/* + * Virtual Column list: + * 0 Folder Name + * 1 Subscribed + * 2 Description + */ +char *headers [COL_LAST] = { + "Folder", + "Subscribed", + "Description", +}; + +static GtkObjectClass *subscribe_control_parent_class; + +void +subscribe_select_all (BonoboUIHandler *uih, + void *user_data, const char *path) +{ +} + +void +subscribe_unselect_all (BonoboUIHandler *uih, + void *user_data, const char *path) +{ +} + +void +subscribe_folder (GtkWidget *widget, gpointer user_data) +{ +} + +void +unsubscribe_folder (GtkWidget *widget, gpointer user_data) +{ +} + +gboolean +subscribe_control_set_uri (SubscribeControl *subscribe_control, + const char *uri) +{ + printf ("set_uri (%s) called\n", uri); + return TRUE; +} + + +/* HTML Helpers */ +static void +html_size_req (GtkWidget *widget, GtkRequisition *requisition) +{ + if (GTK_LAYOUT (widget)->height > 90) + requisition->height = 90; + else + requisition->height = GTK_LAYOUT (widget)->height; +} + +/* Returns a GtkHTML which is already inside a GtkScrolledWindow. If + * @white is TRUE, the GtkScrolledWindow will be inside a GtkFrame. + */ +static GtkWidget * +html_new (gboolean white) +{ + GtkWidget *html, *scrolled, *frame; + GtkStyle *style; + + html = gtk_html_new (); + GTK_LAYOUT (html)->height = 0; + gtk_signal_connect (GTK_OBJECT (html), "size_request", + GTK_SIGNAL_FUNC (html_size_req), NULL); + gtk_html_set_editable (GTK_HTML (html), FALSE); + style = gtk_rc_get_style (html); + if (style) { + gtk_html_set_default_background_color (GTK_HTML (html), + white ? &style->white : + &style->bg[0]); + } + gtk_widget_set_sensitive (html, FALSE); + scrolled = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), + GTK_POLICY_NEVER, + GTK_POLICY_NEVER); + gtk_container_add (GTK_CONTAINER (scrolled), html); + + if (white) { + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), + GTK_SHADOW_ETCHED_IN); + gtk_container_add (GTK_CONTAINER (frame), scrolled); + gtk_widget_show_all (frame); + } else + gtk_widget_show_all (scrolled); + + return html; +} + +static void +put_html (GtkHTML *html, char *text) +{ + GtkHTMLStream *handle; + + text = e_text_to_html (text, (E_TEXT_TO_HTML_CONVERT_NL | + E_TEXT_TO_HTML_CONVERT_SPACES | + E_TEXT_TO_HTML_CONVERT_URLS)); + handle = gtk_html_begin (html); + gtk_html_write (html, handle, "<HTML><BODY>", 12); + gtk_html_write (html, handle, text, strlen (text)); + gtk_html_write (html, handle, "</BODY></HTML>", 14); + g_free (text); + gtk_html_end (html, handle, GTK_HTML_STREAM_OK); +} + + + +/* etable stuff for the subscribe ui */ + +static int +etable_col_count (ETableModel *etm, void *data) +{ + return COL_LAST; +} + +static void* +etable_duplicate_value (ETableModel *etm, int col, const void *val, void *data) +{ + return g_strdup (val); +} + +static void +etable_free_value (ETableModel *etm, int col, void *val, void *data) +{ + g_free (val); +} + +static void* +etable_init_value (ETableModel *etm, int col, void *data) +{ + return g_strdup (""); +} + +static gboolean +etable_value_is_empty (ETableModel *etm, int col, const void *val, void *data) +{ + return !(val && *(char *)val); +} + +static char* +etable_value_to_string (ETableModel *etm, int col, const void *val, void *data) +{ + return g_strdup(val); +} + +static GdkPixbuf* +etree_icon_at (ETreeModel *etree, ETreePath *path, void *model_data) +{ + return NULL; /* XXX no icons for now */ +} + +static void* +etree_value_at (ETreeModel *etree, ETreePath *path, int col, void *model_data) +{ + if (col == COL_FOLDER_NAME) + return "Folder Name"; + else if (col == COL_FOLDER_DESCRIPTION) + return "Folder Description"; + else /* COL_FOLDER_SUBSCRIBED */ + return 1; /* XXX */ +} + +static void +etree_set_value_at (ETreeModel *etree, ETreePath *path, int col, const void *val, void *model_data) +{ + /* nothing */ +} + +static gboolean +etree_is_editable (ETreeModel *etree, ETreePath *path, int col, void *model_data) +{ + return FALSE; +} + + + +#define EXAMPLE_DESCR "And the beast shall come forth surrounded by a roiling cloud of vengeance.\n" \ +" The house of the unbelievers shall be razed and they shall be scorched to the\n" \ +" earth. Their tags shall blink until the end of days. \n" \ +" from The Book of Mozilla, 12:10" + +static void +subscribe_control_gui_init (SubscribeControl *sc) +{ + int i; + ECell *cells[3]; + ETableHeader *e_table_header; + GdkPixbuf *toggles[2]; + + sc->description = html_new (TRUE); + put_html (GTK_HTML (sc->description), EXAMPLE_DESCR); + + gtk_table_attach ( + GTK_TABLE (sc), sc->description->parent->parent, + 0, 1, 0, 1, + GTK_FILL | GTK_EXPAND, + 0, + 0, 0); + + sc->model = e_tree_simple_new (etable_col_count, + etable_duplicate_value, + etable_free_value, + etable_init_value, + etable_value_is_empty, + etable_value_to_string, + etree_icon_at, + etree_value_at, + etree_set_value_at, + etree_is_editable, + sc); + + sc->root = e_tree_model_node_insert (sc->model, NULL, + 0, NULL); + + e_tree_model_root_node_set_visible (sc->model, FALSE); + + + for (i = 0; i < 100; i ++) + e_tree_model_node_insert (sc->model, sc->root, + 0, NULL); + + e_table_header = e_table_header_new (); + + toggles[0] = NULL; + toggles[1] = gdk_pixbuf_new_from_xpm_data ((const char **)mark_xpm); + + cells[2] = e_cell_text_new (E_TABLE_MODEL(sc->model), NULL, GTK_JUSTIFY_LEFT); + cells[1] = e_cell_toggle_new (0, 2, toggles); + cells[0] = e_cell_tree_new (E_TABLE_MODEL(sc->model), + NULL, NULL, + /*tree_expanded_pixbuf, tree_unexpanded_pixbuf,*/ + TRUE, cells[2]); + + for (i = 0; i < COL_LAST; i++) { + /* Create the column. */ + ETableCol *ecol; + + if (i == 1) + ecol = e_table_col_new_with_pixbuf (i, toggles[1], + 0, gdk_pixbuf_get_width (toggles[1]), + cells[i], g_str_compare, FALSE); + else + ecol = e_table_col_new (i, headers [i], + 80, 20, + cells[i], + g_str_compare, TRUE); + /* Add it to the header. */ + e_table_header_add_column (e_table_header, ecol, i); + } + + sc->table = e_table_scrolled_new (e_table_header, E_TABLE_MODEL(sc->model), ETABLE_SPEC); + + gtk_table_attach ( + GTK_TABLE (sc), sc->table, + 0, 1, 1, 3, + GTK_FILL | GTK_EXPAND, + GTK_FILL | GTK_EXPAND, + 0, 0); + + gtk_widget_show_all (GTK_WIDGET(sc)); +} + +static void +subscribe_control_destroy (GtkObject *object) +{ + SubscribeControl *subscribe_control; + CORBA_Environment ev; + + subscribe_control = SUBSCRIBE_CONTROL (object); + + CORBA_exception_init (&ev); + + if (subscribe_control->shell != CORBA_OBJECT_NIL) + CORBA_Object_release (subscribe_control->shell, &ev); + + CORBA_exception_free (&ev); + + subscribe_control_parent_class->destroy (object); +} + +static void +subscribe_control_class_init (GtkObjectClass *object_class) +{ + object_class->destroy = subscribe_control_destroy; + + subscribe_control_parent_class = gtk_type_class (PARENT_TYPE); +} + +static void +subscribe_control_init (GtkObject *object) +{ +} + +static void +subscribe_control_construct (GtkObject *object) +{ + SubscribeControl *sc = SUBSCRIBE_CONTROL (object); + + /* + * Setup parent class fields. + */ + GTK_TABLE (sc)->homogeneous = FALSE; + gtk_table_resize (GTK_TABLE (sc), 1, 2); + + /* + * Our instance data + */ + + subscribe_control_gui_init (sc); +} + +GtkWidget * +subscribe_control_new (const Evolution_Shell shell) +{ + static int serial = 0; + CORBA_Environment ev; + SubscribeControl *subscribe_control; + + CORBA_exception_init (&ev); + + subscribe_control = gtk_type_new (subscribe_control_get_type ()); + + subscribe_control_construct (GTK_OBJECT (subscribe_control)); + subscribe_control->uri = NULL; + subscribe_control->serial = serial++; + + subscribe_control->shell = CORBA_Object_duplicate (shell, &ev); + if (ev._major != CORBA_NO_EXCEPTION) { + subscribe_control->shell = CORBA_OBJECT_NIL; + gtk_widget_destroy (GTK_WIDGET (subscribe_control)); + CORBA_exception_free (&ev); + return NULL; + } + + CORBA_exception_free (&ev); + + return GTK_WIDGET (subscribe_control); +} + +E_MAKE_TYPE (subscribe_control, "SubscribeControl", SubscribeControl, subscribe_control_class_init, subscribe_control_init, PARENT_TYPE); + diff --git a/mail/subscribe-control.h b/mail/subscribe-control.h new file mode 100644 index 0000000000..5124f3a8b7 --- /dev/null +++ b/mail/subscribe-control.h @@ -0,0 +1,60 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + + +#ifndef _SUBSCRIBE_CONTROL_H_ +#define _SUBSCRIBE_CONTROL_H_ + +#include "mail-types.h" +#include <gtk/gtktable.h> +#include <gal/e-table/e-tree-model.h> +#include <bonobo/bonobo-ui-handler.h> +#include <bonobo/bonobo-property-bag.h> +#include "shell/Evolution.h" + + +#define SUBSCRIBE_CONTROL_TYPE (subscribe_control_get_type ()) +#define SUBSCRIBE_CONTROL(o) (GTK_CHECK_CAST ((o), SUBSCRIBE_CONTROL_TYPE, SubscribeControl)) +#define SUBSCRIBE_CONTROL_CLASS(k) (GTK_CHECK_CLASS_CAST((k), SUBSCRIBE_CONTROL_TYPE, SubscribeControlClass)) +#define IS_SUBSCRIBE_CONTROL(o) (GTK_CHECK_TYPE ((o), SUBSCRIBE_CONTROL_TYPE)) +#define IS_SUBSCRIBE_CONTROL_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), SUBSCRIBE_CONTROL_TYPE)) + +struct _SubscribeControl { + GtkTable parent; + + BonoboPropertyBag *properties; + + Evolution_Shell shell; + + /* This is a kludge for the toolbar problem. */ + int serial; + + /* + * The current URI being displayed by the SubscribeControl + */ + char *uri; + gboolean is_news; + + GtkWidget *description; + GtkWidget *table; + ETreeModel *model; + ETreePath *root; +}; + + +typedef struct { + GtkTableClass parent_class; +} SubscribeControlClass; + +GtkType subscribe_control_get_type (void); +GtkWidget *subscribe_control_new (const Evolution_Shell shell); + +gboolean subscribe_control_set_uri (SubscribeControl *subscribe_control, + const char *uri); + +/* menu/toolbar callbacks */ +void subscribe_select_all (BonoboUIHandler *uih, void *user_data, const char *path); +void subscribe_unselect_all (BonoboUIHandler *uih, void *user_data, const char *path); +void subscribe_folder (GtkWidget *widget, gpointer user_data); +void unsubscribe_folder (GtkWidget *widget, gpointer user_data); + +#endif /* _SUBSCRIBE_CONTROL_H_ */ |