diff options
Diffstat (limited to 'mail')
123 files changed, 26414 insertions, 23218 deletions
diff --git a/mail/Makefile.am b/mail/Makefile.am index 2a567ec042..8039bfe52d 100644 --- a/mail/Makefile.am +++ b/mail/Makefile.am @@ -31,163 +31,166 @@ INCLUDES = \ -DPREFIX=\""$(prefix)"\" \ -DG_LOG_DOMAIN=\"evolution-mail\" -component_LTLIBRARIES = libevolution-mail.la - -# Mail.idl -MAIL_IDL = Evolution-Mail.idl -MAIL_IDL_GENERATED_H = \ - Evolution-Mail.h -MAIL_IDL_GENERATED_C = \ - Evolution-Mail-common.c \ - Evolution-Mail-skels.c \ - Evolution-Mail-stubs.c -MAIL_IDL_GENERATED = $(MAIL_IDL_GENERATED_C) $(MAIL_IDL_GENERATED_H) - -$(MAIL_IDL_GENERATED_H): $(MAIL_IDL) - $(ORBIT_IDL) -I $(top_srcdir) -I $(datadir)/idl $(IDL_INCLUDES) $^ -$(MAIL_IDL_GENERATED_C): $(MAIL_IDL_GENERATED_H) - -# IDL install - -idl_DATA = $(MAIL_IDL) - -# plugin mail api -mailinclude_HEADERS = \ - $(MAIL_IDL_GENERATED_H) \ - e-mail-attachment-bar.h \ - em-composer-utils.h \ - em-config.h \ - em-event.h \ - em-folder-browser.h \ - em-folder-tree-model.h \ - em-folder-tree.h \ - em-folder-utils.h \ - em-folder-view.h \ - em-format-hook.h \ - em-format-html-display.h \ - em-format-html-print.h \ - em-format-html.h \ - em-format-quote.h \ - em-format.h \ - em-html-stream.h \ - em-icon-stream.h \ - em-inline-filter.h \ - em-junk-hook.h \ - em-menu.h \ - em-message-browser.h \ - em-popup.h \ - em-stripsig-filter.h \ - em-sync-stream.h \ - em-utils.h \ - mail-autofilter.h \ - mail-component.h \ - mail-config.h \ - mail-mt.h \ - mail-ops.h \ - mail-session.h \ - mail-tools.h \ - message-list.h \ - mail-vfolder.h - -# libevolution-mail - -libevolution_mail_la_SOURCES = \ - $(MAIL_IDL_GENERATED) \ - $(mailinclude_HEADERS) \ - e-attachment-handler-mail.c \ - e-attachment-handler-mail.h \ - e-mail-attachment-bar.c \ - e-searching-tokenizer.c \ - e-searching-tokenizer.h \ - em-account-editor.c \ - em-account-editor.h \ - em-account-prefs.c \ - em-account-prefs.h \ - em-composer-prefs.c \ - em-composer-prefs.h \ - em-composer-utils.c \ - em-config.c \ - em-event.c \ - em-filter-context.c \ - em-filter-context.h \ - em-filter-editor.c \ - em-filter-editor.h \ - em-filter-folder-element.c \ - em-filter-folder-element.h \ - em-filter-rule.c \ - em-filter-rule.h \ - em-filter-source-element.c \ - em-filter-source-element.h \ - em-folder-browser.c \ - em-folder-properties.c \ - em-folder-properties.h \ - em-folder-selection-button.c \ - em-folder-selection-button.h \ - em-folder-selection.c \ - em-folder-selection.h \ - em-folder-selector.c \ - em-folder-selector.h \ - em-folder-tree-model.c \ - em-folder-tree.c \ - em-folder-utils.c \ - em-folder-view.c \ - em-format-hook.c \ - em-format-html-display.c \ - em-format-html-print.c \ - em-format-html.c \ - em-format-quote.c \ - em-format.c \ - em-html-stream.c \ - em-icon-stream.c \ - em-inline-filter.c \ - em-junk-hook.c \ - em-mailer-prefs.c \ - em-mailer-prefs.h \ - em-menu.c \ - em-message-browser.c \ - em-migrate.c \ - em-migrate.h \ - em-network-prefs.c \ - em-network-prefs.h \ - em-popup.c \ - em-search-context.c \ - em-search-context.h \ - em-stripsig-filter.c \ - em-subscribe-editor.c \ - em-subscribe-editor.h \ - em-sync-stream.c \ - em-utils.c \ - em-vfolder-context.c \ - em-vfolder-context.h \ - em-vfolder-editor.c \ - em-vfolder-editor.h \ - em-vfolder-rule.c \ - em-vfolder-rule.h \ - mail-autofilter.c \ - mail-component-factory.c \ - mail-component.c \ - mail-config-factory.c \ - mail-config-factory.h \ - mail-config.c \ - mail-crypto.c \ - mail-crypto.h \ - mail-folder-cache.c \ - mail-folder-cache.h \ - mail-mt.c \ - mail-ops.c \ - mail-send-recv.c \ - mail-send-recv.h \ - mail-session.c \ - mail-signature-editor.c \ - mail-signature-editor.h \ - mail-tools.c \ - mail-types.h \ - mail-vfolder.c \ - message-list.c \ - message-tag-editor.c \ - message-tag-editor.h \ - message-tag-followup.c \ - message-tag-followup.h +module_LTLIBRARIES = \ + libevolution-module-mail.la + +libevolution_module_mail_la_SOURCES = \ + e-attachment-handler-mail.c \ + e-attachment-handler-mail.h \ + e-mail-attachment-bar.c \ + e-mail-attachment-bar.h \ + e-mail-browser.c \ + e-mail-browser.h \ + e-mail-display.c \ + e-mail-display.h \ + e-mail-label-dialog.c \ + e-mail-label-dialog.h \ + e-mail-label-list-store.c \ + e-mail-label-list-store.h \ + e-mail-label-manager.c \ + e-mail-label-manager.h \ + e-mail-label-tree-view.c \ + e-mail-label-tree-view.h \ + e-mail-reader.c \ + e-mail-reader.h \ + e-mail-reader-utils.c \ + e-mail-reader-utils.h \ + e-mail-search-bar.c \ + e-mail-search-bar.h \ + e-mail-shell-module.c \ + e-mail-shell-module.h \ + e-mail-shell-module-migrate.c \ + e-mail-shell-module-migrate.h \ + e-mail-shell-module-settings.c \ + e-mail-shell-module-settings.h \ + e-mail-shell-content.c \ + e-mail-shell-content.h \ + e-mail-shell-sidebar.c \ + e-mail-shell-sidebar.h \ + e-mail-shell-view.c \ + e-mail-shell-view.h \ + e-mail-shell-view-actions.c \ + e-mail-shell-view-actions.h \ + e-mail-shell-view-private.c \ + e-mail-shell-view-private.h \ + e-searching-tokenizer.c \ + e-searching-tokenizer.h \ + em-account-editor.c \ + em-account-editor.h \ + em-account-prefs.c \ + em-account-prefs.h \ + em-composer-prefs.c \ + em-composer-prefs.h \ + em-composer-utils.c \ + em-composer-utils.h \ + em-config.c \ + em-config.h \ + em-event.c \ + em-event.h \ + em-filter-context.c \ + em-filter-context.h \ + em-filter-editor.c \ + em-filter-editor.h \ + em-filter-folder-element.c \ + em-filter-folder-element.h \ + em-filter-rule.c \ + em-filter-rule.h \ + em-filter-source-element.c \ + em-filter-source-element.h \ + em-folder-properties.c \ + em-folder-properties.h \ + em-folder-selection.c \ + em-folder-selection.h \ + em-folder-selector.c \ + em-folder-selector.h \ + em-folder-selection-button.c \ + em-folder-selection-button.h \ + em-folder-tree.c \ + em-folder-tree.h \ + em-folder-tree-model.c \ + em-folder-tree-model.h \ + em-folder-utils.c \ + em-folder-utils.h \ + em-format.c \ + em-format.h \ + em-format-hook.c \ + em-format-hook.h \ + em-format-html.c \ + em-format-html.h \ + em-format-html-display.c \ + em-format-html-display.h \ + em-format-html-print.c \ + em-format-html-print.h \ + em-format-quote.c \ + em-format-quote.h \ + em-html-stream.c \ + em-html-stream.h \ + em-icon-stream.c \ + em-icon-stream.h \ + em-inline-filter.c \ + em-inline-filter.h \ + em-junk-hook.c \ + em-junk-hook.h \ + em-mailer-prefs.c \ + em-mailer-prefs.h \ + em-menu.c \ + em-menu.h \ + em-network-prefs.c \ + em-network-prefs.h \ + em-popup.c \ + em-popup.h \ + em-search-context.c \ + em-search-context.h \ + em-stripsig-filter.c \ + em-stripsig-filter.h \ + em-subscribe-editor.c \ + em-subscribe-editor.h \ + em-sync-stream.c \ + em-sync-stream.h \ + em-utils.c \ + em-utils.h \ + em-vfolder-context.c \ + em-vfolder-context.h \ + em-vfolder-editor.c \ + em-vfolder-editor.h \ + em-vfolder-rule.c \ + em-vfolder-rule.h \ + mail-autofilter.c \ + mail-autofilter.h \ + mail-config.c \ + mail-config.h \ + mail-folder-cache.c \ + mail-folder-cache.h \ + mail-mt.c \ + mail-mt.h \ + mail-ops.c \ + mail-ops.h \ + mail-send-recv.c \ + mail-send-recv.h \ + mail-session.c \ + mail-session.h \ + mail-tools.c \ + mail-tools.h \ + mail-vfolder.c \ + mail-vfolder.h \ + message-list.c \ + message-list.h \ + message-tag-editor.c \ + message-tag-editor.h \ + message-tag-followup.c \ + message-tag-followup,h + +libevolution_module_mail_la_LIBADD = \ + $(top_builddir)/e-util/libeutil.la \ + $(top_builddir)/shell/libeshell.la \ + $(top_builddir)/composer/libcomposer.la \ + $(top_builddir)/widgets/table/libetable.la \ + $(top_builddir)/widgets/text/libetext.la \ + $(top_builddir)/widgets/misc/libemiscwidgets.la \ + $(top_builddir)/mail/importers/libevolution-mail-importers.la \ + $(top_builddir)/addressbook/gui/contact-editor/libecontacteditor.la \ + $(top_builddir)/addressbook/gui/contact-list-editor/libecontactlisteditor.la \ + $(SMIME_LIBS) if ENABLE_SMIME SMIME_LIBS = \ @@ -195,38 +198,20 @@ SMIME_LIBS = \ $(top_builddir)/smime/gui/libevolution-smime.la endif -libevolution_mail_la_LIBADD = \ - $(top_builddir)/e-util/libeutil.la \ - $(top_builddir)/shell/libeshell.la \ - $(top_builddir)/composer/libcomposer.la \ - $(top_builddir)/widgets/table/libetable.la \ - $(top_builddir)/widgets/text/libetext.la \ - $(top_builddir)/widgets/misc/libemiscwidgets.la \ - $(top_builddir)/widgets/misc/libefilterbar.la \ - $(top_builddir)/filter/libfilter.la \ - $(top_builddir)/widgets/menus/libmenus.la \ - $(top_builddir)/addressbook/util/libeabutil.la \ - $(top_builddir)/addressbook/gui/contact-editor/libecontacteditor.la \ - $(top_builddir)/addressbook/gui/contact-list-editor/libecontactlisteditor.la \ - $(top_builddir)/mail/importers/libevolution-mail-importers.la \ - $(SMIME_LIBS) \ - $(EVOLUTION_MAIL_LIBS) \ - $(GTKHTML_LIBS) \ - $(REGEX_LIBS) \ - $(THREADS_LIBS) - -libevolution_mail_la_LDFLAGS = \ - -avoid-version -module $(NO_UNDEFINED) - -libevolution_mail_la_DEPENDENCIES = em-filter-i18n.h - -# .server files +#libevolution_mail_la_LIBADD = \ +# $(top_builddir)/widgets/misc/libefilterbar.la \ +# $(top_builddir)/filter/libfilter.la \ +# $(top_builddir)/widgets/menus/libmenus.la \ +# $(top_builddir)/addressbook/util/libeabutil.la \ +# $(EVOLUTION_MAIL_LIBS) \ +# $(GTKHTML_LIBS) \ +# $(REGEX_LIBS) \ +# $(THREADS_LIBS) -server_in_files = GNOME_Evolution_Mail.server.in.in -server_DATA = $(server_in_files:.server.in.in=.server) +#libevolution_mail_la_LDFLAGS = \ +# -avoid-version -module $(NO_UNDEFINED) -@EVO_SERVER_RULE@ -@INTLTOOL_SERVER_RULE@ +#libevolution_mail_la_DEPENDENCIES = em-filter-i18n.h # Misc data to install filterdir = $(privdatadir) @@ -250,7 +235,6 @@ etspec_DATA = message-list.etspec EXTRA_DIST = \ ChangeLog.pre-1-4 \ README.async \ - $(MAIL_IDL) \ mail.error.xml \ $(glade_DATA) \ $(schema_in_files) \ @@ -306,7 +290,7 @@ endif dist-hook: cd $(distdir); rm -f $(BUILT_SOURCES) -BUILT_SOURCES = $(MAIL_IDL_GENERATED) $(server_DATA) $(error_DATA) +BUILT_SOURCES = $(error_DATA) CLEANFILES = $(BUILT_SOURCES) diff --git a/mail/e-mail-attachment-bar.c b/mail/e-mail-attachment-bar.c index d3432ca9cd..731b52164a 100644 --- a/mail/e-mail-attachment-bar.c +++ b/mail/e-mail-attachment-bar.c @@ -98,6 +98,7 @@ mail_attachment_bar_update_status (EMailAttachmentBar *bar) { EAttachmentView *view; EAttachmentStore *store; + GtkActivatable *activatable; GtkExpander *expander; GtkAction *action; GtkLabel *label; @@ -106,10 +107,6 @@ mail_attachment_bar_update_status (EMailAttachmentBar *bar) gchar *display_size; gchar *markup; -#if GTK_CHECK_VERSION(2,16,0) - GtkActivatable *activatable; -#endif - view = E_ATTACHMENT_VIEW (bar); store = e_attachment_view_get_store (view); expander = GTK_EXPANDER (bar->priv->expander); @@ -126,20 +123,12 @@ mail_attachment_bar_update_status (EMailAttachmentBar *bar) gtk_label_set_markup (label, markup); g_free (markup); -#if GTK_CHECK_VERSION(2,16,0) activatable = GTK_ACTIVATABLE (bar->priv->save_all_button); action = gtk_activatable_get_related_action (activatable); -#else - action = e_attachment_view_get_action (view, "save-all"); -#endif gtk_action_set_visible (action, (num_attachments > 1)); -#if GTK_CHECK_VERSION(2,16,0) activatable = GTK_ACTIVATABLE (bar->priv->save_one_button); action = gtk_activatable_get_related_action (activatable); -#else - action = e_attachment_view_get_action (view, "save-one"); -#endif gtk_action_set_visible (action, (num_attachments == 1)); g_free (display_size); @@ -599,11 +588,7 @@ mail_attachment_bar_init (EMailAttachmentBar *bar) view = E_ATTACHMENT_VIEW (bar->priv->icon_view); action = e_attachment_view_get_action (view, "save-all"); gtk_button_set_image (GTK_BUTTON (widget), gtk_image_new ()); -#if GTK_CHECK_VERSION(2,16,0) gtk_activatable_set_related_action (GTK_ACTIVATABLE (widget), action); -#else - gtk_action_connect_proxy (action, widget); /* XXX Deprecated */ -#endif gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); bar->priv->save_all_button = g_object_ref (widget); gtk_widget_show (widget); @@ -613,11 +598,7 @@ mail_attachment_bar_init (EMailAttachmentBar *bar) view = E_ATTACHMENT_VIEW (bar->priv->icon_view); action = e_attachment_view_get_action (view, "save-one"); gtk_button_set_image (GTK_BUTTON (widget), gtk_image_new ()); -#if GTK_CHECK_VERSION(2,16,0) gtk_activatable_set_related_action (GTK_ACTIVATABLE (widget), action); -#else - gtk_action_connect_proxy (action, widget); /* XXX Deprecated */ -#endif gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); bar->priv->save_one_button = g_object_ref (widget); gtk_widget_show (widget); diff --git a/mail/e-mail-browser.c b/mail/e-mail-browser.c new file mode 100644 index 0000000000..69ccc54f44 --- /dev/null +++ b/mail/e-mail-browser.c @@ -0,0 +1,750 @@ +/* + * e-mail-browser.c + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-browser.h" + +#include <string.h> +#include <glib/gi18n.h> +#include <camel/camel-folder.h> + +#include "e-util/e-util.h" +#include "e-util/gconf-bridge.h" +#include "shell/e-shell.h" + +#include "mail/e-mail-reader.h" +#include "mail/e-mail-reader-utils.h" +#include "mail/e-mail-search-bar.h" +#include "mail/e-mail-shell-module.h" +#include "mail/em-folder-tree-model.h" +#include "mail/em-format-html-display.h" +#include "mail/message-list.h" + +#define E_MAIL_BROWSER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_BROWSER, EMailBrowserPrivate)) + +#define MAIL_BROWSER_GCONF_PREFIX "/apps/evolution/mail/mail_browser" + +struct _EMailBrowserPrivate { + GtkUIManager *ui_manager; + EShellModule *shell_module; + GtkActionGroup *action_group; + EMFormatHTMLDisplay *html_display; + + GtkWidget *main_menu; + GtkWidget *main_toolbar; + GtkWidget *message_list; + GtkWidget *search_bar; + GtkWidget *statusbar; + + guint show_deleted : 1; +}; + +enum { + PROP_0, + PROP_SHELL_MODULE, + PROP_SHOW_DELETED, + PROP_UI_MANAGER +}; + +static gpointer parent_class; + +/* This is too trivial to put in a file. + * It gets merged with the EMailReader UI. */ +static const gchar *ui = +"<ui>" +" <menubar name='main-menu'>" +" <menu action='file-menu'>" +" <placeholder name='file-actions'/>" +" <placeholder name='print-actions'/>" +" <separator/>" +" <menuitem action='close'/>" +" </menu>" +" </menubar>" +"</ui>"; + +static void +action_close_cb (GtkAction *action, + EMailBrowser *browser) +{ + e_mail_browser_close (browser); +} + +static GtkActionEntry mail_browser_entries[] = { + + { "close", + GTK_STOCK_CLOSE, + NULL, + NULL, + N_("Close this window"), + G_CALLBACK (action_close_cb) }, + + /*** Menus ***/ + + { "file-menu", + NULL, + N_("_File"), + NULL, + NULL, + NULL }, + + { "edit-menu", + NULL, + N_("_Edit"), + NULL, + NULL, + NULL }, + + { "view-menu", + NULL, + N_("_View"), + NULL, + NULL, + NULL } +}; + +static void +mail_browser_menu_item_select_cb (EMailBrowser *browser, + GtkWidget *menu_item) +{ + GtkAction *action; + GtkStatusbar *statusbar; + gchar *tooltip = NULL; + guint context_id; + gpointer data; + + action = g_object_get_data (G_OBJECT (menu_item), "action"); + g_return_if_fail (GTK_IS_ACTION (action)); + + data = g_object_get_data (G_OBJECT (menu_item), "context-id"); + context_id = GPOINTER_TO_UINT (data); + + g_object_get (action, "tooltip", &tooltip, NULL); + + if (tooltip == NULL) + return; + + statusbar = GTK_STATUSBAR (browser->priv->statusbar); + gtk_statusbar_push (statusbar, context_id, tooltip); +} + +static void +mail_browser_menu_item_deselect_cb (EMailBrowser *browser, + GtkWidget *menu_item) +{ + GtkStatusbar *statusbar; + guint context_id; + gpointer data; + + data = g_object_get_data (G_OBJECT (menu_item), "context-id"); + context_id = GPOINTER_TO_UINT (data); + + statusbar = GTK_STATUSBAR (browser->priv->statusbar); + gtk_statusbar_pop (statusbar, context_id); +} + +static void +mail_browser_connect_proxy_cb (EMailBrowser *browser, + GtkAction *action, + GtkWidget *proxy) +{ + GtkStatusbar *statusbar; + guint context_id; + + if (!GTK_IS_MENU_ITEM (proxy)) + return; + + statusbar = GTK_STATUSBAR (browser->priv->statusbar); + context_id = gtk_statusbar_get_context_id (statusbar, G_STRFUNC); + + g_object_set_data_full ( + G_OBJECT (proxy), + "action", g_object_ref (action), + (GDestroyNotify) g_object_unref); + + g_object_set_data ( + G_OBJECT (proxy), "context-id", + GUINT_TO_POINTER (context_id)); + + g_signal_connect_swapped ( + proxy, "select", + G_CALLBACK (mail_browser_menu_item_select_cb), browser); + + g_signal_connect_swapped ( + proxy, "deselect", + G_CALLBACK (mail_browser_menu_item_deselect_cb), browser); +} + +static void +mail_browser_message_selected_cb (EMailBrowser *browser, + const gchar *uid) +{ + EMFormatHTMLDisplay *html_display; + MessageList *message_list; + CamelMessageInfo *info; + EMailReader *reader; + + if (uid == NULL) + return; + + reader = E_MAIL_READER (browser); + html_display = e_mail_reader_get_html_display (reader); + message_list = e_mail_reader_get_message_list (reader); + info = camel_folder_get_message_info (message_list->folder, uid); + + if (info == NULL) + return; + + gtk_window_set_title ( + GTK_WINDOW (browser), + camel_message_info_subject (info)); + gtk_widget_grab_focus ( + GTK_WIDGET (((EMFormatHTML *) html_display)->html)); + + camel_folder_free_message_info (message_list->folder, info); +} + +static void +mail_browser_status_message_cb (EMailBrowser *browser, + const gchar *status_message) +{ + GtkStatusbar *statusbar; + guint context_id; + + statusbar = GTK_STATUSBAR (browser->priv->statusbar); + context_id = gtk_statusbar_get_context_id (statusbar, G_STRFUNC); + + /* Always pop first. This prevents messages from piling up. */ + gtk_statusbar_pop (statusbar, context_id); + + if (status_message != NULL && *status_message != '\0') + gtk_statusbar_push (statusbar, context_id, status_message); +} + +static void +mail_browser_set_shell_module (EMailBrowser *browser, + EShellModule *shell_module) +{ + g_return_if_fail (browser->priv->shell_module == NULL); + + browser->priv->shell_module = g_object_ref (shell_module); +} + +static void +mail_browser_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SHELL_MODULE: + mail_browser_set_shell_module ( + E_MAIL_BROWSER (object), + g_value_get_object (value)); + return; + + case PROP_SHOW_DELETED: + e_mail_browser_set_show_deleted ( + E_MAIL_BROWSER (object), + g_value_get_boolean (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_browser_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SHELL_MODULE: + g_value_set_object ( + value, e_mail_reader_get_shell_module ( + E_MAIL_READER (object))); + return; + + case PROP_SHOW_DELETED: + g_value_set_boolean ( + value, e_mail_browser_get_show_deleted ( + E_MAIL_BROWSER (object))); + return; + + case PROP_UI_MANAGER: + g_value_set_object ( + value, e_mail_browser_get_ui_manager ( + E_MAIL_BROWSER (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_browser_dispose (GObject *object) +{ + EMailBrowserPrivate *priv; + + priv = E_MAIL_BROWSER_GET_PRIVATE (object); + + if (priv->ui_manager != NULL) { + g_object_unref (priv->ui_manager); + priv->ui_manager = NULL; + } + + if (priv->shell_module != NULL) { + g_object_unref (priv->shell_module); + priv->shell_module = NULL; + } + + if (priv->action_group != NULL) { + g_object_unref (priv->action_group); + priv->action_group = NULL; + } + + if (priv->html_display != NULL) { + g_object_unref (priv->html_display); + priv->html_display = NULL; + } + + if (priv->main_menu != NULL) { + g_object_unref (priv->main_menu); + priv->main_menu = NULL; + } + + if (priv->main_toolbar != NULL) { + g_object_unref (priv->main_toolbar); + priv->main_toolbar = NULL; + } + + if (priv->message_list != NULL) { + g_object_unref (priv->message_list); + priv->message_list = NULL; + } + + if (priv->search_bar != NULL) { + g_object_unref (priv->search_bar); + priv->search_bar = NULL; + } + + if (priv->statusbar != NULL) { + g_object_unref (priv->statusbar); + priv->statusbar = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +mail_browser_constructed (GObject *object) +{ + EMFormatHTMLDisplay *html_display; + EMailBrowserPrivate *priv; + EMailReader *reader; + EShellModule *shell_module; + EShell *shell; + GConfBridge *bridge; + GtkAccelGroup *accel_group; + GtkActionGroup *action_group; + GtkUIManager *ui_manager; + GtkWidget *container; + GtkWidget *widget; + GtkHTML *html; + const gchar *domain; + const gchar *key; + guint merge_id; + + priv = E_MAIL_BROWSER_GET_PRIVATE (object); + + reader = E_MAIL_READER (object); + ui_manager = priv->ui_manager; + domain = GETTEXT_PACKAGE; + + html_display = e_mail_reader_get_html_display (reader); + shell_module = e_mail_reader_get_shell_module (reader); + + shell = e_shell_module_get_shell (shell_module); + e_shell_watch_window (shell, GTK_WINDOW (object)); + + html = EM_FORMAT_HTML (html_display)->html; + + /* The message list is a widget, but it is not shown in the browser. + * Unfortunately, the widget is inseparable from its model, and the + * model is all we need. */ + priv->message_list = message_list_new (shell_module); + g_object_ref_sink (priv->message_list); + + g_signal_connect_swapped ( + priv->message_list, "message-selected", + G_CALLBACK (mail_browser_message_selected_cb), object); + + g_signal_connect_swapped ( + html, "status-message", + G_CALLBACK (mail_browser_status_message_cb), object); + + e_mail_reader_init (reader); + + action_group = priv->action_group; + gtk_action_group_set_translation_domain (action_group, domain); + gtk_action_group_add_actions ( + action_group, mail_browser_entries, + G_N_ELEMENTS (mail_browser_entries), object); + gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); + + e_load_ui_definition (ui_manager, E_MAIL_READER_UI_DEFINITION); + gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, NULL); + + merge_id = gtk_ui_manager_new_merge_id (ui_manager); + e_mail_reader_create_charset_menu (reader, ui_manager, merge_id); + + accel_group = gtk_ui_manager_get_accel_group (ui_manager); + gtk_window_add_accel_group (GTK_WINDOW (object), accel_group); + + g_signal_connect_swapped ( + ui_manager, "connect-proxy", + G_CALLBACK (mail_browser_connect_proxy_cb), object); + + /* Construct window widgets. */ + + widget = gtk_vbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (object), widget); + gtk_widget_show (widget); + + container = widget; + + /* Create the status bar before connecting proxy widgets. */ + widget = gtk_statusbar_new (); + gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 0); + priv->statusbar = g_object_ref (widget); + gtk_widget_show (widget); + + widget = e_mail_search_bar_new (EM_FORMAT_HTML (html_display)->html); + gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 0); + priv->search_bar = g_object_ref (widget); + gtk_widget_hide (widget); + + g_signal_connect_swapped ( + widget, "changed", + G_CALLBACK (em_format_redraw), html_display); + + widget = gtk_ui_manager_get_widget (ui_manager, "/main-menu"); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + priv->main_menu = g_object_ref (widget); + gtk_widget_show (widget); + + widget = gtk_ui_manager_get_widget (ui_manager, "/main-toolbar"); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + priv->main_toolbar = g_object_ref (widget); + gtk_widget_show (widget); + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + gtk_widget_show (widget); + + container = widget; + + widget = GTK_WIDGET (EM_FORMAT_HTML (html_display)->html); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); + + /* Bind GObject properties to GConf keys. */ + + bridge = gconf_bridge_get (); + + object = G_OBJECT (reader); + key = "/apps/evolution/mail/display/show_deleted"; + gconf_bridge_bind_property (bridge, key, object, "show-deleted"); +} + +static gboolean +mail_browser_key_press_event (GtkWidget *widget, + GdkEventKey *event) +{ + if (event->keyval == GDK_Escape) { + e_mail_browser_close (E_MAIL_BROWSER (widget)); + return TRUE; + } + + /* Chain up to parent's key_press_event() method. */ + return GTK_WIDGET_CLASS (parent_class)-> + key_press_event (widget, event); +} + +static GtkActionGroup * +mail_browser_get_action_group (EMailReader *reader) +{ + EMailBrowserPrivate *priv; + + priv = E_MAIL_BROWSER_GET_PRIVATE (reader); + + return priv->action_group; +} + +static gboolean +mail_browser_get_hide_deleted (EMailReader *reader) +{ + EMailBrowser *browser; + + browser = E_MAIL_BROWSER (reader); + + return !e_mail_browser_get_show_deleted (browser); +} + +static EMFormatHTMLDisplay * +mail_browser_get_html_display (EMailReader *reader) +{ + EMailBrowserPrivate *priv; + + priv = E_MAIL_BROWSER_GET_PRIVATE (reader); + + return priv->html_display; +} + +static MessageList * +mail_browser_get_message_list (EMailReader *reader) +{ + EMailBrowserPrivate *priv; + + priv = E_MAIL_BROWSER_GET_PRIVATE (reader); + + return MESSAGE_LIST (priv->message_list); +} + +static EShellModule * +mail_browser_get_shell_module (EMailReader *reader) +{ + EMailBrowserPrivate *priv; + + priv = E_MAIL_BROWSER_GET_PRIVATE (reader); + + return priv->shell_module; +} + +static GtkWindow * +mail_browser_get_window (EMailReader *reader) +{ + return GTK_WINDOW (reader); +} + +static void +mail_browser_set_message (EMailReader *reader, + const gchar *uid, + gboolean mark_read) +{ + EMailReaderIface *iface; + MessageList *message_list; + CamelMessageInfo *info; + CamelFolder *folder; + + /* Chain up to parent's set_message() method. */ + iface = g_type_default_interface_peek (E_TYPE_MAIL_READER); + iface->set_message (reader, uid, mark_read); + + if (uid == NULL) { + e_mail_browser_close (E_MAIL_BROWSER (reader)); + return; + } + + message_list = e_mail_reader_get_message_list (reader); + + folder = message_list->folder; + info = camel_folder_get_message_info (folder, uid); + + if (info != NULL) { + gtk_window_set_title ( + GTK_WINDOW (reader), + camel_message_info_subject (info)); + camel_folder_free_message_info (folder, info); + } + + if (mark_read) + e_mail_reader_mark_as_read (reader, uid); +} + +static void +mail_browser_show_search_bar (EMailReader *reader) +{ + EMailBrowserPrivate *priv; + + priv = E_MAIL_BROWSER_GET_PRIVATE (reader); + + gtk_widget_show (priv->search_bar); +} + +static void +mail_browser_class_init (EMailBrowserClass *class) +{ + GObjectClass *object_class; + GtkWidgetClass *widget_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMailBrowserPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_browser_set_property; + object_class->get_property = mail_browser_get_property; + object_class->dispose = mail_browser_dispose; + object_class->constructed = mail_browser_constructed; + + widget_class = GTK_WIDGET_CLASS (class); + widget_class->key_press_event = mail_browser_key_press_event; + + g_object_class_install_property ( + object_class, + PROP_SHELL_MODULE, + g_param_spec_object ( + "shell-module", + _("Shell Module"), + _("The mail shell module"), + E_TYPE_SHELL_MODULE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property ( + object_class, + PROP_SHOW_DELETED, + g_param_spec_boolean ( + "show-deleted", + _("Show Deleted"), + _("Show deleted messages"), + FALSE, + G_PARAM_READWRITE)); +} + +static void +mail_browser_iface_init (EMailReaderIface *iface) +{ + iface->get_action_group = mail_browser_get_action_group; + iface->get_hide_deleted = mail_browser_get_hide_deleted; + iface->get_html_display = mail_browser_get_html_display; + iface->get_message_list = mail_browser_get_message_list; + iface->get_shell_module = mail_browser_get_shell_module; + iface->get_window = mail_browser_get_window; + iface->set_message = mail_browser_set_message; + iface->show_search_bar = mail_browser_show_search_bar; +} + +static void +mail_browser_init (EMailBrowser *browser) +{ + GConfBridge *bridge; + const gchar *prefix; + + browser->priv = E_MAIL_BROWSER_GET_PRIVATE (browser); + + browser->priv->ui_manager = gtk_ui_manager_new (); + browser->priv->action_group = gtk_action_group_new ("mail-browser"); + browser->priv->html_display = em_format_html_display_new (); + + bridge = gconf_bridge_get (); + prefix = "/apps/evolution/mail/mail_browser"; + gconf_bridge_bind_window_size (bridge, prefix, GTK_WINDOW (browser)); + + gtk_window_set_title (GTK_WINDOW (browser), _("Evolution")); +} + +GType +e_mail_browser_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMailBrowserClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) mail_browser_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMailBrowser), + 0, /* n_preallocs */ + (GInstanceInitFunc) mail_browser_init, + NULL /* value_table */ + }; + + static const GInterfaceInfo iface_info = { + (GInterfaceInitFunc) mail_browser_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL /* interface_data */ + }; + + type = g_type_register_static ( + GTK_TYPE_WINDOW, "EMailBrowser", &type_info, 0); + + g_type_add_interface_static ( + type, E_TYPE_MAIL_READER, &iface_info); + } + + return type; +} + +GtkWidget * +e_mail_browser_new (EShellModule *shell_module) +{ + g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), NULL); + + return g_object_new ( + E_TYPE_MAIL_BROWSER, + "shell-module", shell_module, NULL); +} + +void +e_mail_browser_close (EMailBrowser *browser) +{ + g_return_if_fail (E_IS_MAIL_BROWSER (browser)); + + gtk_widget_destroy (GTK_WIDGET (browser)); +} + +gboolean +e_mail_browser_get_show_deleted (EMailBrowser *browser) +{ + g_return_val_if_fail (E_IS_MAIL_BROWSER (browser), FALSE); + + return browser->priv->show_deleted; +} + +void +e_mail_browser_set_show_deleted (EMailBrowser *browser, + gboolean show_deleted) +{ + g_return_if_fail (E_IS_MAIL_BROWSER (browser)); + + browser->priv->show_deleted = show_deleted; + + g_object_notify (G_OBJECT (browser), "show-deleted"); +} + +GtkUIManager * +e_mail_browser_get_ui_manager (EMailBrowser *browser) +{ + g_return_val_if_fail (E_IS_MAIL_BROWSER (browser), NULL); + + return browser->priv->ui_manager; +} diff --git a/mail/e-mail-browser.h b/mail/e-mail-browser.h new file mode 100644 index 0000000000..bcc8870478 --- /dev/null +++ b/mail/e-mail-browser.h @@ -0,0 +1,72 @@ +/* + * e-mail-browser.h + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MAIL_BROWSER_H +#define E_MAIL_BROWSER_H + +#include <gtk/gtk.h> +#include <shell/e-shell-module.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_BROWSER \ + (e_mail_browser_get_type ()) +#define E_MAIL_BROWSER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_BROWSER, EMailBrowser)) +#define E_MAIL_BROWSER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_BROWSER, EMailBrowserClass)) +#define E_IS_MAIL_BROWSER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_BROWSER)) +#define E_IS_MAIL_BROWSER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_BROWSER)) +#define E_MAIL_BROWSER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_BROWSER, EMailBrowserClass)) + +G_BEGIN_DECLS + +typedef struct _EMailBrowser EMailBrowser; +typedef struct _EMailBrowserClass EMailBrowserClass; +typedef struct _EMailBrowserPrivate EMailBrowserPrivate; + +struct _EMailBrowser { + GtkWindow parent; + EMailBrowserPrivate *priv; +}; + +struct _EMailBrowserClass { + GtkWindowClass parent_class; +}; + +GType e_mail_browser_get_type (void); +GtkWidget * e_mail_browser_new (EShellModule *shell_module); +void e_mail_browser_close (EMailBrowser *browser); +gboolean e_mail_browser_get_show_deleted (EMailBrowser *browser); +void e_mail_browser_set_show_deleted (EMailBrowser *browser, + gboolean show_deleted); +GtkUIManager * e_mail_browser_get_ui_manager (EMailBrowser *browser); + +G_END_DECLS + +#endif /* E_MAIL_BROWSER_H */ diff --git a/mail/e-mail-display.c b/mail/e-mail-display.c new file mode 100644 index 0000000000..f649393f40 --- /dev/null +++ b/mail/e-mail-display.c @@ -0,0 +1,627 @@ +/* + * e-mail-display.c + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-display.h" + +#include <string.h> +#include <glib/gi18n.h> + +#include "e-util/e-util.h" + +#define E_MAIL_DISPLAY_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_DISPLAY, EMailDisplayPrivate)) + +struct _EMailDisplayPrivate { + EMFormatHTML *formatter; +}; + +enum { + PROP_0, + PROP_ANIMATE, + PROP_CARET_MODE, + PROP_FORMATTER +}; + +enum { + POPUP_EVENT, + STATUS_MESSAGE, + LAST_SIGNAL +}; + +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; + +static gboolean +mail_display_emit_popup_event (EMailDisplay *display, + GdkEventButton *event, + const gchar *uri, + EMFormatPURI *puri) +{ + CamelMimePart *mime_part; + gboolean stop_handlers = FALSE; + + mime_part = (puri != NULL) ? puri->part : NULL; + + g_signal_emit ( + display, signals[POPUP_EVENT], 0, + event, uri, mime_part, &stop_handlers); + + return stop_handlers; +} + +static void +mail_display_emit_status_message (EMailDisplay *display, + const gchar *status_message) +{ + g_signal_emit (display, signals[STATUS_MESSAGE], 0, status_message); +} + +static void +mail_display_get_uri_puri (EMailDisplay *display, + GdkEventButton *event, + gchar **uri, + EMFormatPURI **puri) +{ + EMFormat *formatter; + GtkHTML *html; + gchar *text_uri; + gchar *image_uri; + gboolean is_cid; + + html = GTK_HTML (display); + formatter = EM_FORMAT (display->priv->formatter); + + if (event != NULL) { + text_uri = gtk_html_get_url_at (html, event->x, event->y); + image_uri = gtk_html_get_image_src_at (html, event->x, event->y); + } else { + text_uri = gtk_html_get_cursor_url (html); + image_uri = gtk_html_get_cursor_image_src (html); + } + + is_cid = (image_uri != NULL) && + (g_ascii_strncasecmp (image_uri, "cid:", 4) == 0); + + if (image_uri != NULL) { + if (strstr (image_uri, "://") == NULL && !is_cid) { + gchar *temp; + + temp = g_strconcat ("file://", image_uri, NULL); + g_free (image_uri); + temp = image_uri; + } + } + + if (puri != NULL) { + if (text_uri != NULL) + *puri = em_format_find_puri (formatter, text_uri); + + if (*puri == NULL && image_uri != NULL) + *puri = em_format_find_puri (formatter, image_uri); + } + + if (uri != NULL) { + *uri = NULL; + if (is_cid) { + if (text_uri != NULL) + *uri = g_strdup_printf ( + "%s\n%s", text_uri, image_uri); + else { + *uri = image_uri; + image_uri = NULL; + } + } else { + *uri = text_uri; + text_uri = NULL; + } + } + + g_free (text_uri); + g_free (image_uri); +} + +static void +mail_display_update_formatter_colors (EMailDisplay *display) +{ + EMFormatHTMLColorType type; + EMFormatHTML *formatter; + GdkColor *color; + GtkStyle *style; + gint state; + + state = GTK_WIDGET_STATE (display); + formatter = display->priv->formatter; + + style = gtk_widget_get_style (GTK_WIDGET (display)); + if (style == NULL) + return; + + g_object_freeze_notify (G_OBJECT (formatter)); + + color = &style->bg[state]; + type = EM_FORMAT_HTML_COLOR_BODY; + em_format_html_set_color (formatter, type, color); + + color = &style->base[GTK_STATE_NORMAL]; + type = EM_FORMAT_HTML_COLOR_CONTENT; + em_format_html_set_color (formatter, type, color); + + color = &style->dark[state]; + type = EM_FORMAT_HTML_COLOR_FRAME; + em_format_html_set_color (formatter, type, color); + + color = &style->fg[state]; + type = EM_FORMAT_HTML_COLOR_HEADER; + em_format_html_set_color (formatter, type, color); + + color = &style->text[state]; + type = EM_FORMAT_HTML_COLOR_TEXT; + em_format_html_set_color (formatter, type, color); + + g_object_thaw_notify (G_OBJECT (formatter)); +} + +static void +mail_display_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ANIMATE: + e_mail_display_set_animate ( + E_MAIL_DISPLAY (object), + g_value_get_boolean (value)); + return; + + case PROP_CARET_MODE: + e_mail_display_set_caret_mode ( + E_MAIL_DISPLAY (object), + g_value_get_boolean (value)); + return; + + case PROP_FORMATTER: + e_mail_display_set_formatter ( + E_MAIL_DISPLAY (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_display_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ANIMATE: + g_value_set_boolean ( + value, e_mail_display_get_animate ( + E_MAIL_DISPLAY (object))); + return; + + case PROP_CARET_MODE: + g_value_set_boolean ( + value, e_mail_display_get_caret_mode ( + E_MAIL_DISPLAY (object))); + return; + + case PROP_FORMATTER: + g_value_set_object ( + value, e_mail_display_get_formatter ( + E_MAIL_DISPLAY (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_display_dispose (GObject *object) +{ + EMailDisplayPrivate *priv; + + priv = E_MAIL_DISPLAY_GET_PRIVATE (object); + + if (priv->formatter) { + g_object_unref (priv->formatter); + priv->formatter = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +mail_display_realize (GtkWidget *widget) +{ + /* Chain up to parent's realize() method. */ + GTK_WIDGET_CLASS (parent_class)->realize (widget); + + mail_display_update_formatter_colors (E_MAIL_DISPLAY (widget)); +} + +static void +mail_display_style_set (GtkWidget *widget, + GtkStyle *previous_style) +{ + EMailDisplayPrivate *priv; + + priv = E_MAIL_DISPLAY_GET_PRIVATE (widget); + + /* Chain up to parent's style_set() method. */ + GTK_WIDGET_CLASS (parent_class)->style_set (widget, previous_style); + + mail_display_update_formatter_colors (E_MAIL_DISPLAY (widget)); + em_format_redraw (EM_FORMAT (priv->formatter)); +} + +static gboolean +mail_display_button_press_event (GtkWidget *widget, + GdkEventButton *event) +{ + if (event->button == 3) { + EMailDisplay *display; + EMFormatPURI *puri = NULL; + gboolean stop_handlers = TRUE; + gchar *uri = NULL; + + display = E_MAIL_DISPLAY (widget); + mail_display_get_uri_puri (display, event, &uri, &puri); + + if (uri == NULL || !g_str_has_prefix (uri, "##")) + stop_handlers = mail_display_emit_popup_event ( + display, event, uri, puri); + + g_free (uri); + + if (stop_handlers) + return TRUE; + } + + /* Chain up to parent's button_press_event() method. */ + return GTK_WIDGET_CLASS (parent_class)-> + button_press_event (widget, event); +} + +static gboolean +mail_display_scroll_event (GtkWidget *widget, + GdkEventScroll *event) +{ + if (event->state & GDK_CONTROL_MASK) { + switch (event->direction) { + case GDK_SCROLL_UP: + gtk_html_zoom_in (GTK_HTML (widget)); + return TRUE; + case GDK_SCROLL_DOWN: + gtk_html_zoom_out (GTK_HTML (widget)); + return TRUE; + default: + break; + } + } + + return FALSE; +} + +static void +mail_display_link_clicked (GtkHTML *html, + const gchar *uri) +{ + EMailDisplayPrivate *priv; + + priv = E_MAIL_DISPLAY_GET_PRIVATE (html); + g_return_if_fail (priv->formatter != NULL); + + if (g_str_has_prefix (uri, "##")) { + guint32 flags; + + flags = priv->formatter->header_wrap_flags; + + if (strcmp (uri, "##TO##") == 0) { + if (!(flags & EM_FORMAT_HTML_HEADER_TO)) + flags |= EM_FORMAT_HTML_HEADER_TO; + else + flags &= ~EM_FORMAT_HTML_HEADER_TO; + } else if (strcmp (uri, "##CC##") == 0) { + if (!(flags & EM_FORMAT_HTML_HEADER_CC)) + flags |= EM_FORMAT_HTML_HEADER_CC; + else + flags |= EM_FORMAT_HTML_HEADER_CC; + } else if (strcmp (uri, "##BCC##") == 0) { + if (!(flags & EM_FORMAT_HTML_HEADER_BCC)) + flags |= EM_FORMAT_HTML_HEADER_BCC; + else + flags |= EM_FORMAT_HTML_HEADER_BCC; + } + + priv->formatter->header_wrap_flags = flags; + em_format_redraw (EM_FORMAT (priv->formatter)); + + } else if (*uri == '#') + gtk_html_jump_to_anchor (html, uri + 1); + + else if (g_ascii_strncasecmp (uri, "thismessage:", 12) == 0) + /* ignore */ ; + + else if (g_ascii_strncasecmp (uri, "cid:", 4) == 0) + /* ignore */ ; + + else { + gpointer parent; + + parent = gtk_widget_get_toplevel (GTK_WIDGET (html)); + parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; + + e_show_uri (parent, uri); + } +} + +static void +mail_display_on_url (GtkHTML *html, + const gchar *uri) +{ + EMailDisplay *display; + CamelInternetAddress *address; + CamelURL *curl; + const gchar *format = NULL; + gchar *message = NULL; + gchar *who; + + display = E_MAIL_DISPLAY (html); + + if (uri == NULL || *uri == '\0') + goto exit; + + if (g_str_has_prefix (uri, "mailto:")) + format = _("Click to mail %s"); + else if (g_str_has_prefix (uri, "callto:")) + format = _("Click to call %s"); + else if (g_str_has_prefix (uri, "h323:")) + format = _("Click to call %s"); + else if (g_str_has_prefix (uri, "sip:")) + format = _("Click to call %s"); + else if (g_str_has_prefix (uri, "##")) + message = g_strdup (_("Click to hide/unhide addresses")); + else + message = g_strdup_printf (_("Click to open %s"), uri); + + if (format == NULL) + goto exit; + + curl = camel_url_new (uri, NULL); + address = camel_internet_address_new (); + camel_address_decode (CAMEL_ADDRESS (address), curl->path); + who = camel_address_format (CAMEL_ADDRESS (address)); + camel_object_unref (address); + camel_url_free (curl); + + if (who == NULL) + who = g_strdup (strchr (uri, ':') + 1); + + message = g_strdup_printf (format, who); + + g_free (who); + +exit: + mail_display_emit_status_message (display, message); + + g_free (message); +} + +static void +mail_display_iframe_created (GtkHTML *html, + GtkHTML *iframe) +{ + g_signal_connect_swapped ( + iframe, "button-press-event", + G_CALLBACK (mail_display_button_press_event), html); +} + +static void +mail_display_class_init (EMailDisplayClass *class) +{ + GObjectClass *object_class; + GtkWidgetClass *widget_class; + GtkHTMLClass *html_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMailDisplayPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_display_set_property; + object_class->get_property = mail_display_get_property; + object_class->dispose = mail_display_dispose; + + widget_class = GTK_WIDGET_CLASS (class); + widget_class->realize = mail_display_realize; + widget_class->style_set = mail_display_style_set; + widget_class->button_press_event = mail_display_button_press_event; + widget_class->scroll_event = mail_display_scroll_event; + + html_class = GTK_HTML_CLASS (class); + html_class->link_clicked = mail_display_link_clicked; + html_class->on_url = mail_display_on_url; + html_class->iframe_created = mail_display_iframe_created; + + g_object_class_install_property ( + object_class, + PROP_ANIMATE, + g_param_spec_boolean ( + "animate", + "Animate Images", + NULL, + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_CARET_MODE, + g_param_spec_boolean ( + "caret-mode", + "Caret Mode", + NULL, + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_FORMATTER, + g_param_spec_object ( + "formatter", + "HTML Formatter", + NULL, + EM_TYPE_FORMAT_HTML, + G_PARAM_READWRITE)); + + signals[POPUP_EVENT] = g_signal_new ( + "popup-event", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMailDisplayClass, popup_event), + g_signal_accumulator_true_handled, NULL, + e_marshal_BOOLEAN__BOXED_POINTER_POINTER, + G_TYPE_BOOLEAN, 3, + GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE, + G_TYPE_POINTER, + G_TYPE_POINTER); + + signals[STATUS_MESSAGE] = g_signal_new ( + "status-message", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EMailDisplayClass, status_message), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); +} + +static void +mail_display_init (EMailDisplay *display) +{ + display->priv = E_MAIL_DISPLAY_GET_PRIVATE (display); +} + +GType +e_mail_display_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMailDisplayClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) mail_display_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMailDisplay), + 0, /* n_preallocs */ + (GInstanceInitFunc) mail_display_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_HTML, "EMailDisplay", &type_info, 0); + } + + return type; +} + +gboolean +e_mail_display_get_animate (EMailDisplay *display) +{ + /* XXX This is just here to maintain symmetry + * with e_mail_display_set_animate(). */ + + g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), FALSE); + + return gtk_html_get_animate (GTK_HTML (display)); +} + +void +e_mail_display_set_animate (EMailDisplay *display, + gboolean animate) +{ + /* XXX GtkHTML does not utilize GObject properties as well + * as it could. This just wraps gtk_html_set_animate() + * so we can get a "notify::animate" signal. */ + + g_return_if_fail (E_IS_MAIL_DISPLAY (display)); + + gtk_html_set_animate (GTK_HTML (display), animate); + + g_object_notify (G_OBJECT (display), "animate"); +} + +gboolean +e_mail_display_get_caret_mode (EMailDisplay *display) +{ + /* XXX This is just here to maintain symmetry + * with e_mail_display_set_caret_mode(). */ + + g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), FALSE); + + return gtk_html_get_caret_mode (GTK_HTML (display)); +} + +void +e_mail_display_set_caret_mode (EMailDisplay *display, + gboolean caret_mode) +{ + /* XXX GtkHTML does not utilize GObject properties as well + * as it could. This just wraps gtk_html_set_caret_mode() + * so we can get a "notify::caret-mode" signal. */ + + g_return_if_fail (E_IS_MAIL_DISPLAY (display)); + + gtk_html_set_caret_mode (GTK_HTML (display), caret_mode); + + g_object_notify (G_OBJECT (display), "caret-mode"); +} + +EMFormatHTML * +e_mail_display_get_formatter (EMailDisplay *display) +{ + g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), NULL); + + return display->priv->formatter; +} + +void +e_mail_display_set_formatter (EMailDisplay *display, + EMFormatHTML *formatter) +{ + g_return_if_fail (E_IS_MAIL_DISPLAY (display)); + g_return_if_fail (EM_IS_FORMAT_HTML (formatter)); + + if (display->priv->formatter != NULL) + g_object_unref (display->priv->formatter); + + display->priv->formatter = g_object_ref (formatter); + + g_object_notify (G_OBJECT (display), "formatter"); +} diff --git a/mail/e-mail-display.h b/mail/e-mail-display.h new file mode 100644 index 0000000000..f1d5fc583f --- /dev/null +++ b/mail/e-mail-display.h @@ -0,0 +1,83 @@ +/* + * e-mail-display.h + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MAIL_DISPLAY_H +#define E_MAIL_DISPLAY_H + +#include <gtkhtml/gtkhtml.h> +#include <mail/em-format-html.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_DISPLAY \ + (e_mail_display_get_type ()) +#define E_MAIL_DISPLAY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_DISPLAY, EMailDisplay)) +#define E_MAIL_DISPLAY_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_DISPLAY, EMailDisplayClass)) +#define E_IS_MAIL_DISPLAY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_DISPLAY)) +#define E_IS_MAIL_DISPLAY_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_DISPLAY)) +#define E_MAIL_DISPLAY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_DISPLAY, EMailDisplayClass)) + +G_BEGIN_DECLS + +typedef struct _EMailDisplay EMailDisplay; +typedef struct _EMailDisplayClass EMailDisplayClass; +typedef struct _EMailDisplayPrivate EMailDisplayPrivate; + +struct _EMailDisplay { + GtkHTML parent; + EMailDisplayPrivate *priv; +}; + +struct _EMailDisplayClass { + GtkHTMLClass parent_class; + + /* Signals */ + gboolean (*popup_event) (EMailDisplay *display, + GdkEventButton *event, + const gchar *uri, + EMFormatPURI *puri); + void (*status_message) (EMailDisplay *display, + const gchar *status_message); +}; + +GType e_mail_display_get_type (void); +gboolean e_mail_display_get_animate (EMailDisplay *display); +void e_mail_display_set_animate (EMailDisplay *display, + gboolean animate); +gboolean e_mail_display_get_caret_mode (EMailDisplay *display); +void e_mail_display_set_caret_mode (EMailDisplay *display, + gboolean caret_mode); +EMFormatHTML * e_mail_display_get_formatter (EMailDisplay *display); +void e_mail_display_set_formatter (EMailDisplay *display, + EMFormatHTML *formatter); + +G_END_DECLS + +#endif /* E_MAIL_DISPLAY_H */ diff --git a/mail/e-mail-label-dialog.c b/mail/e-mail-label-dialog.c new file mode 100644 index 0000000000..23b5068737 --- /dev/null +++ b/mail/e-mail-label-dialog.c @@ -0,0 +1,323 @@ +/* + * e-mail-label-dialog.c + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-label-dialog.h" + +#include <glib/gi18n.h> + +#define E_MAIL_LABEL_DIALOG_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_LABEL_DIALOG, EMailLabelDialogPrivate)) + +struct _EMailLabelDialogPrivate { + GtkWidget *entry; + GtkWidget *colorsel; +}; + +enum { + PROP_0, + PROP_LABEL_COLOR, + PROP_LABEL_NAME +}; + +static gpointer parent_class; + +static void +mail_label_dialog_entry_changed_cb (EMailLabelDialog *dialog) +{ + const gchar *text; + gboolean sensitive; + + text = gtk_entry_get_text (GTK_ENTRY (dialog->priv->entry)); + sensitive = (text != NULL && *text != '\0'); + + gtk_dialog_set_response_sensitive ( + GTK_DIALOG (dialog), GTK_RESPONSE_OK, sensitive); +} + +static void +mail_label_dialog_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_LABEL_COLOR: + e_mail_label_dialog_set_label_color ( + E_MAIL_LABEL_DIALOG (object), + g_value_get_boxed (value)); + return; + + case PROP_LABEL_NAME: + e_mail_label_dialog_set_label_name ( + E_MAIL_LABEL_DIALOG (object), + g_value_get_string (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_label_dialog_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GdkColor color; + + switch (property_id) { + case PROP_LABEL_COLOR: + e_mail_label_dialog_get_label_color ( + E_MAIL_LABEL_DIALOG (object), &color); + g_value_set_boxed (value, &color); + return; + + case PROP_LABEL_NAME: + g_value_set_string ( + value, e_mail_label_dialog_get_label_name ( + E_MAIL_LABEL_DIALOG (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_label_dialog_dispose (GObject *object) +{ + EMailLabelDialogPrivate *priv; + + priv = E_MAIL_LABEL_DIALOG_GET_PRIVATE (object); + + if (priv->entry != NULL) { + g_object_unref (priv->entry); + priv->entry = NULL; + } + + if (priv->colorsel != NULL) { + g_object_unref (priv->colorsel); + priv->colorsel = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +mail_label_dialog_constructed (GObject *object) +{ + GtkWidget *action_area; + GtkWidget *content_area; + + /* XXX Override GTK's style property defaults for GtkDialog. + * Hopefully GTK+ 3.0 will fix the broken defaults. */ + + action_area = gtk_dialog_get_action_area (GTK_DIALOG (object)); + content_area = gtk_dialog_get_content_area (GTK_DIALOG (object)); + + gtk_box_set_spacing (GTK_BOX (content_area), 12); + gtk_container_set_border_width (GTK_CONTAINER (object), 12); + gtk_container_set_border_width (GTK_CONTAINER (action_area), 0); + gtk_container_set_border_width (GTK_CONTAINER (content_area), 0); +} + +static void +mail_label_dialog_class_init (EMailLabelDialogClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMailLabelDialogPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_label_dialog_set_property; + object_class->get_property = mail_label_dialog_get_property; + object_class->dispose = mail_label_dialog_dispose; + object_class->constructed = mail_label_dialog_constructed; + + g_object_class_install_property ( + object_class, + PROP_LABEL_COLOR, + g_param_spec_boxed ( + "label-color", + "Label Color", + NULL, + GDK_TYPE_COLOR, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_LABEL_NAME, + g_param_spec_string ( + "label-name", + "Label Name", + NULL, + NULL, + G_PARAM_READWRITE)); +} + +static void +mail_label_dialog_init (EMailLabelDialog *dialog) +{ + GtkWidget *content_area; + GtkWidget *container; + GtkWidget *widget; + + dialog->priv = E_MAIL_LABEL_DIALOG_GET_PRIVATE (dialog); + + content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); + + gtk_dialog_add_button ( + GTK_DIALOG (dialog), + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); + + gtk_dialog_add_button ( + GTK_DIALOG (dialog), + GTK_STOCK_OK, GTK_RESPONSE_OK); + + gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); + + container = content_area; + + widget = gtk_hbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_entry_new (); + gtk_entry_set_activates_default (GTK_ENTRY (widget), TRUE); + gtk_box_pack_end (GTK_BOX (container), widget, TRUE, TRUE, 0); + dialog->priv->entry = g_object_ref (widget); + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "changed", + G_CALLBACK (mail_label_dialog_entry_changed_cb), dialog); + + mail_label_dialog_entry_changed_cb (dialog); + + widget = gtk_label_new_with_mnemonic (_("_Label name:")); + gtk_label_set_mnemonic_widget ( + GTK_LABEL (widget), dialog->priv->entry); + gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = content_area; + + widget = gtk_color_selection_new (); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + dialog->priv->colorsel = g_object_ref (widget); + gtk_widget_show (widget); +} + +GType +e_mail_label_dialog_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMailLabelDialogClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) mail_label_dialog_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMailLabelDialog), + 0, /* n_preallocs */ + (GInstanceInitFunc) mail_label_dialog_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_DIALOG, "EMailLabelDialog", &type_info, 0); + } + + return type; +} + +GtkWidget * +e_mail_label_dialog_new (GtkWindow *parent) +{ + return g_object_new ( + E_TYPE_MAIL_LABEL_DIALOG, + "transient-for", parent, NULL); +} + +const gchar * +e_mail_label_dialog_get_label_name (EMailLabelDialog *dialog) +{ + GtkEntry *entry; + + g_return_val_if_fail (E_IS_MAIL_LABEL_DIALOG (dialog), NULL); + + entry = GTK_ENTRY (dialog->priv->entry); + + return gtk_entry_get_text (entry); +} + +void +e_mail_label_dialog_set_label_name (EMailLabelDialog *dialog, + const gchar *label_name) +{ + GtkEntry *entry; + + g_return_if_fail (E_IS_MAIL_LABEL_DIALOG (dialog)); + + entry = GTK_ENTRY (dialog->priv->entry); + + gtk_entry_set_text (entry, label_name); + + g_object_notify (G_OBJECT (dialog), "label-name"); +} + +void +e_mail_label_dialog_get_label_color (EMailLabelDialog *dialog, + GdkColor *label_color) +{ + GtkColorSelection *colorsel; + + g_return_if_fail (E_IS_MAIL_LABEL_DIALOG (dialog)); + g_return_if_fail (label_color != NULL); + + colorsel = GTK_COLOR_SELECTION (dialog->priv->colorsel); + + gtk_color_selection_get_current_color (colorsel, label_color); +} + +void +e_mail_label_dialog_set_label_color (EMailLabelDialog *dialog, + const GdkColor *label_color) +{ + GtkColorSelection *colorsel; + + g_return_if_fail (E_IS_MAIL_LABEL_DIALOG (dialog)); + g_return_if_fail (label_color != NULL); + + colorsel = GTK_COLOR_SELECTION (dialog->priv->colorsel); + + gtk_color_selection_set_current_color (colorsel, label_color); + + g_object_notify (G_OBJECT (dialog), "label-color"); +} diff --git a/mail/e-mail-label-dialog.h b/mail/e-mail-label-dialog.h new file mode 100644 index 0000000000..3a259f6f50 --- /dev/null +++ b/mail/e-mail-label-dialog.h @@ -0,0 +1,77 @@ +/* + * e-mail-label-dialog.h + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MAIL_LABEL_DIALOG_H +#define E_MAIL_LABEL_DIALOG_H + +#include <gtk/gtk.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_LABEL_DIALOG \ + (e_mail_label_dialog_get_type ()) +#define E_MAIL_LABEL_DIALOG(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_LABEL_DIALOG, EMailLabelDialog)) +#define E_MAIL_LABEL_DIALOG_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_LABEL_DIALOG, EMailLabelDialogClass)) +#define E_IS_MAIL_LABEL_DIALOG(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_LABEL_DIALOG)) +#define E_IS_MAIL_LABEL_DIALOG_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_LABEL_DIALOG)) +#define E_MAIL_LABEL_DIALOG_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_LABEL_DIALOG, EMailLabelDialogClass)) + +G_BEGIN_DECLS + +typedef struct _EMailLabelDialog EMailLabelDialog; +typedef struct _EMailLabelDialogClass EMailLabelDialogClass; +typedef struct _EMailLabelDialogPrivate EMailLabelDialogPrivate; + +struct _EMailLabelDialog { + GtkDialog parent; + EMailLabelDialogPrivate *priv; +}; + +struct _EMailLabelDialogClass { + GtkDialogClass parent_class; +}; + +GType e_mail_label_dialog_get_type (void); +GtkWidget * e_mail_label_dialog_new (GtkWindow *parent); +const gchar * e_mail_label_dialog_get_label_name + (EMailLabelDialog *dialog); +void e_mail_label_dialog_set_label_name + (EMailLabelDialog *dialog, + const gchar *label_name); +void e_mail_label_dialog_get_label_color + (EMailLabelDialog *dialog, + GdkColor *label_color); +void e_mail_label_dialog_set_label_color + (EMailLabelDialog *dialog, + const GdkColor *label_color); + +G_END_DECLS + +#endif /* E_MAIL_LABEL_DIALOG_H */ diff --git a/mail/e-mail-label-list-store.c b/mail/e-mail-label-list-store.c new file mode 100644 index 0000000000..3892838aaf --- /dev/null +++ b/mail/e-mail-label-list-store.c @@ -0,0 +1,513 @@ +/* + * e-mail-label-list-store.c + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-label-list-store.h" + +#include <glib/gi18n.h> +#include <camel/camel-utf8.h> +#include "e-util/gconf-bridge.h" + +#define E_MAIL_LABEL_LIST_STORE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_LABEL_LIST_STORE, EMailLabelListStorePrivate)) + +struct _EMailLabelListStorePrivate { + GHashTable *tag_index; +}; + +static struct { + const gchar *label_name; + const gchar *label_color; + const gchar *label_tag; +} label_defaults[] = { + { N_("I_mportant"), "#EF2929", "$Labelimportant" }, /* red */ + { N_("_Work"), "#F57900", "$Labelwork" }, /* orange */ + { N_("_Personal"), "#4E9A06", "$Labelpersonal" }, /* green */ + { N_("_To Do"), "#3465A4", "$Labeltodo" }, /* blue */ + { N_("_Later"), "#75507B", "$Labellater" } /* purple */ +}; + +static gpointer parent_class; + +static gchar * +mail_label_list_store_tag_from_name (const gchar *label_name) +{ + gchar *label_tag; + gchar *temp; + + /* Thunderbird compatible */ + temp = g_ascii_strdown (label_name, -1); + g_strdelimit (temp, " ()/{%*<>\\\"", '_'); + label_tag = camel_utf8_utf7 (temp); + g_free (temp); + + return label_tag; +} + +static gchar * +mail_label_list_store_encode_label (const gchar *label_name, + const gchar *label_color, + const gchar *label_tag) +{ + GString *string; + + /* Encoded Form: <name> ':' <color> [ '|' <tag> ] */ + + string = g_string_new (label_name); + g_string_append_printf (string, ":%s", label_color); + + if (label_tag != NULL) + g_string_append_printf (string, "|%s", label_tag); + + return g_string_free (string, FALSE); +} + +static void +mail_label_list_store_ensure_defaults (EMailLabelListStore *store) +{ + gint ii; + + for (ii = 0; ii < G_N_ELEMENTS (label_defaults); ii++) { + GtkTreeIter iter; + const gchar *label_name; + const gchar *label_color; + const gchar *label_tag; + gchar *encoded; + + label_name = gettext (label_defaults[ii].label_name); + label_color = label_defaults[ii].label_color; + label_tag = label_defaults[ii].label_tag; + + encoded = mail_label_list_store_encode_label ( + label_name, label_color, label_tag); + + if (e_mail_label_list_store_lookup (store, label_tag, &iter)) + gtk_list_store_set ( + GTK_LIST_STORE (store), + &iter, 0, encoded, -1); + else + gtk_list_store_insert_with_values ( + GTK_LIST_STORE (store), + NULL, -1, 0, encoded, -1); + + g_free (encoded); + } +} + +static gchar * +mail_label_list_store_get_stock_id (EMailLabelListStore *store, + const gchar *color_spec) +{ + EMailLabelListStoreClass *class; + GtkIconFactory *icon_factory; + GdkColor color; + gchar *stock_id; + + class = E_MAIL_LABEL_LIST_STORE_GET_CLASS (store); + icon_factory = class->icon_factory; + + if (!gdk_color_parse (color_spec, &color)) + return NULL; + + stock_id = g_strdup_printf ("evolution-label-%s", color_spec); + + /* Themes need not be taken into account here. + * It's just a solid block of a user-chosen color. */ + if (gtk_icon_factory_lookup (icon_factory, stock_id) == NULL) { + GtkIconSet *icon_set; + GdkPixbuf *pixbuf; + guint32 pixel; + + pixel = ((color.red & 0xFF00) << 16) + + ((color.green & 0xFF00) << 8) + + (color.blue & 0xFF00); + + pixbuf = gdk_pixbuf_new ( + GDK_COLORSPACE_RGB, FALSE, 8, 16, 16); + gdk_pixbuf_fill (pixbuf, pixel); + + icon_set = gtk_icon_set_new_from_pixbuf (pixbuf); + gtk_icon_factory_add (icon_factory, stock_id, icon_set); + gtk_icon_set_unref (icon_set); + + g_object_unref (pixbuf); + } + + return stock_id; +} + +static void +mail_label_list_store_finalize (GObject *object) +{ + EMailLabelListStorePrivate *priv; + + priv = E_MAIL_LABEL_LIST_STORE_GET_PRIVATE (object); + + g_hash_table_destroy (priv->tag_index); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +mail_label_list_store_constructed (GObject *object) +{ + EMailLabelListStore *store; + GtkTreeModel *model; + GConfBridge *bridge; + const gchar *key; + + model = GTK_TREE_MODEL (object); + store = E_MAIL_LABEL_LIST_STORE (object); + + bridge = gconf_bridge_get (); + key = "/apps/evolution/mail/labels"; + gconf_bridge_bind_string_list_store ( + bridge, key, GTK_LIST_STORE (store)); + + mail_label_list_store_ensure_defaults (store); +} + +static void +mail_label_list_store_row_inserted (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter) +{ + EMailLabelListStore *store; + GtkTreeRowReference *reference; + GHashTable *tag_index; + gchar *tag; + + store = E_MAIL_LABEL_LIST_STORE (model); + + /* Hash table takes ownership of both tag and reference. */ + tag_index = store->priv->tag_index; + tag = e_mail_label_list_store_get_tag (store, iter); + reference = gtk_tree_row_reference_new (model, path); + g_hash_table_insert (tag_index, tag, reference); + + /* We don't need to do anything special for row deletion. + * The reference will automatically become invalid (that's + * why we're storing references and not iterators or paths), + * so garbage collection is not important. We'll do it + * lazily. */ +} + +static void +mail_label_list_store_class_init (EMailLabelListStoreClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMailLabelListStorePrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->finalize = mail_label_list_store_finalize; + object_class->constructed = mail_label_list_store_constructed; + + class->icon_factory = gtk_icon_factory_new (); + gtk_icon_factory_add_default (class->icon_factory); +} + +static void +mail_label_list_store_init (EMailLabelListStore *store) +{ + GHashTable *tag_index; + GType type = G_TYPE_STRING; + + tag_index = g_hash_table_new_full ( + g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) gtk_tree_row_reference_free); + + store->priv = E_MAIL_LABEL_LIST_STORE_GET_PRIVATE (store); + store->priv->tag_index = tag_index; + + /* XXX While it may seem awkward to cram the label name and color + * into a single string column, we do it for the benefit of + * letting GConfBridge keep the model in sync with GConf. + * + * XXX There's a valid argument to be made that this information + * doesn't belong in GConf in the first place. A key file + * under $(user_data_dir)/mail would work better. */ + gtk_list_store_set_column_types (GTK_LIST_STORE (store), 1, &type); +} + +static void +mail_label_list_store_iface_init (GtkTreeModelIface *iface) +{ + iface->row_inserted = mail_label_list_store_row_inserted; +} + +GType +e_mail_label_list_store_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMailLabelListStoreClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) mail_label_list_store_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMailLabelListStore), + 0, /* n_preallocs */ + (GInstanceInitFunc) mail_label_list_store_init, + NULL /* vaule_table */ + }; + + static const GInterfaceInfo iface_info = { + (GInterfaceInitFunc) mail_label_list_store_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL /* interface_data */ + }; + + type = g_type_register_static ( + GTK_TYPE_LIST_STORE, "EMailLabelListStore", + &type_info, 0); + + g_type_add_interface_static ( + type, GTK_TYPE_TREE_MODEL, &iface_info); + } + + return type; +} + +EMailLabelListStore * +e_mail_label_list_store_new (void) +{ + return g_object_new (E_TYPE_MAIL_LABEL_LIST_STORE, NULL); +} + +gchar * +e_mail_label_list_store_get_name (EMailLabelListStore *store, + GtkTreeIter *iter) +{ + gchar *encoded; + gchar *result; + gchar **strv; + + /* Encoded Form: <name> ':' <color> [ '|' <tag> ] */ + + g_return_val_if_fail (E_IS_MAIL_LABEL_LIST_STORE (store), NULL); + g_return_val_if_fail (iter != NULL, NULL); + + gtk_tree_model_get (GTK_TREE_MODEL (store), iter, 0, &encoded, -1); + + strv = g_strsplit_set (encoded, ":|", 3); + + if (g_strv_length (strv) >= 2) + result = g_strdup (gettext (strv[0])); + else + result = NULL; + + g_strfreev (strv); + + return result; +} + +gboolean +e_mail_label_list_store_get_color (EMailLabelListStore *store, + GtkTreeIter *iter, + GdkColor *color) +{ + gchar *encoded; + gchar **strv; + gboolean valid; + + /* Encoded Form: <name> ':' <color> [ '|' <tag> ] */ + + g_return_val_if_fail (E_IS_MAIL_LABEL_LIST_STORE (store), FALSE); + g_return_val_if_fail (iter != NULL, FALSE); + g_return_val_if_fail (color != NULL, FALSE); + + gtk_tree_model_get (GTK_TREE_MODEL (store), iter, 0, &encoded, -1); + + strv = g_strsplit_set (encoded, ":|", 3); + + if (g_strv_length (strv) >= 2) + valid = gdk_color_parse (strv[1], color); + else + valid = FALSE; + + g_strfreev (strv); + + return valid; +} + +gchar * +e_mail_label_list_store_get_stock_id (EMailLabelListStore *store, + GtkTreeIter *iter) +{ + gchar *encoded; + gchar *result; + gchar **strv; + + /* Encoded Form: <name> ':' <color> [ '|' <tag> ] */ + + g_return_val_if_fail (E_IS_MAIL_LABEL_LIST_STORE (store), NULL); + g_return_val_if_fail (iter != NULL, NULL); + gtk_tree_model_get (GTK_TREE_MODEL (store), iter, 0, &encoded, -1); + + strv = g_strsplit_set (encoded, ":|", 3); + + if (g_strv_length (strv) >= 2) + result = mail_label_list_store_get_stock_id (store, strv[1]); + else + result = NULL; + + g_strfreev (strv); + + return result; +} + +gchar * +e_mail_label_list_store_get_tag (EMailLabelListStore *store, + GtkTreeIter *iter) +{ + gchar *encoded; + gchar *result; + gchar **strv; + + /* Encoded Form: <name> ':' <color> [ '|' <tag> ] */ + + g_return_val_if_fail (E_IS_MAIL_LABEL_LIST_STORE (store), NULL); + g_return_val_if_fail (iter != NULL, NULL); + + gtk_tree_model_get (GTK_TREE_MODEL (store), iter, 0, &encoded, -1); + + strv = g_strsplit_set (encoded, ":|", 3); + + /* XXX I guess for historical reasons the default label tags have + * a "$Label" prefix, but the default list in GConf doesn't + * include tags. That's why the <tag> part is optional. + * So if we're missing the <tag> part, look it up in the + * hard-coded default list above. + * + * Not sure I got my facts straight here. Double check. */ + if (g_strv_length (strv) >= 3) + result = g_strdup (strv[2]); + else { + gint ii; + + result = NULL; + + for (ii = 0; ii < G_N_ELEMENTS (label_defaults); ii++) { + const gchar *label_name; + const gchar *label_tag; + + label_name = label_defaults[ii].label_name; + label_tag = label_defaults[ii].label_tag; + + if (strcmp (strv[0], label_name) == 0) { + result = g_strdup (label_tag); + break; + } + } + } + + g_strfreev (strv); + + return result; +} + +void +e_mail_label_list_store_set (EMailLabelListStore *store, + GtkTreeIter *iter, + const gchar *name, + const GdkColor *color) +{ + gchar *encoded; + gchar *label_color; + gchar *label_tag = NULL; + + g_return_if_fail (E_IS_MAIL_LABEL_LIST_STORE (store)); + g_return_if_fail (name != NULL); + g_return_if_fail (color != NULL); + + label_color = gdk_color_to_string (color); + + if (iter != NULL) + label_tag = e_mail_label_list_store_get_tag (store, iter); + if (label_tag == NULL) + label_tag = mail_label_list_store_tag_from_name (name); + + encoded = mail_label_list_store_encode_label ( + name, label_color, label_tag); + + /* We use gtk_list_store_insert_with_values() so the data is + * in place when the 'row-inserted' signal is emitted and our + * row_inserted() method executes. */ + if (iter != NULL) + gtk_list_store_set ( + GTK_LIST_STORE (store), iter, 0, encoded, -1); + else + gtk_list_store_insert_with_values ( + GTK_LIST_STORE (store), NULL, -1, 0, encoded, -1); + + g_free (label_color); + g_free (label_tag); + g_free (encoded); +} + +gboolean +e_mail_label_list_store_lookup (EMailLabelListStore *store, + const gchar *tag, + GtkTreeIter *iter) +{ + GtkTreeRowReference *reference; + GHashTable *tag_index; + GtkTreeModel *model; + GtkTreePath *path; + + g_return_val_if_fail (E_IS_MAIL_LABEL_LIST_STORE (store), FALSE); + g_return_val_if_fail (tag != NULL, FALSE); + g_return_val_if_fail (iter != NULL, FALSE); + + tag_index = store->priv->tag_index; + reference = g_hash_table_lookup (tag_index, tag); + + if (reference == NULL) + return FALSE; + + if (!gtk_tree_row_reference_valid (reference)) { + /* Garbage collect the dead reference. */ + g_hash_table_remove (tag_index, tag); + return FALSE; + } + + model = gtk_tree_row_reference_get_model (reference); + path = gtk_tree_row_reference_get_path (reference); + gtk_tree_model_get_iter (model, iter, path); + gtk_tree_path_free (path); + + return TRUE; +} + +gboolean +e_mail_label_tag_is_default (const gchar *tag) +{ + g_return_val_if_fail (tag != NULL, FALSE); + + return g_str_has_prefix (tag, "$Label"); +} diff --git a/mail/e-mail-label-list-store.h b/mail/e-mail-label-list-store.h new file mode 100644 index 0000000000..2469d210c0 --- /dev/null +++ b/mail/e-mail-label-list-store.h @@ -0,0 +1,85 @@ +/* + * e-mail-label-list-store.h + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MAIL_LABEL_LIST_STORE_H +#define E_MAIL_LABEL_LIST_STORE_H + +#include <gtk/gtk.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_LABEL_LIST_STORE \ + (e_mail_label_list_store_get_type ()) +#define E_MAIL_LABEL_LIST_STORE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_LABEL_LIST_STORE, EMailLabelListStore)) +#define E_MAIL_LABEL_LIST_STORE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_LABEL_LIST_STORE, EMailLabelListStoreClass)) +#define E_IS_MAIL_LABEL_LIST_STORE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_LABEL_LIST_STORE)) +#define E_IS_MAIL_LABEL_LIST_STORE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_LABEL_LIST_STORE)) +#define E_MAIL_LABEL_LIST_STORE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_LABEL_LIST_STORE, EMailLabelListStoreClass)) + +G_BEGIN_DECLS + +typedef struct _EMailLabelListStore EMailLabelListStore; +typedef struct _EMailLabelListStoreClass EMailLabelListStoreClass; +typedef struct _EMailLabelListStorePrivate EMailLabelListStorePrivate; + +struct _EMailLabelListStore { + GtkListStore parent; + EMailLabelListStorePrivate *priv; +}; + +struct _EMailLabelListStoreClass { + GtkListStoreClass parent_class; + GtkIconFactory *icon_factory; +}; + +GType e_mail_label_list_store_get_type (void); +EMailLabelListStore * + e_mail_label_list_store_new (void); +gchar * e_mail_label_list_store_get_name (EMailLabelListStore *store, + GtkTreeIter *iter); +gboolean e_mail_label_list_store_get_color (EMailLabelListStore *store, + GtkTreeIter *iter, + GdkColor *color); +gchar * e_mail_label_list_store_get_stock_id (EMailLabelListStore *store, + GtkTreeIter *iter); +gchar * e_mail_label_list_store_get_tag (EMailLabelListStore *store, + GtkTreeIter *iter); +void e_mail_label_list_store_set (EMailLabelListStore *store, + GtkTreeIter *iter, + const gchar *name, + const GdkColor *color); +gboolean e_mail_label_list_store_lookup (EMailLabelListStore *store, + const gchar *tag, + GtkTreeIter *iter); +gboolean e_mail_label_tag_is_default (const gchar *tag); + +G_END_DECLS + +#endif /* E_MAIL_LABEL_LIST_STORE_H */ diff --git a/mail/e-mail-label-manager.c b/mail/e-mail-label-manager.c new file mode 100644 index 0000000000..fc18da3e95 --- /dev/null +++ b/mail/e-mail-label-manager.c @@ -0,0 +1,479 @@ +/* + * e-mail-label-manager.c + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-label-manager.h" + +#include <glib/gi18n.h> +#include "e-mail-label-dialog.h" +#include "e-mail-label-tree-view.h" + +#define E_MAIL_LABEL_MANAGER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_LABEL_MANAGER, EMailLabelManagerPrivate)) + +struct _EMailLabelManagerPrivate { + GtkWidget *tree_view; + GtkWidget *add_button; + GtkWidget *edit_button; + GtkWidget *remove_button; +}; + +enum { + PROP_0, + PROP_LIST_STORE +}; + +enum { + ADD_LABEL, + EDIT_LABEL, + REMOVE_LABEL, + LAST_SIGNAL +}; + +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; + +static void +mail_label_manager_selection_changed_cb (EMailLabelManager *manager, + GtkTreeSelection *selection) +{ + GtkWidget *edit_button; + GtkWidget *remove_button; + GtkTreeModel *model; + GtkTreeIter iter; + + edit_button = manager->priv->edit_button; + remove_button = manager->priv->remove_button; + + if (gtk_tree_selection_get_selected (selection, &model, &iter)) { + EMailLabelListStore *store; + gboolean sensitive; + gchar *label_tag; + + store = E_MAIL_LABEL_LIST_STORE (model); + label_tag = e_mail_label_list_store_get_tag (store, &iter); + sensitive = !e_mail_label_tag_is_default (label_tag); + g_free (label_tag); + + /* Disallow removing default labels. */ + gtk_widget_set_sensitive (edit_button, TRUE); + gtk_widget_set_sensitive (remove_button, sensitive); + } else { + gtk_widget_set_sensitive (edit_button, FALSE); + gtk_widget_set_sensitive (remove_button, FALSE); + } +} + +static void +mail_label_manager_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_LIST_STORE: + e_mail_label_manager_set_list_store ( + E_MAIL_LABEL_MANAGER (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_label_manager_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_LIST_STORE: + g_value_set_object ( + value, e_mail_label_manager_get_list_store ( + E_MAIL_LABEL_MANAGER (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_label_manager_dispose (GObject *object) +{ + EMailLabelManagerPrivate *priv; + + priv = E_MAIL_LABEL_MANAGER_GET_PRIVATE (object); + + if (priv->tree_view != NULL) { + g_object_unref (priv->tree_view); + priv->tree_view = NULL; + } + + if (priv->add_button != NULL) { + g_object_unref (priv->add_button); + priv->add_button = NULL; + } + + if (priv->edit_button != NULL) { + g_object_unref (priv->edit_button); + priv->edit_button = NULL; + } + + if (priv->remove_button != NULL) { + g_object_unref (priv->remove_button); + priv->remove_button = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +mail_label_manager_add_label (EMailLabelManager *manager) +{ + EMailLabelDialog *label_dialog; + GtkTreeView *tree_view; + GtkTreeModel *model; + GtkWidget *dialog; + gpointer parent; + GdkColor label_color; + const gchar *label_name; + + parent = gtk_widget_get_toplevel (GTK_WIDGET (manager)); + parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; + dialog = e_mail_label_dialog_new (parent); + + gtk_window_set_title (GTK_WINDOW (dialog), _("Add Label")); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) + goto exit; + + label_dialog = E_MAIL_LABEL_DIALOG (dialog); + label_name = e_mail_label_dialog_get_label_name (label_dialog); + e_mail_label_dialog_get_label_color (label_dialog, &label_color); + + tree_view = GTK_TREE_VIEW (manager->priv->tree_view); + model = gtk_tree_view_get_model (tree_view); + + e_mail_label_list_store_set ( + E_MAIL_LABEL_LIST_STORE (model), + NULL, label_name, &label_color); + +exit: + gtk_widget_destroy (dialog); +} + +static void +mail_label_manager_edit_label (EMailLabelManager *manager) +{ + EMailLabelDialog *label_dialog; + EMailLabelListStore *label_store; + GtkTreeSelection *selection; + GtkTreeView *tree_view; + GtkTreeModel *model; + GtkTreeIter iter; + GtkWidget *dialog; + GtkWidget *parent; + GdkColor label_color; + const gchar *new_name; + gchar *label_name; + + tree_view = GTK_TREE_VIEW (manager->priv->tree_view); + selection = gtk_tree_view_get_selection (tree_view); + + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + return; + + label_store = E_MAIL_LABEL_LIST_STORE (model); + label_name = e_mail_label_list_store_get_name (label_store, &iter); + e_mail_label_list_store_get_color (label_store, &iter, &label_color); + + parent = gtk_widget_get_toplevel (GTK_WIDGET (manager)); + dialog = e_mail_label_dialog_new (GTK_WINDOW (parent)); + label_dialog = E_MAIL_LABEL_DIALOG (dialog); + + e_mail_label_dialog_set_label_name (label_dialog, label_name); + e_mail_label_dialog_set_label_color (label_dialog, &label_color); + gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Label")); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) + goto exit; + + new_name = e_mail_label_dialog_get_label_name (label_dialog); + e_mail_label_dialog_get_label_color (label_dialog, &label_color); + + e_mail_label_list_store_set ( + label_store, &iter, new_name, &label_color); + +exit: + gtk_widget_destroy (dialog); + + g_free (label_name); +} + +static void +mail_label_manager_remove_label (EMailLabelManager *manager) +{ + GtkTreeSelection *selection; + GtkTreeView *tree_view; + GtkTreeModel *model; + GtkTreeIter iter; + + tree_view = GTK_TREE_VIEW (manager->priv->tree_view); + selection = gtk_tree_view_get_selection (tree_view); + + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + return; + + gtk_list_store_remove (GTK_LIST_STORE (model), &iter); +} + +static void +mail_label_manager_class_init (EMailLabelManagerClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMailLabelManagerPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_label_manager_set_property; + object_class->get_property = mail_label_manager_get_property; + object_class->dispose = mail_label_manager_dispose; + + class->add_label = mail_label_manager_add_label; + class->edit_label = mail_label_manager_edit_label; + class->remove_label = mail_label_manager_remove_label; + + g_object_class_install_property ( + object_class, + PROP_LIST_STORE, + g_param_spec_object ( + "list-store", + "List Store", + NULL, + E_TYPE_MAIL_LABEL_LIST_STORE, + G_PARAM_READWRITE)); + + signals[ADD_LABEL] = g_signal_new ( + "add-label", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (EMailLabelManagerClass, add_label), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[EDIT_LABEL] = g_signal_new ( + "edit-label", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (EMailLabelManagerClass, edit_label), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[REMOVE_LABEL] = g_signal_new ( + "remove-label", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (EMailLabelManagerClass, remove_label), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +mail_label_manager_init (EMailLabelManager *manager) +{ + GtkTreeSelection *selection; + GtkWidget *container; + GtkWidget *widget; + + manager->priv = E_MAIL_LABEL_MANAGER_GET_PRIVATE (manager); + + gtk_table_resize (GTK_TABLE (manager), 2, 2); + gtk_table_set_col_spacings (GTK_TABLE (manager), 6); + gtk_table_set_row_spacings (GTK_TABLE (manager), 12); + + container = GTK_WIDGET (manager); + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_table_attach ( + GTK_TABLE (container), widget, 0, 1, 0, 1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_widget_show (widget); + + container = widget; + + widget = e_mail_label_tree_view_new (); + gtk_container_add (GTK_CONTAINER (container), widget); + manager->priv->tree_view = g_object_ref (widget); + gtk_widget_show (widget); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget)); + + g_signal_connect_swapped ( + selection, "changed", + G_CALLBACK (mail_label_manager_selection_changed_cb), + manager); + + container = GTK_WIDGET (manager); + + /* FIXME Clarify this. What menu? */ + widget = gtk_label_new ( + _("Note: Underscore in the label name is used\n" + "as mnemonic identifier in menu.")); + gtk_label_set_justify (GTK_LABEL (widget), GTK_JUSTIFY_CENTER); + gtk_table_attach ( + GTK_TABLE (container), widget, + 0, 1, 1, 2, 0, 0, 0, 0); + gtk_widget_show (widget); + + widget = gtk_vbutton_box_new (); + gtk_button_box_set_layout ( + GTK_BUTTON_BOX (widget), GTK_BUTTONBOX_START); + gtk_box_set_spacing (GTK_BOX (widget), 6); + gtk_table_attach ( + GTK_TABLE (container), widget, + 1, 2, 0, 2, 0, GTK_FILL, 0, 0); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_button_new_from_stock (GTK_STOCK_ADD); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + manager->priv->add_button = g_object_ref (widget); + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (e_mail_label_manager_add_label), manager); + + widget = gtk_button_new_from_stock (GTK_STOCK_EDIT); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + manager->priv->edit_button = g_object_ref (widget); + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (e_mail_label_manager_edit_label), manager); + + widget = gtk_button_new_from_stock (GTK_STOCK_REMOVE); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + manager->priv->remove_button = g_object_ref (widget); + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (e_mail_label_manager_remove_label), manager); +} + +GType +e_mail_label_manager_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMailLabelManagerClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) mail_label_manager_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMailLabelManager), + 0, /* n_preallocs */ + (GInstanceInitFunc) mail_label_manager_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_TABLE, "EMailLabelManager", &type_info, 0); + } + + return type; +} + +GtkWidget * +e_mail_label_manager_new (void) +{ + return g_object_new (E_TYPE_MAIL_LABEL_MANAGER, NULL); +} + +void +e_mail_label_manager_add_label (EMailLabelManager *manager) +{ + g_return_if_fail (E_IS_MAIL_LABEL_MANAGER (manager)); + + g_signal_emit (manager, signals[ADD_LABEL], 0); +} + +void +e_mail_label_manager_edit_label (EMailLabelManager *manager) +{ + g_return_if_fail (E_IS_MAIL_LABEL_MANAGER (manager)); + + g_signal_emit (manager, signals[EDIT_LABEL], 0); +} + +void +e_mail_label_manager_remove_label (EMailLabelManager *manager) +{ + g_return_if_fail (E_IS_MAIL_LABEL_MANAGER (manager)); + + g_signal_emit (manager, signals[REMOVE_LABEL], 0); +} + +EMailLabelListStore * +e_mail_label_manager_get_list_store (EMailLabelManager *manager) +{ + GtkTreeView *tree_view; + GtkTreeModel *model; + + g_return_val_if_fail (E_IS_MAIL_LABEL_MANAGER (manager), NULL); + + tree_view = GTK_TREE_VIEW (manager->priv->tree_view); + model = gtk_tree_view_get_model (tree_view); + + return E_MAIL_LABEL_LIST_STORE (model); +} + +void +e_mail_label_manager_set_list_store (EMailLabelManager *manager, + EMailLabelListStore *list_store) +{ + GtkTreeView *tree_view; + + g_return_if_fail (E_IS_MAIL_LABEL_MANAGER (manager)); + g_return_if_fail (E_IS_MAIL_LABEL_LIST_STORE (list_store)); + + tree_view = GTK_TREE_VIEW (manager->priv->tree_view); + gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (list_store)); + + g_object_notify (G_OBJECT (manager), "list-store"); +} diff --git a/mail/e-mail-label-manager.h b/mail/e-mail-label-manager.h new file mode 100644 index 0000000000..0a36ee27c8 --- /dev/null +++ b/mail/e-mail-label-manager.h @@ -0,0 +1,81 @@ +/* + * e-mail-label-manager.h + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MAIL_LABEL_MANAGER_H +#define E_MAIL_LABEL_MANAGER_H + +#include <gtk/gtk.h> +#include <mail/e-mail-label-list-store.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_LABEL_MANAGER \ + (e_mail_label_manager_get_type ()) +#define E_MAIL_LABEL_MANAGER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_LABEL_MANAGER, EMailLabelManager)) +#define E_MAIL_LABEL_MANAGER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_LABEL_MANAGER, EMailLabelManagerClass)) +#define E_IS_MAIL_LABEL_MANAGER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_LABEL_MANAGER)) +#define E_IS_MAIL_LABEL_MANAGER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_LABEL_MANAGER)) +#define E_MAIL_LABEL_MANAGER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_LABEL_MANAGER, EMailLabelManagerClass)) + +G_BEGIN_DECLS + +typedef struct _EMailLabelManager EMailLabelManager; +typedef struct _EMailLabelManagerClass EMailLabelManagerClass; +typedef struct _EMailLabelManagerPrivate EMailLabelManagerPrivate; + +struct _EMailLabelManager { + GtkTable parent; + EMailLabelManagerPrivate *priv; +}; + +struct _EMailLabelManagerClass { + GtkTableClass parent_class; + + void (*add_label) (EMailLabelManager *manager); + void (*edit_label) (EMailLabelManager *manager); + void (*remove_label) (EMailLabelManager *manager); +}; + +GType e_mail_label_manager_get_type (void); +GtkWidget * e_mail_label_manager_new (void); +void e_mail_label_manager_add_label (EMailLabelManager *manager); +void e_mail_label_manager_edit_label (EMailLabelManager *manager); +void e_mail_label_manager_remove_label + (EMailLabelManager *manager); +EMailLabelListStore * + e_mail_label_manager_get_list_store + (EMailLabelManager *manager); +void e_mail_label_manager_set_list_store + (EMailLabelManager *manager, + EMailLabelListStore *list_store); + +G_END_DECLS + +#endif /* E_MAIL_LABEL_MANAGER_H */ diff --git a/mail/e-mail-label-tree-view.c b/mail/e-mail-label-tree-view.c new file mode 100644 index 0000000000..5675329139 --- /dev/null +++ b/mail/e-mail-label-tree-view.c @@ -0,0 +1,136 @@ +/* + * e-mail-label-tree-view.c + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-label-tree-view.h" + +#include <glib/gi18n.h> +#include "e-mail-label-list-store.h" + +#define E_MAIL_LABEL_TREE_VIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_LABEL_TREE_VIEW, EMailLabelTreeViewPrivate)) + +struct _EMailLabelTreeViewPrivate { + gint placeholder; +}; + +static gpointer parent_class; + +static void +mail_label_tree_view_render_pixbuf (GtkTreeViewColumn *column, + GtkCellRenderer *renderer, + GtkTreeModel *model, + GtkTreeIter *iter, + EMailLabelTreeView *tree_view) +{ + EMailLabelListStore *store; + gchar *stock_id; + + store = E_MAIL_LABEL_LIST_STORE (model); + stock_id = e_mail_label_list_store_get_stock_id (store, iter); + g_object_set (renderer, "stock-id", stock_id, NULL); + g_free (stock_id); +} + +static void +mail_label_tree_view_render_text (GtkTreeViewColumn *column, + GtkCellRenderer *renderer, + GtkTreeModel *model, + GtkTreeIter *iter, + EMailLabelTreeView *tree_view) +{ + EMailLabelListStore *store; + gchar *name; + + store = E_MAIL_LABEL_LIST_STORE (model); + name = e_mail_label_list_store_get_name (store, iter); + g_object_set (renderer, "text", name, NULL); + g_free (name); +} + +static void +mail_label_tree_view_class_init (EMailLabelTreeViewClass *class) +{ + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMailLabelTreeViewPrivate)); +} + +static void +mail_label_tree_view_init (EMailLabelTreeView *tree_view) +{ + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + + tree_view->priv = E_MAIL_LABEL_TREE_VIEW_GET_PRIVATE (tree_view); + + column = gtk_tree_view_column_new (); + renderer = gtk_cell_renderer_pixbuf_new (); + gtk_tree_view_column_set_title (column, _("Color")); + gtk_tree_view_column_pack_start (column, renderer, TRUE); + gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column); + + gtk_tree_view_column_set_cell_data_func ( + column, renderer, (GtkTreeCellDataFunc) + mail_label_tree_view_render_pixbuf, tree_view, NULL); + + column = gtk_tree_view_column_new (); + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_column_set_title (column, _("Name")); + gtk_tree_view_column_pack_start (column, renderer, TRUE); + gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column); + + gtk_tree_view_column_set_cell_data_func ( + column, renderer, (GtkTreeCellDataFunc) + mail_label_tree_view_render_text, tree_view, NULL); +} + +GType +e_mail_label_tree_view_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMailLabelTreeViewClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) mail_label_tree_view_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMailLabelTreeView), + 0, /* n_preallocs */ + (GInstanceInitFunc) mail_label_tree_view_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_TREE_VIEW, "EMailLabelTreeView", + &type_info, 0); + } + + return type; +} + +GtkWidget * +e_mail_label_tree_view_new (void) +{ + return g_object_new (E_TYPE_MAIL_LABEL_TREE_VIEW, NULL); +} diff --git a/mail/e-mail-label-tree-view.h b/mail/e-mail-label-tree-view.h new file mode 100644 index 0000000000..d29ad628a5 --- /dev/null +++ b/mail/e-mail-label-tree-view.h @@ -0,0 +1,66 @@ +/* + * e-mail-label-tree-view.h + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MAIL_LABEL_TREE_VIEW_H +#define E_MAIL_LABEL_TREE_VIEW_H + +#include <gtk/gtk.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_LABEL_TREE_VIEW \ + (e_mail_label_tree_view_get_type ()) +#define E_MAIL_LABEL_TREE_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_LABEL_TREE_VIEW, EMailLabelTreeView)) +#define E_MAIL_LABEL_TREE_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_LABEL_TREE_VIEW, EMailLabelTreeViewClass)) +#define E_IS_MAIL_LABEL_TREE_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_LABEL_TREE_VIEW)) +#define E_IS_MAIL_LABEL_TREE_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_LABEL_TREE_VIEW)) +#define E_MAIL_LABEL_TREE_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_LABEL_TREE_VIEW, EMailLabelTreeViewClass)) + +G_BEGIN_DECLS + +typedef struct _EMailLabelTreeView EMailLabelTreeView; +typedef struct _EMailLabelTreeViewClass EMailLabelTreeViewClass; +typedef struct _EMailLabelTreeViewPrivate EMailLabelTreeViewPrivate; + +struct _EMailLabelTreeView { + GtkTreeView parent; + EMailLabelTreeViewPrivate *priv; +}; + +struct _EMailLabelTreeViewClass { + GtkTreeViewClass parent_class; +}; + +GType e_mail_label_tree_view_get_type (void); +GtkWidget * e_mail_label_tree_view_new (void); + +G_END_DECLS + +#endif /* E_MAIL_LABEL_TREE_VIEW_H */ diff --git a/mail/e-mail-reader-utils.c b/mail/e-mail-reader-utils.c new file mode 100644 index 0000000000..b0c3edff2d --- /dev/null +++ b/mail/e-mail-reader-utils.c @@ -0,0 +1,590 @@ +/* + * e-mail-reader-utils.c + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +/* Miscellaneous utility functions used by EMailReader actions. */ + +#include "e-mail-reader-utils.h" + +#include <glib/gi18n.h> +#include <gtkhtml/gtkhtml.h> +#include <camel/camel-mime-message.h> +#include <camel/camel-vee-folder.h> +#include <camel/camel-vee-store.h> + +#include "e-util/e-error.h" +#include "filter/filter-rule.h" + +#include "mail/e-mail-browser.h" +#include "mail/em-composer-utils.h" +#include "mail/em-format-html-print.h" +#include "mail/em-utils.h" +#include "mail/mail-autofilter.h" +#include "mail/mail-ops.h" +#include "mail/mail-tools.h" +#include "mail/mail-vfolder.h" + +void +e_mail_reader_activate (EMailReader *reader, + const gchar *action_name) +{ + GtkActionGroup *action_group; + GtkAction *action; + + g_return_if_fail (E_IS_MAIL_READER (reader)); + g_return_if_fail (action_name != NULL); + + action_group = e_mail_reader_get_action_group (reader); + action = gtk_action_group_get_action (action_group, action_name); + g_return_if_fail (action != NULL); + + gtk_action_activate (action); +} + +gboolean +e_mail_reader_confirm_delete (EMailReader *reader) +{ + EShell *shell; + EShellModule *shell_module; + EShellSettings *shell_settings; + MessageList *message_list; + CamelFolder *folder; + GtkWidget *check_button; + GtkWidget *content_area; + GtkWidget *dialog; + GtkWindow *window; + const gchar *label; + gboolean prompt_delete_in_vfolder; + gint response; + + /* Remind users what deleting from a search folder does. */ + + g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE); + + message_list = e_mail_reader_get_message_list (reader); + window = e_mail_reader_get_window (reader); + + shell_module = e_mail_reader_get_shell_module (reader); + shell = e_shell_module_get_shell (shell_module); + shell_settings = e_shell_get_shell_settings (shell); + + folder = message_list->folder; + + prompt_delete_in_vfolder = e_shell_settings_get_boolean ( + shell_settings, "mail-prompt-delete-in-vfolder"); + + if (!CAMEL_IS_VEE_STORE (folder->parent_store)) + return TRUE; + + if (!prompt_delete_in_vfolder) + return TRUE; + + dialog = e_error_new ( + window, "mail:ask-delete-vfolder-msg", + folder->full_name, NULL); + + /* XXX e-error should provide a widget layout and API suitable + * for packing additional widgets to the right of the alert + * icon. But for now, screw it. */ + + label = _("Do not ask me again"); + content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); + check_button = gtk_check_button_new_with_label (label); + gtk_box_pack_start ( + GTK_BOX (content_area), check_button, TRUE, TRUE, 6); + + response = gtk_dialog_run (GTK_DIALOG (dialog)); + + if (response == GTK_RESPONSE_OK) + e_shell_settings_set_boolean ( + shell_settings, + "mail-prompt-delete-in-vfolder", + gtk_toggle_button_get_active ( + GTK_TOGGLE_BUTTON (check_button))); + + gtk_widget_destroy (dialog); + + return (response == GTK_RESPONSE_OK); +} + +void +e_mail_reader_mark_as_read (EMailReader *reader, + const gchar *uid) +{ + EMFormatHTMLDisplay *html_display; + MessageList *message_list; + CamelFolder *folder; + guint32 mask, set; + guint32 flags; + + g_return_if_fail (E_IS_MAIL_READER (reader)); + g_return_if_fail (uid != NULL); + + html_display = e_mail_reader_get_html_display (reader); + message_list = e_mail_reader_get_message_list (reader); + + folder = message_list->folder; + flags = camel_folder_get_message_flags (folder, uid); + + if (!(flags & CAMEL_MESSAGE_SEEN)) { + CamelMimeMessage *message; + + message = ((EMFormat *) html_display)->message; + em_utils_handle_receipt (folder, uid, message); + } + + mask = CAMEL_MESSAGE_SEEN; + set = CAMEL_MESSAGE_SEEN; + camel_folder_set_message_flags (folder, uid, mask, set); +} + +guint +e_mail_reader_mark_selected (EMailReader *reader, + guint32 mask, + guint32 set) +{ + MessageList *message_list; + CamelFolder *folder; + GPtrArray *uids; + guint ii; + + g_return_val_if_fail (E_IS_MAIL_READER (reader), 0); + + message_list = e_mail_reader_get_message_list (reader); + + folder = message_list->folder; + if (folder == NULL) + return 0; + + camel_folder_freeze (folder); + uids = message_list_get_selected (message_list); + + for (ii = 0; ii < uids->len; ii++) + camel_folder_set_message_flags ( + folder, uids->pdata[ii], mask, set); + + message_list_free_uids (message_list, uids); + camel_folder_thaw (folder); + + return ii; +} + +guint +e_mail_reader_open_selected (EMailReader *reader) +{ + EShellModule *shell_module; + MessageList *message_list; + CamelFolder *folder; + GtkWindow *window; + GPtrArray *views; + GPtrArray *uids; + const gchar *folder_uri; + guint ii; + + g_return_val_if_fail (E_IS_MAIL_READER (reader), 0); + + message_list = e_mail_reader_get_message_list (reader); + shell_module = e_mail_reader_get_shell_module (reader); + window = e_mail_reader_get_window (reader); + + folder = message_list->folder; + folder_uri = message_list->folder_uri; + uids = message_list_get_selected (message_list); + + if (uids->len >= 10) { + gchar *len_str; + gboolean proceed; + + len_str = g_strdup_printf ("%d", uids->len); + + proceed = em_utils_prompt_user ( + window, "/apps/evolution/mail/prompts/open_many", + "mail:ask-open-many", len_str, NULL); + + g_free (len_str); + + if (!proceed) { + message_list_free_uids (message_list, uids); + return 0; + } + } + + if (em_utils_folder_is_drafts (folder, folder_uri) || + em_utils_folder_is_outbox (folder, folder_uri) || + em_utils_folder_is_templates (folder, folder_uri)) { + em_utils_edit_messages (folder, uids, TRUE); + return uids->len; + } + + views = g_ptr_array_new (); + + /* For vfolders we need to edit the original, not the vfolder copy. */ + for (ii = 0; ii < uids->len; ii++) { + const gchar *uid = uids->pdata[ii]; + CamelFolder *real_folder; + CamelMessageInfo *info; + gchar *real_folder_uri; + gchar *real_uid; + + if (!CAMEL_IS_VEE_FOLDER (folder)) { + g_ptr_array_add (views, g_strdup (uid)); + continue; + } + + info = camel_folder_get_message_info (folder, uid); + if (info == NULL) + continue; + + real_folder = camel_vee_folder_get_location ( + CAMEL_VEE_FOLDER (folder), + (CamelVeeMessageInfo *) info, &real_uid); + real_folder_uri = mail_tools_folder_to_url (real_folder); + + if (em_utils_folder_is_drafts (real_folder, real_folder_uri) || + em_utils_folder_is_outbox (real_folder, real_folder_uri)) { + GPtrArray *edits; + + edits = g_ptr_array_new (); + g_ptr_array_add (edits, real_uid); + em_utils_edit_messages (real_folder, edits, TRUE); + } else { + g_free (real_uid); + g_ptr_array_add (views, g_strdup (uid)); + } + + g_free (real_folder_uri); + } + + for (ii = 0; ii < views->len; ii++) { + const gchar *uid = views->pdata[ii]; + GtkWidget *browser; + + browser = e_mail_browser_new (shell_module); + e_mail_reader_set_folder ( + E_MAIL_READER (browser), folder, folder_uri); + e_mail_reader_set_message ( + E_MAIL_READER (browser), uid, FALSE); + gtk_widget_show (browser); + } + + g_ptr_array_free (views, TRUE); + + message_list_free_uids (message_list, uids); + + return ii; +} + +void +e_mail_reader_print (EMailReader *reader, + GtkPrintOperationAction action) +{ + MessageList *message_list; + EMFormatHTMLDisplay *html_display; + EMFormatHTMLPrint *html_print; + CamelFolder *folder; + GPtrArray *uids; + + g_return_if_fail (E_IS_MAIL_READER (reader)); + + html_display = e_mail_reader_get_html_display (reader); + message_list = e_mail_reader_get_message_list (reader); + + folder = message_list->folder; + g_return_if_fail (folder != NULL); + + /* XXX Learn to handle len > 1. */ + uids = message_list_get_selected (message_list); + if (uids->len != 1) + goto exit; + + html_print = em_format_html_print_new ( + (EMFormatHTML *) html_display, action); + em_format_merge_handler ( + (EMFormat *) html_print, + (EMFormat *) html_display); + em_format_html_print_message (html_print, folder, uids->pdata[0]); + g_object_unref (html_print); + +exit: + message_list_free_uids (message_list, uids); +} + +/* Helper for e_mail_reader_reply_to_message() + * XXX This function belongs in e-html-utils.c */ +static gboolean +html_contains_nonwhitespace (const gchar *html, + gint len) +{ + const gchar *cp; + gunichar uc = 0; + + if (html == NULL || len <= 0) + return FALSE; + + cp = html; + + while (cp != NULL && cp - html < len) { + uc = g_utf8_get_char (cp); + if (uc == 0) + break; + + if (uc == '<') { + /* skip until next '>' */ + uc = g_utf8_get_char (cp); + while (uc != 0 && uc != '>' && cp - html < len) { + cp = g_utf8_next_char (cp); + uc = g_utf8_get_char (cp); + } + if (uc == 0) + break; + } else if (uc == '&') { + /* sequence ' ' is a space */ + if (g_ascii_strncasecmp (cp, " ", 6) == 0) + cp = cp + 5; + else + break; + } else if (!g_unichar_isspace (uc)) + break; + + cp = g_utf8_next_char (cp); + } + + return cp - html < len - 1 && uc != 0; +} + +void +e_mail_reader_reply_to_message (EMailReader *reader, + gint reply_mode) +{ + EMFormatHTMLDisplay *html_display; + MessageList *message_list; + CamelMimeMessage *new_message; + CamelMimeMessage *src_message; + CamelFolder *folder; + GtkWindow *window; + GtkHTML *html; + struct _camel_header_raw *header; + const gchar *uid; + gchar *selection = NULL; + gint length; + + /* This handles quoting only selected text in the reply. If + * nothing is selected or only whitespace is selected, fall + * back to the normal em_utils_reply_to_message(). */ + + g_return_if_fail (E_IS_MAIL_READER (reader)); + + html_display = e_mail_reader_get_html_display (reader); + html = ((EMFormatHTML *) html_display)->html; + + message_list = e_mail_reader_get_message_list (reader); + window = e_mail_reader_get_window (reader); + + folder = message_list->folder; + uid = message_list->cursor_uid; + g_return_if_fail (uid != NULL); + + if (!em_utils_check_user_can_send_mail (window)) + return; + + if (!gtk_html_command (html, "is-selection-active")) + goto whole_message; + + selection = gtk_html_get_selection_html (html, &length); + if (selection == NULL || *selection == '\0') + goto whole_message; + + if (!html_contains_nonwhitespace (selection, length)) + goto whole_message; + + src_message = + CAMEL_MIME_MESSAGE (((EMFormat *) html_display)->message); + new_message = camel_mime_message_new (); + + /* Filter out "content-*" headers. */ + header = CAMEL_MIME_PART (src_message)->headers; + while (header != NULL) { + if (g_ascii_strncasecmp (header->name, "content-", 8) != 0) + camel_medium_add_header ( + CAMEL_MEDIUM (new_message), + header->name, header->value); + } + + camel_mime_part_set_encoding ( + CAMEL_MIME_PART (new_message), + CAMEL_TRANSFER_ENCODING_8BIT); + + camel_mime_part_set_content ( + CAMEL_MIME_PART (new_message), + selection, length, "text/html"); + + em_utils_reply_to_message ( + folder, uid, new_message, reply_mode, NULL); + + g_free (selection); + + return; + +whole_message: + em_utils_reply_to_message ( + folder, uid, NULL, reply_mode, (EMFormat *) html_display); +} + +void +e_mail_reader_select_next_message (EMailReader *reader, + gboolean or_else_previous) +{ + MessageList *message_list; + gboolean hide_deleted; + gboolean success; + + g_return_if_fail (E_IS_MAIL_READER (reader)); + + hide_deleted = e_mail_reader_get_hide_deleted (reader); + message_list = e_mail_reader_get_message_list (reader); + + success = message_list_select ( + message_list, MESSAGE_LIST_SELECT_NEXT, 0, 0); + + if (!success && (hide_deleted || or_else_previous)) + message_list_select ( + message_list, MESSAGE_LIST_SELECT_PREVIOUS, 0, 0); +} + +/* Helper for e_mail_reader_create_filter_from_selected() */ +static void +mail_reader_create_filter_cb (CamelFolder *folder, + const gchar *uid, + CamelMimeMessage *message, + gpointer user_data) +{ + struct { + const gchar *source; + gint type; + } *filter_data = user_data; + + if (message != NULL) + filter_gui_add_from_message ( + message, filter_data->source, filter_data->type); + + g_free (filter_data); +} + +void +e_mail_reader_create_filter_from_selected (EMailReader *reader, + gint filter_type) +{ + MessageList *message_list; + CamelFolder *folder; + const gchar *filter_source; + const gchar *folder_uri; + GPtrArray *uids; + + struct { + const gchar *source; + gint type; + } *filter_data; + + g_return_if_fail (E_IS_MAIL_READER (reader)); + + message_list = e_mail_reader_get_message_list (reader); + + folder = message_list->folder; + folder_uri = message_list->folder_uri; + + if (em_utils_folder_is_sent (folder, folder_uri)) + filter_source = FILTER_SOURCE_OUTGOING; + else if (em_utils_folder_is_outbox (folder, folder_uri)) + filter_source = FILTER_SOURCE_OUTGOING; + else + filter_source = FILTER_SOURCE_INCOMING; + + uids = message_list_get_selected (message_list); + + if (uids->len == 1) { + filter_data = g_malloc (sizeof (*filter_data)); + filter_data->source = filter_source; + filter_data->type = filter_type; + + mail_get_message ( + folder, uids->pdata[0], + mail_reader_create_filter_cb, + filter_data, mail_msg_unordered_push); + } + + em_utils_uids_free (uids); +} + +/* Helper for e_mail_reader_create_vfolder_from_selected() */ +static void +mail_reader_create_vfolder_cb (CamelFolder *folder, + const gchar *uid, + CamelMimeMessage *message, + gpointer user_data) +{ + struct { + gchar *uri; + gint type; + } *vfolder_data = user_data; + + if (message != NULL) + vfolder_gui_add_from_message ( + message, vfolder_data->type, vfolder_data->uri); + + g_free (vfolder_data->uri); + g_free (vfolder_data); +} + +void +e_mail_reader_create_vfolder_from_selected (EMailReader *reader, + gint vfolder_type) +{ + MessageList *message_list; + CamelFolder *folder; + const gchar *folder_uri; + GPtrArray *uids; + + struct { + gchar *uri; + gint type; + } *vfolder_data; + + g_return_if_fail (E_IS_MAIL_READER (reader)); + + message_list = e_mail_reader_get_message_list (reader); + + folder = message_list->folder; + folder_uri = message_list->folder_uri; + + uids = message_list_get_selected (message_list); + + if (uids->len == 1) { + vfolder_data = g_malloc (sizeof (*vfolder_data)); + vfolder_data->uri = g_strdup (folder_uri); + vfolder_data->type = vfolder_type; + + mail_get_message ( + folder, uids->pdata[0], + mail_reader_create_vfolder_cb, + vfolder_data, mail_msg_unordered_push); + } + + em_utils_uids_free (uids); +} diff --git a/mail/e-mail-reader-utils.h b/mail/e-mail-reader-utils.h new file mode 100644 index 0000000000..8ec2235629 --- /dev/null +++ b/mail/e-mail-reader-utils.h @@ -0,0 +1,56 @@ +/* + * e-mail-reader-utils.h + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +/* Miscellaneous utility functions used by EMailReader actions. */ + +#ifndef E_MAIL_READER_UTILS_H +#define E_MAIL_READER_UTILS_H + +#include <mail/e-mail-reader.h> + +G_BEGIN_DECLS + +void e_mail_reader_activate (EMailReader *reader, + const gchar *action_name); +gboolean e_mail_reader_confirm_delete (EMailReader *reader); +void e_mail_reader_mark_as_read (EMailReader *reader, + const gchar *uid); +guint e_mail_reader_mark_selected (EMailReader *reader, + guint32 mask, + guint32 set); +guint e_mail_reader_open_selected (EMailReader *reader); +void e_mail_reader_print (EMailReader *reader, + GtkPrintOperationAction action); +void e_mail_reader_reply_to_message (EMailReader *reader, + gint reply_mode); +void e_mail_reader_select_next_message + (EMailReader *reader, + gboolean or_else_previous); +void e_mail_reader_create_filter_from_selected + (EMailReader *reader, + gint filter_type); +void e_mail_reader_create_vfolder_from_selected + (EMailReader *reader, + gint filter_type); + +G_END_DECLS + +#endif /* E_MAIL_READER_UTILS_H */ diff --git a/mail/e-mail-reader.c b/mail/e-mail-reader.c new file mode 100644 index 0000000000..c5db73c4f9 --- /dev/null +++ b/mail/e-mail-reader.c @@ -0,0 +1,2801 @@ +/* + * e-mail-reader.c + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-reader.h" + +#include <glib/gi18n.h> +#include <gdk/gdkkeysyms.h> +#include <gtkhtml/gtkhtml.h> +#include <gtkhtml/gtkhtml-stream.h> + +#ifdef HAVE_XFREE +#include <X11/XF86keysym.h> +#endif + +#include "e-util/e-util.h" +#include "e-util/e-binding.h" +#include "e-util/gconf-bridge.h" +#include "shell/e-shell.h" +#include "widgets/misc/e-charset-picker.h" +#include "widgets/misc/e-popup-action.h" + +#include "mail/e-mail-browser.h" +#include "mail/e-mail-reader-utils.h" +#include "mail/e-mail-shell-module.h" +#include "mail/em-composer-utils.h" +#include "mail/em-event.h" +#include "mail/em-folder-selector.h" +#include "mail/em-folder-tree.h" +#include "mail/em-utils.h" +#include "mail/mail-autofilter.h" +#include "mail/mail-config.h" +#include "mail/mail-ops.h" + +enum { + CHANGED, + FOLDER_LOADED, + SHOW_SEARCH_BAR, + LAST_SIGNAL +}; + +/* Remembers the previously selected folder when transferring messages. */ +static gchar *default_xfer_messages_uri; + +static guint signals[LAST_SIGNAL]; + +static void +action_mail_add_sender_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + CamelMessageInfo *info; + CamelFolder *folder; + GtkWindow *window; + GPtrArray *uids; + const gchar *address; + + message_list = e_mail_reader_get_message_list (reader); + window = e_mail_reader_get_window (reader); + + folder = message_list->folder; + uids = message_list_get_selected (message_list); + + if (uids->len != 1) + goto exit; + + info = camel_folder_get_message_info (folder, uids->pdata[0]); + if (info == NULL) + goto exit; + + address = camel_message_info_from (info); + if (address == NULL || *address == '\0') + goto exit; + + em_utils_add_address (window, address); + +exit: + em_utils_uids_free (uids); +} + +static void +action_mail_charset_cb (GtkRadioAction *action, + GtkRadioAction *current, + EMailReader *reader) +{ + EMFormatHTMLDisplay *html_display; + const gchar *charset; + + if (action != current) + return; + + html_display = e_mail_reader_get_html_display (reader); + charset = g_object_get_data (G_OBJECT (action), "charset"); + + /* Charset for "Default" action will be NULL. */ + em_format_set_charset (EM_FORMAT (html_display), charset); +} + +static void +action_mail_check_for_junk_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + CamelFolder *folder; + GPtrArray *uids; + + message_list = e_mail_reader_get_message_list (reader); + + folder = message_list->folder; + uids = message_list_get_selected (message_list); + + mail_filter_junk (folder, uids); +} + +static void +action_mail_clipboard_copy_cb (GtkAction *action, + EMailReader *reader) +{ + EMFormatHTMLDisplay *html_display; + GtkHTML *html; + + html_display = e_mail_reader_get_html_display (reader); + html = EM_FORMAT_HTML (html_display)->html; + + gtk_html_copy (html); +} + +static void +action_mail_copy_cb (GtkAction *action, + EMailReader *reader) +{ + EShellModule *shell_module; + MessageList *message_list; + EMFolderTreeModel *model; + CamelFolder *folder; + GtkWidget *folder_tree; + GtkWidget *dialog; + GPtrArray *selected; + const gchar *uri; + + message_list = e_mail_reader_get_message_list (reader); + shell_module = e_mail_reader_get_shell_module (reader); + model = e_mail_shell_module_get_folder_tree_model (shell_module); + + folder_tree = em_folder_tree_new_with_model (model); + selected = message_list_get_selected (message_list); + + folder = message_list->folder; + + em_folder_tree_set_excluded ( + EM_FOLDER_TREE (folder_tree), + EMFT_EXCLUDE_NOSELECT | EMFT_EXCLUDE_VIRTUAL | + EMFT_EXCLUDE_VTRASH); + + dialog = em_folder_selector_new ( + EM_FOLDER_TREE (folder_tree), + EM_FOLDER_SELECTOR_CAN_CREATE, + _("Select Folder"), NULL, _("C_opy")); + + if (default_xfer_messages_uri != NULL) + em_folder_selector_set_selected ( + EM_FOLDER_SELECTOR (dialog), + default_xfer_messages_uri); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) + goto exit; + + uri = em_folder_selector_get_selected_uri ( + EM_FOLDER_SELECTOR (dialog)); + + g_free (default_xfer_messages_uri); + default_xfer_messages_uri = g_strdup (uri); + + if (uri != NULL) { + mail_transfer_messages ( + folder, selected, FALSE, uri, 0, NULL, NULL); + selected = NULL; + } + +exit: + if (selected != NULL) + em_utils_uids_free (selected); + + gtk_widget_destroy (dialog); +} + +static void +action_mail_delete_cb (GtkAction *action, + EMailReader *reader) +{ + guint32 mask = CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_DELETED; + guint32 set = CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_DELETED; + + if (!e_mail_reader_confirm_delete (reader)) + return; + + /* FIXME Verify all selected messages are deletable. + * But handle it by disabling this action. */ + + if (e_mail_reader_mark_selected (reader, mask, set) == 1) + e_mail_reader_select_next_message (reader, FALSE); +} + +static void +action_mail_filter_on_mailing_list_cb (GtkAction *action, + EMailReader *reader) +{ + e_mail_reader_create_filter_from_selected (reader, AUTO_MLIST); +} + +static void +action_mail_filter_on_recipients_cb (GtkAction *action, + EMailReader *reader) +{ + e_mail_reader_create_filter_from_selected (reader, AUTO_TO); +} + +static void +action_mail_filter_on_sender_cb (GtkAction *action, + EMailReader *reader) +{ + e_mail_reader_create_filter_from_selected (reader, AUTO_FROM); +} + +static void +action_mail_filter_on_subject_cb (GtkAction *action, + EMailReader *reader) +{ + e_mail_reader_create_filter_from_selected (reader, AUTO_SUBJECT); +} + +static void +action_mail_filters_apply_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + CamelFolder *folder; + GPtrArray *uids; + + message_list = e_mail_reader_get_message_list (reader); + + folder = message_list->folder; + uids = message_list_get_selected (message_list); + + mail_filter_on_demand (folder, uids); +} + +static void +action_mail_find_cb (GtkAction *action, + EMailReader *reader) +{ + e_mail_reader_show_search_bar (reader); +} + +static void +action_mail_flag_clear_cb (GtkAction *action, + EMailReader *reader) +{ + EMFormatHTMLDisplay *html_display; + MessageList *message_list; + CamelFolder *folder; + GtkWindow *window; + GPtrArray *uids; + + html_display = e_mail_reader_get_html_display (reader); + message_list = e_mail_reader_get_message_list (reader); + window = e_mail_reader_get_window (reader); + + folder = message_list->folder; + uids = message_list_get_selected (message_list); + + em_utils_flag_for_followup_clear (window, folder, uids); + + em_format_redraw (EM_FORMAT (html_display)); +} + +static void +action_mail_flag_completed_cb (GtkAction *action, + EMailReader *reader) +{ + EMFormatHTMLDisplay *html_display; + MessageList *message_list; + CamelFolder *folder; + GtkWindow *window; + GPtrArray *uids; + + html_display = e_mail_reader_get_html_display (reader); + message_list = e_mail_reader_get_message_list (reader); + window = e_mail_reader_get_window (reader); + + folder = message_list->folder; + uids = message_list_get_selected (message_list); + + em_utils_flag_for_followup_completed (window, folder, uids); + + em_format_redraw (EM_FORMAT (html_display)); +} + +static void +action_mail_flag_for_followup_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + CamelFolder *folder; + GtkWindow *window; + GPtrArray *uids; + + message_list = e_mail_reader_get_message_list (reader); + window = e_mail_reader_get_window (reader); + + folder = message_list->folder; + uids = message_list_get_selected (message_list); + + em_utils_flag_for_followup (window, folder, uids); +} + +static void +action_mail_forward_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + CamelFolder *folder; + GtkWindow *window; + GPtrArray *uids; + const gchar *folder_uri; + + message_list = e_mail_reader_get_message_list (reader); + window = e_mail_reader_get_window (reader); + + if (!em_utils_check_user_can_send_mail (window)) + return; + + folder = message_list->folder; + folder_uri = message_list->folder_uri; + uids = message_list_get_selected (message_list); + + em_utils_forward_messages (folder, uids, folder_uri); +} + +static void +action_mail_forward_attached_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + CamelFolder *folder; + GtkWindow *window; + GPtrArray *uids; + const gchar *folder_uri; + + message_list = e_mail_reader_get_message_list (reader); + window = e_mail_reader_get_window (reader); + + if (!em_utils_check_user_can_send_mail (window)) + return; + + folder = message_list->folder; + folder_uri = message_list->folder_uri; + uids = message_list_get_selected (message_list); + + em_utils_forward_attached (folder, uids, folder_uri); +} + +static void +action_mail_forward_inline_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + CamelFolder *folder; + GtkWindow *window; + GPtrArray *uids; + const gchar *folder_uri; + + message_list = e_mail_reader_get_message_list (reader); + window = e_mail_reader_get_window (reader); + + if (!em_utils_check_user_can_send_mail (window)) + return; + + folder = message_list->folder; + folder_uri = message_list->folder_uri; + uids = message_list_get_selected (message_list); + + em_utils_forward_inline (folder, uids, folder_uri); +} + +static void +action_mail_forward_quoted_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + CamelFolder *folder; + GtkWindow *window; + GPtrArray *uids; + const gchar *folder_uri; + + message_list = e_mail_reader_get_message_list (reader); + window = e_mail_reader_get_window (reader); + + if (!em_utils_check_user_can_send_mail (window)) + return; + + folder = message_list->folder; + folder_uri = message_list->folder_uri; + uids = message_list_get_selected (message_list); + + em_utils_forward_quoted (folder, uids, folder_uri); +} + +static void +action_mail_load_images_cb (GtkAction *action, + EMailReader *reader) +{ + EMFormatHTMLDisplay *html_display; + + html_display = e_mail_reader_get_html_display (reader); + + em_format_html_load_images (EM_FORMAT_HTML (html_display)); +} + +static void +action_mail_mark_important_cb (GtkAction *action, + EMailReader *reader) +{ + guint32 mask = CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_DELETED; + guint32 set = CAMEL_MESSAGE_FLAGGED; + + e_mail_reader_mark_selected (reader, mask, set); +} + +static void +action_mail_mark_junk_cb (GtkAction *action, + EMailReader *reader) +{ + guint32 mask = CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_JUNK | + CAMEL_MESSAGE_NOTJUNK | CAMEL_MESSAGE_JUNK_LEARN; + guint32 set = CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_JUNK | + CAMEL_MESSAGE_JUNK_LEARN; + + if (e_mail_reader_mark_selected (reader, mask, set) == 1) + e_mail_reader_select_next_message (reader, TRUE); +} + +static void +action_mail_mark_notjunk_cb (GtkAction *action, + EMailReader *reader) +{ + guint32 mask = CAMEL_MESSAGE_JUNK | CAMEL_MESSAGE_NOTJUNK | + CAMEL_MESSAGE_JUNK_LEARN; + guint32 set = CAMEL_MESSAGE_NOTJUNK | CAMEL_MESSAGE_JUNK_LEARN; + + if (e_mail_reader_mark_selected (reader, mask, set) == 1) + e_mail_reader_select_next_message (reader, TRUE); +} + +static void +action_mail_mark_read_cb (GtkAction *action, + EMailReader *reader) +{ + guint32 mask = CAMEL_MESSAGE_SEEN; + guint32 set = CAMEL_MESSAGE_SEEN; + + e_mail_reader_mark_selected (reader, mask, set); +} + +static void +action_mail_mark_unimportant_cb (GtkAction *action, + EMailReader *reader) +{ + guint32 mask = CAMEL_MESSAGE_FLAGGED; + guint32 set = 0; + + e_mail_reader_mark_selected (reader, mask, set); +} + +static void +action_mail_mark_unread_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + guint32 mask = CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_DELETED; + guint32 set = 0; + + message_list = e_mail_reader_get_message_list (reader); + + e_mail_reader_mark_selected (reader, mask, set); + + if (message_list->seen_id != 0) { + g_source_remove (message_list->seen_id); + message_list->seen_id = 0; + } +} + +static void +action_mail_message_edit_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + CamelFolder *folder; + GtkWindow *window; + GPtrArray *uids; + + window = e_mail_reader_get_window (reader); + message_list = e_mail_reader_get_message_list (reader); + + if (!em_utils_check_user_can_send_mail (window)) + return; + + folder = message_list->folder; + uids = message_list_get_selected (message_list); + + em_utils_edit_messages (folder, uids, FALSE); +} + +static void +action_mail_message_new_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + GtkWindow *window; + + message_list = e_mail_reader_get_message_list (reader); + window = e_mail_reader_get_window (reader); + + if (!em_utils_check_user_can_send_mail (window)) + return; + + em_utils_compose_new_message (message_list->folder_uri); +} + +static void +action_mail_message_open_cb (GtkAction *action, + EMailReader *reader) +{ + e_mail_reader_open_selected (reader); +} + +static void +action_mail_message_post_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + + message_list = e_mail_reader_get_message_list (reader); + + em_utils_post_to_folder (message_list->folder); +} + +static void +action_mail_move_cb (GtkAction *action, + EMailReader *reader) +{ + EShellModule *shell_module; + MessageList *message_list; + EMFolderTreeModel *model; + CamelFolder *folder; + GtkWidget *folder_tree; + GtkWidget *dialog; + GPtrArray *selected; + const gchar *uri; + + message_list = e_mail_reader_get_message_list (reader); + shell_module = e_mail_reader_get_shell_module (reader); + model = e_mail_shell_module_get_folder_tree_model (shell_module); + + folder_tree = em_folder_tree_new_with_model (model); + selected = message_list_get_selected (message_list); + + folder = message_list->folder; + + em_folder_tree_set_excluded ( + EM_FOLDER_TREE (folder_tree), + EMFT_EXCLUDE_NOSELECT | EMFT_EXCLUDE_VIRTUAL | + EMFT_EXCLUDE_VTRASH); + + dialog = em_folder_selector_new ( + EM_FOLDER_TREE (folder_tree), + EM_FOLDER_SELECTOR_CAN_CREATE, + _("Select Folder"), NULL, _("C_opy")); + + if (default_xfer_messages_uri != NULL) + em_folder_selector_set_selected ( + EM_FOLDER_SELECTOR (dialog), + default_xfer_messages_uri); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) + goto exit; + + uri = em_folder_selector_get_selected_uri ( + EM_FOLDER_SELECTOR (dialog)); + + g_free (default_xfer_messages_uri); + default_xfer_messages_uri = g_strdup (uri); + + if (uri != NULL) { + mail_transfer_messages ( + folder, selected, TRUE, uri, 0, NULL, NULL); + selected = NULL; + } + +exit: + if (selected != NULL) + em_utils_uids_free (selected); + + gtk_widget_destroy (dialog); +} + +static void +action_mail_next_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + MessageListSelectDirection direction; + guint32 flags, mask; + + direction = MESSAGE_LIST_SELECT_NEXT; + flags = 0; + mask = 0; + + message_list = e_mail_reader_get_message_list (reader); + message_list_select (message_list, direction, flags, mask); +} + +static void +action_mail_next_important_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + MessageListSelectDirection direction; + guint32 flags, mask; + + direction = MESSAGE_LIST_SELECT_NEXT | MESSAGE_LIST_SELECT_WRAP; + flags = CAMEL_MESSAGE_FLAGGED; + mask = CAMEL_MESSAGE_FLAGGED; + + message_list = e_mail_reader_get_message_list (reader); + message_list_select (message_list, direction, flags, mask); +} + +static void +action_mail_next_thread_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + + message_list = e_mail_reader_get_message_list (reader); + message_list_select_next_thread (message_list); +} + +static void +action_mail_next_unread_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + MessageListSelectDirection direction; + guint32 flags, mask; + + direction = MESSAGE_LIST_SELECT_NEXT | MESSAGE_LIST_SELECT_WRAP; + flags = 0; + mask = CAMEL_MESSAGE_SEEN; + + message_list = e_mail_reader_get_message_list (reader); + message_list_select (message_list, direction, flags, mask); +} + +static void +action_mail_previous_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + MessageListSelectDirection direction; + guint32 flags, mask; + + direction = MESSAGE_LIST_SELECT_PREVIOUS; + flags = 0; + mask = 0; + + message_list = e_mail_reader_get_message_list (reader); + message_list_select (message_list, direction, flags, mask); +} + +static void +action_mail_previous_important_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + MessageListSelectDirection direction; + guint32 flags, mask; + + direction = MESSAGE_LIST_SELECT_PREVIOUS | MESSAGE_LIST_SELECT_WRAP; + flags = CAMEL_MESSAGE_FLAGGED; + mask = CAMEL_MESSAGE_FLAGGED; + + message_list = e_mail_reader_get_message_list (reader); + message_list_select (message_list, direction, flags, mask); +} + +static void +action_mail_previous_unread_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + MessageListSelectDirection direction; + guint32 flags, mask; + + direction = MESSAGE_LIST_SELECT_PREVIOUS | MESSAGE_LIST_SELECT_WRAP; + flags = 0; + mask = CAMEL_MESSAGE_SEEN; + + message_list = e_mail_reader_get_message_list (reader); + message_list_select (message_list, direction, flags, mask); +} + +static void +action_mail_print_cb (GtkAction *action, + EMailReader *reader) +{ + GtkPrintOperationAction print_action; + + print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; + e_mail_reader_print (reader, print_action); +} + +static void +action_mail_print_preview_cb (GtkAction *action, + EMailReader *reader) +{ + GtkPrintOperationAction print_action; + + print_action = GTK_PRINT_OPERATION_ACTION_PREVIEW; + e_mail_reader_print (reader, print_action); +} + +static void +action_mail_redirect_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + CamelFolder *folder; + GtkWindow *window; + const gchar *uid; + + message_list = e_mail_reader_get_message_list (reader); + window = e_mail_reader_get_window (reader); + + folder = message_list->folder; + uid = message_list->cursor_uid; + g_return_if_fail (uid != NULL); + + if (!em_utils_check_user_can_send_mail (window)) + return; + + em_utils_redirect_message_by_uid (folder, uid); +} + +static void +action_mail_reply_all_cb (GtkAction *action, + EMailReader *reader) +{ + e_mail_reader_reply_to_message (reader, REPLY_MODE_ALL); +} + +static void +action_mail_reply_list_cb (GtkAction *action, + EMailReader *reader) +{ + e_mail_reader_reply_to_message (reader, REPLY_MODE_LIST); +} + +static void +action_mail_reply_post_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + CamelFolder *folder; + GtkWindow *window; + const gchar *uid; + + message_list = e_mail_reader_get_message_list (reader); + window = e_mail_reader_get_window (reader); + + folder = message_list->folder; + uid = message_list->cursor_uid; + g_return_if_fail (uid != NULL); + + if (!em_utils_check_user_can_send_mail (window)) + return; + + em_utils_post_reply_to_message_by_uid (folder, uid); +} + +static void +action_mail_reply_sender_cb (GtkAction *action, + EMailReader *reader) +{ + e_mail_reader_reply_to_message (reader, REPLY_MODE_SENDER); +} + +static void +action_mail_save_as_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + CamelFolder *folder; + GtkWindow *window; + GPtrArray *uids; + + message_list = e_mail_reader_get_message_list (reader); + window = e_mail_reader_get_window (reader); + + folder = message_list->folder; + uids = message_list_get_selected (message_list); + + em_utils_save_messages (window, folder, uids); +} + +static void +action_mail_search_folder_from_mailing_list_cb (GtkAction *action, + EMailReader *reader) +{ + e_mail_reader_create_vfolder_from_selected (reader, AUTO_MLIST); +} + +static void +action_mail_search_folder_from_recipients_cb (GtkAction *action, + EMailReader *reader) +{ + e_mail_reader_create_vfolder_from_selected (reader, AUTO_TO); +} + +static void +action_mail_search_folder_from_sender_cb (GtkAction *action, + EMailReader *reader) +{ + e_mail_reader_create_vfolder_from_selected (reader, AUTO_FROM); +} + +static void +action_mail_search_folder_from_subject_cb (GtkAction *action, + EMailReader *reader) +{ + e_mail_reader_create_vfolder_from_selected (reader, AUTO_SUBJECT); +} + +static void +action_mail_select_all_cb (GtkAction *action, + EMailReader *reader) +{ + EMFormatHTMLDisplay *html_display; + GtkHTML *html; + const gchar *action_name; + gboolean selection_active; + + html_display = e_mail_reader_get_html_display (reader); + html = EM_FORMAT_HTML (html_display)->html; + + gtk_html_select_all (html); + + action_name = "mail-clipboard-copy"; + action = e_mail_reader_get_action (reader, action_name); + selection_active = gtk_html_command (html, "is-selection-active"); + gtk_action_set_sensitive (action, selection_active); +} + +static void +action_mail_show_all_headers_cb (GtkToggleAction *action, + EMailReader *reader) +{ + EMFormatHTMLDisplay *html_display; + em_format_mode_t mode; + + html_display = e_mail_reader_get_html_display (reader); + + if (gtk_toggle_action_get_active (action)) + mode = EM_FORMAT_ALLHEADERS; + else + mode = EM_FORMAT_NORMAL; + + em_format_set_mode (EM_FORMAT (html_display), mode); +} + +static void +action_mail_show_source_cb (GtkAction *action, + EMailReader *reader) +{ + EMFormatHTMLDisplay *html_display; + EShellModule *shell_module; + MessageList *message_list; + CamelFolder *folder; + GtkWidget *browser; + GPtrArray *uids; + const gchar *folder_uri; + + message_list = e_mail_reader_get_message_list (reader); + shell_module = e_mail_reader_get_shell_module (reader); + + folder = message_list->folder; + folder_uri = message_list->folder_uri; + uids = message_list_get_selected (message_list); + g_return_if_fail (uids->len > 0); + + browser = e_mail_browser_new (shell_module); + reader = E_MAIL_READER (browser); + html_display = e_mail_reader_get_html_display (reader); + em_format_set_mode (EM_FORMAT (html_display), EM_FORMAT_SOURCE); + e_mail_reader_set_folder (reader, folder, folder_uri); + e_mail_reader_set_message (reader, uids->pdata[0], FALSE); + gtk_widget_show (browser); + + message_list_free_uids (message_list, uids); +} + +static void +action_mail_toggle_important_cb (GtkAction *action, + EMailReader *reader) +{ + MessageList *message_list; + CamelFolder *folder; + GPtrArray *uids; + guint ii; + + message_list = e_mail_reader_get_message_list (reader); + + folder = message_list->folder; + uids = message_list_get_selected (message_list); + + camel_folder_freeze (folder); + + for (ii = 0; ii < uids->len; ii++) { + guint32 flags; + + flags = camel_folder_get_message_flags ( + folder, uids->pdata[ii]); + flags ^= CAMEL_MESSAGE_FLAGGED; + if (flags & CAMEL_MESSAGE_FLAGGED) + flags &= ~CAMEL_MESSAGE_DELETED; + camel_folder_set_message_flags ( + folder, uids->pdata[ii], CAMEL_MESSAGE_FLAGGED | + CAMEL_MESSAGE_DELETED, flags); + } + + camel_folder_thaw (folder); + + message_list_free_uids (message_list, uids); +} + +static void +action_mail_undelete_cb (GtkAction *action, + EMailReader *reader) +{ + guint32 mask = CAMEL_MESSAGE_DELETED; + guint32 set = 0; + + e_mail_reader_mark_selected (reader, mask, set); +} + +static void +action_mail_uri_call_to_cb (GtkAction *action, + EMailReader *reader) +{ + /* FIXME */ + g_print ("Action: %s\n", gtk_action_get_name (GTK_ACTION (action))); +} + +static void +action_mail_uri_copy_cb (GtkAction *action, + EMailReader *reader) +{ + /* FIXME */ + g_print ("Action: %s\n", gtk_action_get_name (GTK_ACTION (action))); +} + +static void +action_mail_uri_copy_address_cb (GtkAction *action, + EMailReader *reader) +{ + /* FIXME */ + g_print ("Action: %s\n", gtk_action_get_name (GTK_ACTION (action))); +} + +static void +action_mail_uri_to_search_folder_recipient_cb (GtkAction *action, + EMailReader *reader) +{ + /* FIXME */ + g_print ("Action: %s\n", gtk_action_get_name (GTK_ACTION (action))); +} + +static void +action_mail_uri_to_search_folder_sender_cb (GtkAction *action, + EMailReader *reader) +{ + /* FIXME */ + g_print ("Action: %s\n", gtk_action_get_name (GTK_ACTION (action))); +} + +static void +action_mail_zoom_100_cb (GtkAction *action, + EMailReader *reader) +{ + EMFormatHTMLDisplay *html_display; + GtkHTML *html; + + html_display = e_mail_reader_get_html_display (reader); + html = EM_FORMAT_HTML (html_display)->html; + + gtk_html_zoom_reset (html); +} + +static void +action_mail_zoom_in_cb (GtkAction *action, + EMailReader *reader) +{ + EMFormatHTMLDisplay *html_display; + GtkHTML *html; + + html_display = e_mail_reader_get_html_display (reader); + html = EM_FORMAT_HTML (html_display)->html; + + gtk_html_zoom_out (html); +} + +static void +action_mail_zoom_out_cb (GtkAction *action, + EMailReader *reader) +{ + EMFormatHTMLDisplay *html_display; + GtkHTML *html; + + html_display = e_mail_reader_get_html_display (reader); + html = EM_FORMAT_HTML (html_display)->html; + + gtk_html_zoom_out (html); +} + +static GtkActionEntry mail_reader_entries[] = { + + { "mail-add-sender", + NULL, + N_("A_dd Sender to Address Book"), + NULL, + N_("Add sender to address book"), + G_CALLBACK (action_mail_add_sender_cb) }, + + { "mail-check-for-junk", + "mail-mark-junk", + N_("Check for _Junk"), + NULL, + N_("Filter the selected messages for junk status"), + G_CALLBACK (action_mail_check_for_junk_cb) }, + + { "mail-clipboard-copy", + GTK_STOCK_COPY, + NULL, + NULL, + N_("Copy selected messages to the clipboard"), + G_CALLBACK (action_mail_clipboard_copy_cb) }, + + { "mail-copy", + "mail-copy", + N_("_Copy to Folder..."), + "<Shift><Control>y", + N_("Copy selected messages to another folder"), + G_CALLBACK (action_mail_copy_cb) }, + + { "mail-delete", + "user-trash", + N_("_Delete Message"), + "<Control>d", + N_("Mark the selected messages for deletion"), + G_CALLBACK (action_mail_delete_cb) }, + + { "mail-filter-on-mailing-list", + NULL, + N_("Filter on Mailing _List..."), + NULL, + N_("Create a rule to filter messages to this mailing list"), + G_CALLBACK (action_mail_filter_on_mailing_list_cb) }, + + { "mail-filter-on-recipients", + NULL, + N_("Filter on _Recipients..."), + NULL, + N_("Create a rule to filter messages to these recipients"), + G_CALLBACK (action_mail_filter_on_recipients_cb) }, + + { "mail-filter-on-sender", + NULL, + N_("Filter on Se_nder..."), + NULL, + N_("Create a rule to filter messages from this sender"), + G_CALLBACK (action_mail_filter_on_sender_cb) }, + + { "mail-filter-on-subject", + NULL, + N_("Filter on _Subject..."), + NULL, + N_("Create a rule to filter messages with this subject"), + G_CALLBACK (action_mail_filter_on_subject_cb) }, + + { "mail-filters-apply", + "stock_mail-filters-apply", + N_("A_pply Filters"), + "<Control>y", + N_("Apply filter rules to the selected messages"), + G_CALLBACK (action_mail_filters_apply_cb) }, + + { "mail-find", + GTK_STOCK_FIND, + N_("_Find in Message..."), + "<Shift><Control>f", + N_("Search for text in the body of the displayed message"), + G_CALLBACK (action_mail_find_cb) }, + + { "mail-flag-clear", + NULL, + N_("_Clear Flag"), + NULL, + N_("Remove the follow-up flag from the selected messages"), + G_CALLBACK (action_mail_flag_clear_cb) }, + + { "mail-flag-completed", + NULL, + N_("_Flag Completed"), + NULL, + N_("Set the follow-up flag to completed on the selected messages"), + G_CALLBACK (action_mail_flag_completed_cb) }, + + { "mail-flag-for-followup", + "stock_mail-flag-for-followup", + N_("Follow _Up..."), + "<Shift><Control>g", + N_("Flag the selected messages for follow-up"), + G_CALLBACK (action_mail_flag_for_followup_cb) }, + + { "mail-forward", + "mail-forward", + N_("_Forward"), + "<Control>f", + N_("Forward the selected message to someone"), + G_CALLBACK (action_mail_forward_cb) }, + + { "mail-forward-attached", + NULL, + N_("_Attached"), + NULL, + N_("Forward the selected message to someone as an attachment"), + G_CALLBACK (action_mail_forward_attached_cb) }, + + { "mail-forward-inline", + NULL, + N_("_Inline"), + NULL, + N_("Forward the selected message in the body of a new message"), + G_CALLBACK (action_mail_forward_inline_cb) }, + + { "mail-forward-quoted", + NULL, + N_("_Quoted"), + NULL, + N_("Forward the selected message quoted like a reply"), + G_CALLBACK (action_mail_forward_quoted_cb) }, + + { "mail-load-images", + "image-x-generic", + N_("_Load Images"), + "<Control>i", + N_("Force images in HTML mail to be loaded"), + G_CALLBACK (action_mail_load_images_cb) }, + + { "mail-mark-important", + "mail-mark-important", + N_("_Important"), + NULL, + N_("Mark the selected messages as important"), + G_CALLBACK (action_mail_mark_important_cb) }, + + { "mail-mark-junk", + "mail-mark-junk", + N_("_Junk"), + "<Control>j", + N_("Mark the selected messages as junk"), + G_CALLBACK (action_mail_mark_junk_cb) }, + + { "mail-mark-notjunk", + "mail-mark-notjunk", + N_("_Not Junk"), + "<Shift><Control>j", + N_("Mark the selected messasges as not being junk"), + G_CALLBACK (action_mail_mark_notjunk_cb) }, + + { "mail-mark-read", + "mail-mark-read", + N_("_Read"), + "<Control>k", + N_("Mark the selected messages as having been read"), + G_CALLBACK (action_mail_mark_read_cb) }, + + { "mail-mark-unimportant", + NULL, + N_("Uni_mportant"), + NULL, + N_("Mark the selected messages as unimportant"), + G_CALLBACK (action_mail_mark_unimportant_cb) }, + + { "mail-mark-unread", + "mail-mark-unread", + N_("_Unread"), + "<Shift><Control>k", + N_("Mark the selected messages as not having been read"), + G_CALLBACK (action_mail_mark_unread_cb) }, + + { "mail-message-edit", + NULL, + N_("_Edit as New Message..."), + NULL, + N_("Open the selected messages in the composer for editing"), + G_CALLBACK (action_mail_message_edit_cb) }, + + { "mail-message-new", + "mail-message-new", + N_("Compose _New Message"), + "<Shift><Control>m", + N_("Open a window for composing a mail message"), + G_CALLBACK (action_mail_message_new_cb) }, + + { "mail-message-open", + NULL, + N_("_Open in New Window"), + "<Control>o", + N_("Open the selected messages in a new window"), + G_CALLBACK (action_mail_message_open_cb) }, + + { "mail-message-post", + NULL, + N_("Pos_t New Message to Folder"), + NULL, + N_("Post a message to a public folder"), + G_CALLBACK (action_mail_message_post_cb) }, + + { "mail-move", + "mail-move", + N_("_Move to Folder..."), + "<Shift><Control>v", + N_("Move selected messages to another folder"), + G_CALLBACK (action_mail_move_cb) }, + + { "mail-next", + GTK_STOCK_GO_FORWARD, + N_("_Next Message"), + "<Control>Page_Down", + N_("Display the next message"), + G_CALLBACK (action_mail_next_cb) }, + + { "mail-next-important", + NULL, + N_("Next _Important Message"), + NULL, + N_("Display the next important message"), + G_CALLBACK (action_mail_next_important_cb) }, + + { "mail-next-thread", + NULL, + N_("Next _Thread"), + NULL, + N_("Display the next thread"), + G_CALLBACK (action_mail_next_thread_cb) }, + + { "mail-next-unread", + NULL, + N_("Next _Unread Message"), + "<Control>bracketright", + N_("Display the next unread message"), + G_CALLBACK (action_mail_next_unread_cb) }, + + { "mail-previous", + GTK_STOCK_GO_BACK, + N_("_Previous Message"), + "<Control>Page_Up", + N_("Display the previous message"), + G_CALLBACK (action_mail_previous_cb) }, + + { "mail-previous-important", + NULL, + N_("Pr_evious Important Message"), + NULL, + N_("Display the previous important message"), + G_CALLBACK (action_mail_previous_important_cb) }, + + { "mail-previous-unread", + NULL, + N_("P_revious Unread Message"), + "<Control>bracketleft", + N_("Display the previous unread message"), + G_CALLBACK (action_mail_previous_unread_cb) }, + + { "mail-print", + GTK_STOCK_PRINT, + NULL, + "<Control>p", + N_("Print this message"), + G_CALLBACK (action_mail_print_cb) }, + + { "mail-print-preview", + GTK_STOCK_PRINT_PREVIEW, + NULL, + NULL, + N_("Preview the message to be printed"), + G_CALLBACK (action_mail_print_preview_cb) }, + + { "mail-redirect", + NULL, + N_("Re_direct"), + NULL, + N_("Redirect (bounce) the selected message to someone"), + G_CALLBACK (action_mail_redirect_cb) }, + + { "mail-reply-all", + "mail-reply-all", + N_("Reply to _All"), + "<Shift><Control>r", + N_("Compose a reply to all the recipients of the selected message"), + G_CALLBACK (action_mail_reply_all_cb) }, + + { "mail-reply-list", + NULL, + N_("Reply to _List"), + "<Control>l", + N_("Compose a reply to the mailing list of the selected message"), + G_CALLBACK (action_mail_reply_list_cb) }, + + { "mail-reply-post", + NULL, + N_("Post a Repl_y"), + NULL, + N_("Post a reply to a message in a public folder"), + G_CALLBACK (action_mail_reply_post_cb) }, + + { "mail-reply-sender", + "mail-reply-sender", + N_("_Reply to Sender"), + "<Control>r", + N_("Compose a reply to the sender of the selected message"), + G_CALLBACK (action_mail_reply_sender_cb) }, + + { "mail-save-as", + GTK_STOCK_SAVE_AS, + N_("_Save as mbox..."), + NULL, + N_("Save selected messages as an mbox file"), + G_CALLBACK (action_mail_save_as_cb) }, + + { "mail-search-folder-from-mailing-list", + NULL, + N_("Search Folder from Mailing _List..."), + NULL, + N_("Create a search folder for this mailing list"), + G_CALLBACK (action_mail_search_folder_from_mailing_list_cb) }, + + { "mail-search-folder-from-recipients", + NULL, + N_("Search Folder from Recipien_ts..."), + NULL, + N_("Create a search folder for these recipients"), + G_CALLBACK (action_mail_search_folder_from_recipients_cb) }, + + { "mail-search-folder-from-sender", + NULL, + N_("Search Folder from Sen_der..."), + NULL, + N_("Create a search folder for this sender"), + G_CALLBACK (action_mail_search_folder_from_sender_cb) }, + + { "mail-search-folder-from-subject", + NULL, + N_("Search Folder from S_ubject..."), + NULL, + N_("Create a search folder for this subject"), + G_CALLBACK (action_mail_search_folder_from_subject_cb) }, + + { "mail-select-all", + NULL, + N_("Select _All Text"), + "<Shift><Control>x", + N_("Select all the text in a message"), + G_CALLBACK (action_mail_select_all_cb) }, + + { "mail-show-source", + NULL, + N_("_Message Source"), + "<Control>u", + N_("Show the raw email source of the message"), + G_CALLBACK (action_mail_show_source_cb) }, + + { "mail-toggle-important", + NULL, + NULL, /* No menu item; key press only */ + NULL, + NULL, + G_CALLBACK (action_mail_toggle_important_cb) }, + + { "mail-undelete", + NULL, + N_("_Undelete Message"), + "<Shift><Control>d", + N_("Undelete the selected messages"), + G_CALLBACK (action_mail_undelete_cb) }, + + { "mail-uri-call-to", + NULL, + N_("C_all To..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_mail_uri_call_to_cb) }, + + { "mail-uri-copy", + NULL, + N_("_Copy Link Location"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_mail_uri_copy_cb) }, + + { "mail-uri-copy-address", + GTK_STOCK_COPY, + N_("Copy _Email Address"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_mail_uri_copy_address_cb) }, + + { "mail-uri-to-search-folder-recipient", + NULL, + N_("_To This Address"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_mail_uri_to_search_folder_recipient_cb) }, + + { "mail-uri-to-search-folder-sender", + NULL, + N_("_From This Address"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_mail_uri_to_search_folder_sender_cb) }, + + { "mail-zoom-100", + GTK_STOCK_ZOOM_100, + N_("_Normal Size"), + "<Control>0", + N_("Reset the text to its original size"), + G_CALLBACK (action_mail_zoom_100_cb) }, + + { "mail-zoom-in", + GTK_STOCK_ZOOM_IN, + N_("_Zoom In"), + "<Control>plus", + N_("Increase the text size"), + G_CALLBACK (action_mail_zoom_in_cb) }, + + { "mail-zoom-out", + GTK_STOCK_ZOOM_OUT, + N_("Zoom _Out"), + "<Control>minus", + N_("Decrease the text size"), + G_CALLBACK (action_mail_zoom_out_cb) }, + + /*** Menus ***/ + + { "mail-create-rule-menu", + NULL, + N_("Create R_ule"), + NULL, + NULL, + NULL }, + + { "mail-encoding-menu", + NULL, + N_("Ch_aracter Encoding"), + NULL, + NULL, + NULL }, + + { "mail-forward-as-menu", + NULL, + N_("F_orward As..."), + NULL, + NULL, + NULL }, + + { "mail-goto-menu", + GTK_STOCK_JUMP_TO, + N_("_Go To"), + NULL, + NULL, + NULL }, + + { "mail-mark-as-menu", + NULL, + N_("Mar_k As"), + NULL, + NULL, + NULL }, + + { "mail-message-menu", + NULL, + N_("_Message"), + NULL, + NULL, + NULL }, + + { "mail-uri-to-search-folder-menu", + NULL, + N_("Create _Search Folder"), + NULL, + NULL, + NULL }, + + { "mail-zoom-menu", + NULL, + N_("_Zoom"), + NULL, + NULL, + NULL } +}; + +static EPopupActionEntry mail_reader_popup_entries[] = { + + { "mail-popup-copy", + NULL, + "mail-copy" }, + + { "mail-popup-delete", + NULL, + "mail-delete" }, + + { "mail-popup-flag-for-followup", + N_("Mark for Follo_w Up..."), + "mail-flag-for-followup" }, + + { "mail-popup-forward", + NULL, + "mail-forward" }, + + { "mail-popup-mark-important", + N_("Mark as _Important"), + "mail-mark-important" }, + + { "mail-popup-mark-junk", + N_("Mark as _Junk"), + "mail-mark-junk" }, + + { "mail-popup-mark-notjunk", + N_("Mark as _Not Junk"), + "mail-mark-notjunk" }, + + { "mail-popup-mark-read", + N_("Mark as _Read"), + "mail-mark-read" }, + + { "mail-popup-mark-unimportant", + N_("Mark as Uni_mportant"), + "mail-mark-unimportant" }, + + { "mail-popup-mark-unread", + N_("Mark as _Unread"), + "mail-mark-unread" }, + + { "mail-popup-message-edit", + NULL, + "mail-message-edit" }, + + { "mail-popup-move", + NULL, + "mail-move" }, + + { "mail-popup-print", + NULL, + "mail-print" }, + + { "mail-popup-reply-all", + NULL, + "mail-reply-all" }, + + { "mail-popup-reply-sender", + NULL, + "mail-reply-sender" }, + + { "mail-popup-save-as", + NULL, + "mail-save-as" }, + + { "mail-popup-undelete", + NULL, + "mail-undelete" } +}; + +static GtkToggleActionEntry mail_reader_toggle_entries[] = { + + { "mail-caret-mode", + NULL, + N_("_Caret Mode"), + "F7", + N_("Show a blinking cursor in the body of displayed messages"), + NULL, /* No callback required */ + FALSE }, + + { "mail-show-all-headers", + NULL, + N_("All Message _Headers"), + NULL, + N_("Show messages with all email headers"), + G_CALLBACK (action_mail_show_all_headers_cb), + FALSE } +}; + +static gboolean +mail_reader_html_button_release_event_cb (EMailReader *reader, + GdkEventButton *button, + GtkHTML *html) +{ + GtkAction *action; + const gchar *action_name; + gboolean selection_active; + + action_name = "mail-clipboard-copy"; + action = e_mail_reader_get_action (reader, action_name); + selection_active = gtk_html_command (html, "is-selection-active"); + gtk_action_set_sensitive (action, selection_active); + + return FALSE; +} + +static void +mail_reader_double_click_cb (EMailReader *reader, + gint row, + ETreePath path, + gint col, + GdkEvent *event) +{ + /* Ignore double clicks on columns that handle their own state. */ + if (MESSAGE_LIST_COLUMN_IS_ACTIVE (col)) + return; + + e_mail_reader_activate (reader, "mail-message-open"); +} + +static gboolean +mail_reader_key_press_event_cb (EMailReader *reader, + GdkEventKey *event) +{ + const gchar *action_name; + + if ((event->state & GDK_CONTROL_MASK) != 0) + goto ctrl; + + /* <keyval> alone */ + switch (event->keyval) { + case GDK_Delete: + case GDK_KP_Delete: + action_name = "mail-delete"; + break; + + case GDK_Return: + case GDK_KP_Enter: + case GDK_ISO_Enter: + action_name = "mail-message-open"; + break; + + case GDK_period: + action_name = "mail-next-unread"; + break; + + case GDK_comma: + action_name = "mail-previous-unread"; + break; + +#ifdef HAVE_XFREE + case XF86XK_Reply: + action_name = "mail-reply-all"; + break; + + case XF86XK_MailForward: + action_name = "mail-forward"; + break; +#endif + + case '!': + action_name = "mail-toggle-important"; + break; + + default: + return FALSE; + } + + goto exit; + +ctrl: + + /* Ctrl + <keyval> */ + switch (event->keyval) { + case GDK_period: + action_name = "mail-next-unread"; + break; + + case GDK_comma: + action_name = "mail-previous-unread"; + break; + + default: + return FALSE; + } + +exit: + e_mail_reader_activate (reader, action_name); + + return TRUE; +} + +static gint +mail_reader_key_press_cb (EMailReader *reader, + gint row, + ETreePath path, + gint col, + GdkEvent *event) +{ + return mail_reader_key_press_event_cb (reader, &event->key); +} + +static gboolean +mail_reader_message_read_cb (EMailReader *reader) +{ + MessageList *message_list; + const gchar *uid; + + message_list = e_mail_reader_get_message_list (reader); + + uid = g_object_get_data (G_OBJECT (reader), "mark-read-uid"); + g_return_val_if_fail (uid != NULL, FALSE); + + if (g_strcmp0 (message_list->cursor_uid, uid) == 0) + e_mail_reader_mark_as_read (reader, uid); + + return FALSE; +} + +static void +mail_reader_message_loaded_cb (CamelFolder *folder, + const gchar *message_uid, + CamelMimeMessage *message, + gpointer user_data, + CamelException *ex) +{ + EMailReader *reader = user_data; + EMFormatHTMLDisplay *html_display; + MessageList *message_list; + EShellModule *shell_module; + EShellSettings *shell_settings; + EShell *shell; + EMEvent *event; + EMEventTargetMessage *target; + gboolean mark_read; + gint timeout_interval; + + html_display = e_mail_reader_get_html_display (reader); + message_list = e_mail_reader_get_message_list (reader); + + shell_module = e_mail_reader_get_shell_module (reader); + shell = e_shell_module_get_shell (shell_module); + shell_settings = e_shell_get_shell_settings (shell); + + /* If the user picked a different message in the time it took + * to fetch this message, then don't bother rendering it. */ + if (g_strcmp0 (message_list->cursor_uid, message_uid) != 0) + return; + + /** @Event: message.reading + * @Title: Viewing a message + * @Target: EMEventTargetMessage + * + * message.reading is emitted whenever a user views a message. + */ + event = em_event_peek (); + target = em_event_target_new_message ( + event, folder, message, message_uid, 0); + e_event_emit ( + (EEvent *) event, "message.reading", + (EEventTarget *) target); + + em_format_format ( + EM_FORMAT (html_display), folder, message_uid, message); + + /* Reset the shell view icon. */ + e_shell_event (shell, "mail-icon", "evolution-mail"); + + /* Determine whether to mark the message as read. */ + mark_read = e_shell_settings_get_boolean ( + shell_settings, "mail-mark-seen"); + timeout_interval = e_shell_settings_get_int ( + shell_settings, "mail-mark-seen-timeout"); + + g_object_set_data_full ( + G_OBJECT (reader), "mark-read-uid", + g_strdup (message_uid), (GDestroyNotify) g_free); + + if (message_list->seen_id > 0) + g_source_remove (message_list->seen_id); + + if (mark_read) { + message_list->seen_id = g_timeout_add ( + timeout_interval, (GSourceFunc) + mail_reader_message_read_cb, reader); + + } else if (camel_exception_is_set (ex)) { + GtkHTMLStream *stream; + + /* Display the error inline and clear the exception. */ + stream = gtk_html_begin ( + EM_FORMAT_HTML (html_display)->html); + gtk_html_stream_printf ( + stream, "<h2>%s</h2><p>%s</p>", + _("Unable to retrieve message"), + ex->desc); + gtk_html_stream_close (stream, GTK_HTML_STREAM_OK); + camel_exception_clear (ex); + } + + e_mail_reader_update_actions (reader); + + /* We referenced this in the call to mail_get_messagex(). */ + g_object_unref (reader); +} + +static gboolean +mail_reader_message_selected_timeout_cb (EMailReader *reader) +{ + EMFormatHTMLDisplay *html_display; + MessageList *message_list; + const gchar *cursor_uid; + const gchar *format_uid; + const gchar *key; + + html_display = e_mail_reader_get_html_display (reader); + message_list = e_mail_reader_get_message_list (reader); + + cursor_uid = message_list->cursor_uid; + format_uid = EM_FORMAT (html_display)->uid; + + if (cursor_uid != NULL) { + if (g_strcmp0 (cursor_uid, format_uid) != 0) + mail_get_messagex ( + message_list->folder, cursor_uid, + mail_reader_message_loaded_cb, + g_object_ref (reader), + mail_msg_fast_ordered_push); + } else + em_format_format (EM_FORMAT (html_display), NULL, NULL, NULL); + + key = "message-selected-timeout"; + g_object_set_data (G_OBJECT (reader), key, NULL); + + return FALSE; +} + +static void +mail_reader_message_selected_cb (EMailReader *reader, + const gchar *uid) +{ + const gchar *key; + guint source_id; + gpointer data; + + /* XXX This is kludgy, but we have no other place to store + * timeout state information. */ + + key = "message-selected-timeout"; + data = g_object_get_data (G_OBJECT (reader), key); + source_id = GPOINTER_TO_UINT (data); + + if (source_id > 0) + g_source_remove (source_id); + + source_id = g_timeout_add ( + 100, (GSourceFunc) + mail_reader_message_selected_timeout_cb, reader); + + data = GUINT_TO_POINTER (source_id); + g_object_set_data (G_OBJECT (reader), key, data); + + e_mail_reader_changed (reader); +} + +static void +mail_reader_emit_folder_loaded (EMailReader *reader) +{ + g_signal_emit (reader, signals[FOLDER_LOADED], 0); +} + +static void +mail_reader_set_folder (EMailReader *reader, + CamelFolder *folder, + const gchar *folder_uri) +{ + EMFormatHTMLDisplay *html_display; + MessageList *message_list; + gboolean outgoing; + + html_display = e_mail_reader_get_html_display (reader); + message_list = e_mail_reader_get_message_list (reader); + + outgoing = folder != NULL && folder_uri != NULL && ( + em_utils_folder_is_drafts (folder, folder_uri) || + em_utils_folder_is_outbox (folder, folder_uri) || + em_utils_folder_is_sent (folder, folder_uri)); + + if (message_list->folder != NULL) + mail_sync_folder (message_list->folder, NULL, NULL); + + em_format_format (EM_FORMAT (html_display), NULL, NULL, NULL); + message_list_set_folder (message_list, folder, folder_uri, outgoing); + + mail_reader_emit_folder_loaded (reader); +} + +static void +mail_reader_set_message (EMailReader *reader, + const gchar *uid, + gboolean mark_read) +{ + MessageList *message_list; + + message_list = e_mail_reader_get_message_list (reader); + message_list_select_uid (message_list, uid); +} + +static void +mail_reader_init_charset_actions (EMailReader *reader) +{ + GtkActionGroup *action_group; + GtkRadioAction *default_action; + GSList *radio_group; + + action_group = e_mail_reader_get_action_group (reader); + + radio_group = e_charset_add_radio_actions ( + action_group, "mail-charset-", NULL, + G_CALLBACK (action_mail_charset_cb), reader); + + /* XXX Add a tooltip! */ + default_action = gtk_radio_action_new ( + "mail-charset-default", _("Default"), NULL, NULL, -1); + + gtk_radio_action_set_group (default_action, radio_group); + + g_signal_connect ( + default_action, "changed", + G_CALLBACK (action_mail_charset_cb), reader); + + gtk_action_group_add_action ( + action_group, GTK_ACTION (default_action)); + + gtk_radio_action_set_current_value (default_action, -1); +} + +static void +mail_reader_class_init (EMailReaderIface *iface) +{ + iface->set_folder = mail_reader_set_folder; + iface->set_message = mail_reader_set_message; + + signals[CHANGED] = g_signal_new ( + "changed", + G_OBJECT_CLASS_TYPE (iface), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[FOLDER_LOADED] = g_signal_new ( + "folder-loaded", + G_OBJECT_CLASS_TYPE (iface), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[SHOW_SEARCH_BAR] = g_signal_new ( + "show-search-bar", + G_OBJECT_CLASS_TYPE (iface), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (EMailReaderIface, show_search_bar), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +GType +e_mail_reader_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMailReaderIface), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) mail_reader_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + 0, /* instance_size */ + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, + NULL /* value_table */ + }; + + type = g_type_register_static ( + G_TYPE_INTERFACE, "EMailReader", &type_info, 0); + + g_type_interface_add_prerequisite (type, G_TYPE_OBJECT); + } + + return type; +} + +void +e_mail_reader_init (EMailReader *reader) +{ + EShell *shell; + EShellModule *shell_module; + EShellSettings *shell_settings; + EMFormatHTMLDisplay *html_display; + GtkActionGroup *action_group; + MessageList *message_list; + GConfBridge *bridge; + GtkAction *action; + GtkHTML *html; + const gchar *action_name; + const gchar *key; + + g_return_if_fail (E_IS_MAIL_READER (reader)); + + action_group = e_mail_reader_get_action_group (reader); + html_display = e_mail_reader_get_html_display (reader); + message_list = e_mail_reader_get_message_list (reader); + shell_module = e_mail_reader_get_shell_module (reader); + + shell = e_shell_module_get_shell (shell_module); + shell_settings = e_shell_get_shell_settings (shell); + + html = EM_FORMAT_HTML (html_display)->html; + + gtk_action_group_add_actions ( + action_group, mail_reader_entries, + G_N_ELEMENTS (mail_reader_entries), reader); + e_action_group_add_popup_actions ( + action_group, mail_reader_popup_entries, + G_N_ELEMENTS (mail_reader_popup_entries)); + gtk_action_group_add_toggle_actions ( + action_group, mail_reader_toggle_entries, + G_N_ELEMENTS (mail_reader_toggle_entries), reader); + + mail_reader_init_charset_actions (reader); + + /* Bind GObject properties to GConf keys. */ + + bridge = gconf_bridge_get (); + + action_name = "mail-caret-mode"; + key = "/apps/evolution/mail/display/caret_mode"; + action = e_mail_reader_get_action (reader, action_name); + gconf_bridge_bind_property (bridge, key, G_OBJECT (action), "active"); + + action_name = "mail-show-all-headers"; + key = "/apps/evolution/mail/display/show_all_headers"; + action = e_mail_reader_get_action (reader, action_name); + gconf_bridge_bind_property (bridge, key, G_OBJECT (action), "active"); + + /* Fine tuning. */ + + action_name = "mail-clipboard-copy"; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, FALSE); + + action_name = "mail-delete"; + action = e_mail_reader_get_action (reader, action_name); + g_object_set (action, "short-label", _("Delete"), NULL); + + action_name = "mail-next"; + action = e_mail_reader_get_action (reader, action_name); + g_object_set (action, "short-label", _("Next"), NULL); + + action_name = "mail-previous"; + action = e_mail_reader_get_action (reader, action_name); + g_object_set (action, "short-label", _("Previous"), NULL); + + action_name = "mail-reply-sender"; + action = e_mail_reader_get_action (reader, action_name); + g_object_set (action, "short-label", _("Reply"), NULL); + + /* Bind properties. */ + + e_binding_new_full ( + G_OBJECT (shell_settings), "mail-citation-color", + G_OBJECT (html_display), "citation-color", + e_binding_transform_string_to_color, + NULL, NULL); + + e_binding_new ( + G_OBJECT (shell_settings), "mail-image-loading-policy", + G_OBJECT (html_display), "image-loading-policy"); + + e_binding_new ( + G_OBJECT (shell_settings), "mail-only-local-photos", + G_OBJECT (html_display), "only-local-photos"); + + e_binding_new ( + G_OBJECT (shell_settings), "mail-show-animated-images", + G_OBJECT (html), "animate"); + + e_binding_new ( + G_OBJECT (shell_settings), "mail-show-sender-photo", + G_OBJECT (html_display), "show-sender-photo"); + + action_name = "mail-caret-mode"; + action = e_mail_reader_get_action (reader, action_name); + + e_mutual_binding_new ( + G_OBJECT (action), "active", + G_OBJECT (html), "caret-mode"); + + /* Connect signals. */ + + g_signal_connect_swapped ( + html, "button-release-event", + G_CALLBACK (mail_reader_html_button_release_event_cb), reader); + + g_signal_connect_swapped ( + html, "key-press-event", + G_CALLBACK (mail_reader_key_press_event_cb), reader); + + g_signal_connect_swapped ( + message_list, "message-selected", + G_CALLBACK (mail_reader_message_selected_cb), reader); + + g_signal_connect_swapped ( + message_list, "message-list-built", + G_CALLBACK (mail_reader_emit_folder_loaded), reader); + + g_signal_connect_swapped ( + message_list->tree, "double-click", + G_CALLBACK (mail_reader_double_click_cb), reader); + + g_signal_connect_swapped ( + message_list->tree, "key-press", + G_CALLBACK (mail_reader_key_press_cb), reader); + + g_signal_connect_swapped ( + message_list->tree, "selection-change", + G_CALLBACK (e_mail_reader_changed), reader); +} + +void +e_mail_reader_changed (EMailReader *reader) +{ + g_return_if_fail (E_IS_MAIL_READER (reader)); + + g_signal_emit (reader, signals[CHANGED], 0); +} + +guint32 +e_mail_reader_check_state (EMailReader *reader) +{ + MessageList *message_list; + GPtrArray *uids; + CamelFolder *folder; + CamelStore *store = NULL; + const gchar *folder_uri; + const gchar *tag; + gboolean can_clear_flags = FALSE; + gboolean can_flag_completed = FALSE; + gboolean can_flag_for_followup = FALSE; + gboolean has_deleted = FALSE; + gboolean has_important = FALSE; + gboolean has_junk = FALSE; + gboolean has_not_junk = FALSE; + gboolean has_read = FALSE; + gboolean has_undeleted = FALSE; + gboolean has_unimportant = FALSE; + gboolean has_unread = FALSE; + gboolean drafts_or_outbox; + gboolean store_supports_vjunk = FALSE; + guint32 state = 0; + guint ii; + + g_return_val_if_fail (E_IS_MAIL_READER (reader), 0); + + message_list = e_mail_reader_get_message_list (reader); + uids = message_list_get_selected (message_list); + folder_uri = message_list->folder_uri; + folder = message_list->folder; + + if (folder != NULL) { + store = CAMEL_STORE (folder->parent_store); + store_supports_vjunk = (store->flags & CAMEL_STORE_VJUNK); + } + + drafts_or_outbox = + em_utils_folder_is_drafts (folder, folder_uri) || + em_utils_folder_is_outbox (folder, folder_uri); + + for (ii = 0; ii < uids->len; ii++) { + CamelMessageInfo *info; + guint32 flags; + + info = camel_folder_get_message_info ( + folder, uids->pdata[ii]); + if (info == NULL) + continue; + + flags = camel_message_info_flags (info); + + if (flags & CAMEL_MESSAGE_SEEN) + has_read = TRUE; + else + has_unread = TRUE; + + if (drafts_or_outbox) { + has_junk = FALSE; + has_not_junk = FALSE; + } else if (store_supports_vjunk) { + guint32 bitmask; + + /* XXX Strictly speaking, this logic is correct. + * Problem is there's nothing in the message + * list that indicates whether a message is + * already marked "Not Junk". So the user may + * think the "Not Junk" button is enabling and + * disabling itself randomly as he reads mail. */ + + if (flags & CAMEL_MESSAGE_JUNK) + has_junk = TRUE; + if (flags & CAMEL_MESSAGE_NOTJUNK) + has_not_junk = TRUE; + + bitmask = CAMEL_MESSAGE_JUNK | CAMEL_MESSAGE_NOTJUNK; + + /* If neither junk flag is set, the + * message can be marked either way. */ + if ((flags & bitmask) == 0) { + has_junk = TRUE; + has_not_junk = TRUE; + } + + } else { + has_junk = TRUE; + has_not_junk = TRUE; + } + + if (flags & CAMEL_MESSAGE_DELETED) + has_deleted = TRUE; + else + has_undeleted = TRUE; + + if (flags & CAMEL_MESSAGE_FLAGGED) + has_important = TRUE; + else + has_unimportant = TRUE; + + tag = camel_message_info_user_tag (info, "follow-up"); + if (tag != NULL && *tag != '\0') { + can_clear_flags = TRUE; + tag = camel_message_info_user_tag ( + info, "completed-on"); + if (tag != NULL && *tag != '\0') + can_flag_completed = TRUE; + } else + can_flag_for_followup = TRUE; + } + + if (uids->len == 1) + state |= E_MAIL_READER_SELECTION_SINGLE; + if (uids->len > 1) + state |= E_MAIL_READER_SELECTION_MULTIPLE; + if (!drafts_or_outbox && uids->len == 1) + state |= E_MAIL_READER_SELECTION_CAN_ADD_SENDER; +#if 0 /* FIXME */ + if (can_edit) + state |= E_MAIL_READER_SELECTION_CAN_EDIT; +#endif + if (can_clear_flags) + state |= E_MAIL_READER_SELECTION_FLAG_CLEAR; + if (can_flag_completed) + state |= E_MAIL_READER_SELECTION_FLAG_COMPLETED; + if (can_flag_for_followup) + state |= E_MAIL_READER_SELECTION_FLAG_FOLLOWUP; + if (has_deleted) + state |= E_MAIL_READER_SELECTION_HAS_DELETED; + if (has_important) + state |= E_MAIL_READER_SELECTION_HAS_IMPORTANT; + if (has_junk) + state |= E_MAIL_READER_SELECTION_HAS_JUNK; + if (has_not_junk) + state |= E_MAIL_READER_SELECTION_HAS_NOT_JUNK; + if (has_read) + state |= E_MAIL_READER_SELECTION_HAS_READ; + if (has_undeleted) + state |= E_MAIL_READER_SELECTION_HAS_UNDELETED; + if (has_unimportant) + state |= E_MAIL_READER_SELECTION_HAS_UNIMPORTANT; + if (has_unread) + state |= E_MAIL_READER_SELECTION_HAS_UNREAD; +#if 0 /* FIXME */ + if (has_callto_uri) + state |= E_MAIL_READER_SELECTION_HAS_URI_CALLTO; + if (has_http_uri) + state |= E_MAIL_READER_SELECTION_HAS_URI_HTTP; + if (has_mailto_uri) + state |= E_MAIL_READER_SELECTION_HAS_URI_MAILTO; + if (is_mailing_list) + state |= E_MAIL_READER_SELECTION_IS_MAILING_LIST; +#endif + + em_utils_uids_free (uids); + + return state; + +} + +void +e_mail_reader_update_actions (EMailReader *reader) +{ + EShell *shell; + EShellModule *shell_module; + EShellSettings *shell_settings; + GtkAction *action; + GtkActionGroup *action_group; + const gchar *action_name; + gboolean sensitive; + guint32 state; + + /* Be descriptive. */ + gboolean any_messages_selected; + gboolean disable_printing; + gboolean enable_flag_clear; + gboolean enable_flag_completed; + gboolean enable_flag_for_followup; + gboolean single_message_selected; + gboolean multiple_messages_selected; + gboolean selection_has_deleted_messages; + gboolean selection_has_important_messages; + gboolean selection_has_junk_messages; + gboolean selection_has_not_junk_messages; + gboolean selection_has_read_messages; + gboolean selection_has_undeleted_messages; + gboolean selection_has_unimportant_messages; + gboolean selection_has_unread_messages; + gboolean selection_is_mailing_list; + + g_return_if_fail (E_IS_MAIL_READER (reader)); + + action_group = e_mail_reader_get_action_group (reader); + state = e_mail_reader_check_state (reader); + + shell_module = e_mail_reader_get_shell_module (reader); + shell = e_shell_module_get_shell (shell_module); + shell_settings = e_shell_get_shell_settings (shell); + + disable_printing = e_shell_settings_get_boolean ( + shell_settings, "disable-printing"); + + single_message_selected = + (state & E_MAIL_READER_SELECTION_SINGLE); + multiple_messages_selected = + (state & E_MAIL_READER_SELECTION_MULTIPLE); + /* FIXME Missing booleans */ + enable_flag_clear = + (state & E_MAIL_READER_SELECTION_FLAG_CLEAR); + enable_flag_completed = + (state & E_MAIL_READER_SELECTION_FLAG_COMPLETED); + enable_flag_for_followup = + (state & E_MAIL_READER_SELECTION_FLAG_FOLLOWUP); + selection_has_deleted_messages = + (state & E_MAIL_READER_SELECTION_HAS_DELETED); + selection_has_important_messages = + (state & E_MAIL_READER_SELECTION_HAS_IMPORTANT); + selection_has_junk_messages = + (state & E_MAIL_READER_SELECTION_HAS_JUNK); + selection_has_not_junk_messages = + (state & E_MAIL_READER_SELECTION_HAS_NOT_JUNK); + selection_has_read_messages = + (state & E_MAIL_READER_SELECTION_HAS_READ); + selection_has_undeleted_messages = + (state & E_MAIL_READER_SELECTION_HAS_UNDELETED); + selection_has_unimportant_messages = + (state & E_MAIL_READER_SELECTION_HAS_UNIMPORTANT); + selection_has_unread_messages = + (state & E_MAIL_READER_SELECTION_HAS_UNREAD); + /* FIXME Missing booleans */ + selection_is_mailing_list = + (state & E_MAIL_READER_SELECTION_IS_MAILING_LIST); + + any_messages_selected = + (single_message_selected || multiple_messages_selected); + + action_name = "mail-check-for-junk"; + sensitive = any_messages_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-copy"; + sensitive = any_messages_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-delete"; + sensitive = selection_has_undeleted_messages; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-filters-apply"; + sensitive = any_messages_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-forward"; + sensitive = any_messages_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-forward-attached"; + sensitive = any_messages_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-forward-inline"; + sensitive = single_message_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-forward-quoted"; + sensitive = single_message_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-load-images"; + sensitive = single_message_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-mark-important"; + sensitive = selection_has_unimportant_messages; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-mark-junk"; + sensitive = selection_has_not_junk_messages; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-mark-notjunk"; + sensitive = selection_has_junk_messages; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-mark-read"; + sensitive = selection_has_unread_messages; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-mark-unimportant"; + sensitive = selection_has_important_messages; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-mark-unread"; + sensitive = selection_has_read_messages; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-message-edit"; + sensitive = single_message_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-message-open"; + sensitive = any_messages_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-move"; + sensitive = any_messages_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-next-important"; + sensitive = single_message_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-next-thread"; + sensitive = single_message_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-next-unread"; + sensitive = single_message_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-previous-important"; + sensitive = single_message_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-previous-unread"; + sensitive = single_message_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-print"; + sensitive = single_message_selected && !disable_printing; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-print-preview"; + sensitive = single_message_selected && !disable_printing; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-redirect"; + sensitive = single_message_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-reply-all"; + sensitive = single_message_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-reply-list"; + sensitive = single_message_selected && selection_is_mailing_list; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-reply-post"; + sensitive = single_message_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-reply-sender"; + sensitive = single_message_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-save-as"; + sensitive = any_messages_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-select-all"; + sensitive = single_message_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-show-source"; + sensitive = single_message_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-undelete"; + sensitive = selection_has_deleted_messages; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-zoom-100"; + sensitive = single_message_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-zoom-in"; + sensitive = single_message_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); + + action_name = "mail-zoom-out"; + sensitive = single_message_selected; + action = e_mail_reader_get_action (reader, action_name); + gtk_action_set_sensitive (action, sensitive); +} + +GtkAction * +e_mail_reader_get_action (EMailReader *reader, + const gchar *action_name) +{ + GtkActionGroup *action_group; + GtkAction *action; + + g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL); + g_return_val_if_fail (action_name != NULL, NULL); + + action_group = e_mail_reader_get_action_group (reader); + action = gtk_action_group_get_action (action_group, action_name); + + if (action == NULL) + g_critical ( + "%s: action `%s' not found", G_STRFUNC, action_name); + + return action; +} + +GtkActionGroup * +e_mail_reader_get_action_group (EMailReader *reader) +{ + EMailReaderIface *iface; + + g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL); + + iface = E_MAIL_READER_GET_IFACE (reader); + g_return_val_if_fail (iface->get_action_group != NULL, NULL); + + return iface->get_action_group (reader); +} + +gboolean +e_mail_reader_get_hide_deleted (EMailReader *reader) +{ + EMailReaderIface *iface; + + g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE); + + iface = E_MAIL_READER_GET_IFACE (reader); + g_return_val_if_fail (iface->get_hide_deleted != NULL, FALSE); + + return iface->get_hide_deleted (reader); +} + +EMFormatHTMLDisplay * +e_mail_reader_get_html_display (EMailReader *reader) +{ + EMailReaderIface *iface; + + g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL); + + iface = E_MAIL_READER_GET_IFACE (reader); + g_return_val_if_fail (iface->get_html_display != NULL, NULL); + + return iface->get_html_display (reader); +} + +MessageList * +e_mail_reader_get_message_list (EMailReader *reader) +{ + EMailReaderIface *iface; + + g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL); + + iface = E_MAIL_READER_GET_IFACE (reader); + g_return_val_if_fail (iface->get_message_list != NULL, NULL); + + return iface->get_message_list (reader); +} + +EShellModule * +e_mail_reader_get_shell_module (EMailReader *reader) +{ + EMailReaderIface *iface; + + g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL); + + iface = E_MAIL_READER_GET_IFACE (reader); + g_return_val_if_fail (iface->get_shell_module != NULL, NULL); + + return iface->get_shell_module (reader); +} + +GtkWindow * +e_mail_reader_get_window (EMailReader *reader) +{ + EMailReaderIface *iface; + + g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL); + + iface = E_MAIL_READER_GET_IFACE (reader); + g_return_val_if_fail (iface->get_window != NULL, NULL); + + return iface->get_window (reader); +} + +void +e_mail_reader_set_folder (EMailReader *reader, + CamelFolder *folder, + const gchar *folder_uri) +{ + EMailReaderIface *iface; + + g_return_if_fail (E_IS_MAIL_READER (reader)); + + iface = E_MAIL_READER_GET_IFACE (reader); + g_return_if_fail (iface->set_folder != NULL); + + iface->set_folder (reader, folder, folder_uri); +} + +/* Helper for e_mail_reader_set_folder_uri() */ +static void +mail_reader_got_folder_cb (gchar *folder_uri, + CamelFolder *folder, + gpointer user_data) +{ + EMailReader *reader = user_data; + + e_mail_reader_set_folder (reader, folder, folder_uri); +} + +void +e_mail_reader_set_folder_uri (EMailReader *reader, + const gchar *folder_uri) +{ + g_return_if_fail (E_IS_MAIL_READER (reader)); + g_return_if_fail (folder_uri != NULL); + + /* Fetch the CamelFolder asynchronously. */ + mail_get_folder ( + folder_uri, 0, mail_reader_got_folder_cb, + reader, mail_msg_fast_ordered_push); +} + +void +e_mail_reader_set_message (EMailReader *reader, + const gchar *uid, + gboolean mark_read) +{ + EMailReaderIface *iface; + + g_return_if_fail (E_IS_MAIL_READER (reader)); + + iface = E_MAIL_READER_GET_IFACE (reader); + g_return_if_fail (iface->set_message != NULL); + + iface->set_message (reader, uid, mark_read); +} + +void +e_mail_reader_create_charset_menu (EMailReader *reader, + GtkUIManager *ui_manager, + guint merge_id) +{ + GtkAction *action; + const gchar *action_name; + const gchar *path; + GSList *list; + + g_return_if_fail (E_IS_MAIL_READER (reader)); + g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager)); + + action_name = "mail-charset-default"; + action = e_mail_reader_get_action (reader, action_name); + g_return_if_fail (action != NULL); + + list = gtk_radio_action_get_group (GTK_RADIO_ACTION (action)); + list = g_slist_copy (list); + list = g_slist_remove (list, action); + list = g_slist_sort (list, (GCompareFunc) e_action_compare_by_label); + + path = "/main-menu/view-menu/mail-message-view-actions/mail-encoding-menu"; + + while (list != NULL) { + action = list->data; + + gtk_ui_manager_add_ui ( + ui_manager, merge_id, path, + gtk_action_get_name (action), + gtk_action_get_name (action), + GTK_UI_MANAGER_AUTO, FALSE); + + list = g_slist_delete_link (list, list); + } + + gtk_ui_manager_ensure_update (ui_manager); +} + +void +e_mail_reader_show_search_bar (EMailReader *reader) +{ + g_return_if_fail (E_IS_MAIL_READER (reader)); + + g_signal_emit (reader, signals[SHOW_SEARCH_BAR], 0); +} diff --git a/mail/e-mail-reader.h b/mail/e-mail-reader.h new file mode 100644 index 0000000000..6499eaf07b --- /dev/null +++ b/mail/e-mail-reader.h @@ -0,0 +1,134 @@ +/* + * e-mail-reader.h + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MAIL_READER_H +#define E_MAIL_READER_H + +#include <gtk/gtk.h> +#include <camel/camel-folder.h> +#include <mail/em-format-html-display.h> +#include <mail/message-list.h> +#include <shell/e-shell-module.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_READER \ + (e_mail_reader_get_type ()) +#define E_MAIL_READER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_READER, EMailReader)) +#define E_MAIL_READER_IFACE(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_READER, EMailReaderIface)) +#define E_IS_MAIL_READER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_READER)) +#define E_IS_MAIL_READER_IFACE(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_READER)) +#define E_MAIL_READER_GET_IFACE(obj) \ + (G_TYPE_INSTANCE_GET_INTERFACE \ + ((obj), E_TYPE_MAIL_READER, EMailReaderIface)) + +/* Basename of the UI definition file. */ +#define E_MAIL_READER_UI_DEFINITION "evolution-mail-reader.ui" + +G_BEGIN_DECLS + +typedef struct _EMailReader EMailReader; +typedef struct _EMailReaderIface EMailReaderIface; + +enum { + E_MAIL_READER_SELECTION_SINGLE = 1 << 0, + E_MAIL_READER_SELECTION_MULTIPLE = 1 << 1, + E_MAIL_READER_SELECTION_CAN_ADD_SENDER = 1 << 2, + E_MAIL_READER_SELECTION_CAN_EDIT = 1 << 3, + E_MAIL_READER_SELECTION_FLAG_CLEAR = 1 << 4, + E_MAIL_READER_SELECTION_FLAG_COMPLETED = 1 << 5, + E_MAIL_READER_SELECTION_FLAG_FOLLOWUP = 1 << 6, + E_MAIL_READER_SELECTION_HAS_DELETED = 1 << 7, + E_MAIL_READER_SELECTION_HAS_IMPORTANT = 1 << 8, + E_MAIL_READER_SELECTION_HAS_JUNK = 1 << 9, + E_MAIL_READER_SELECTION_HAS_NOT_JUNK = 1 << 10, + E_MAIL_READER_SELECTION_HAS_READ = 1 << 11, + E_MAIL_READER_SELECTION_HAS_UNDELETED = 1 << 12, + E_MAIL_READER_SELECTION_HAS_UNIMPORTANT = 1 << 13, + E_MAIL_READER_SELECTION_HAS_UNREAD = 1 << 14, + E_MAIL_READER_SELECTION_HAS_URI_CALLTO = 1 << 15, + E_MAIL_READER_SELECTION_HAS_URI_HTTP = 1 << 16, + E_MAIL_READER_SELECTION_HAS_URI_MAILTO = 1 << 17, + E_MAIL_READER_SELECTION_IS_MAILING_LIST = 1 << 18 +}; + +struct _EMailReaderIface { + GTypeInterface parent_iface; + + GtkActionGroup * + (*get_action_group) (EMailReader *reader); + gboolean (*get_hide_deleted) (EMailReader *reader); + EMFormatHTMLDisplay * + (*get_html_display) (EMailReader *reader); + MessageList * (*get_message_list) (EMailReader *reader); + EShellModule * (*get_shell_module) (EMailReader *reader); + GtkWindow * (*get_window) (EMailReader *reader); + + void (*set_folder) (EMailReader *reader, + CamelFolder *folder, + const gchar *folder_uri); + void (*set_message) (EMailReader *reader, + const gchar *uid, + gboolean mark_read); + + /* Signals */ + void (*show_search_bar) (EMailReader *reader); +}; + +GType e_mail_reader_get_type (void); +void e_mail_reader_init (EMailReader *reader); +void e_mail_reader_changed (EMailReader *reader); +guint32 e_mail_reader_check_state (EMailReader *reader); +void e_mail_reader_update_actions (EMailReader *reader); +GtkAction * e_mail_reader_get_action (EMailReader *reader, + const gchar *action_name); +GtkActionGroup * + e_mail_reader_get_action_group (EMailReader *reader); +gboolean e_mail_reader_get_hide_deleted (EMailReader *reader); +EMFormatHTMLDisplay * + e_mail_reader_get_html_display (EMailReader *reader); +MessageList * e_mail_reader_get_message_list (EMailReader *reader); +EShellModule * e_mail_reader_get_shell_module (EMailReader *reader); +GtkWindow * e_mail_reader_get_window (EMailReader *reader); +void e_mail_reader_set_folder (EMailReader *reader, + CamelFolder *folder, + const gchar *folder_uri); +void e_mail_reader_set_folder_uri (EMailReader *reader, + const gchar *folder_uri); +void e_mail_reader_set_message (EMailReader *reader, + const gchar *uid, + gboolean mark_read); +void e_mail_reader_create_charset_menu + (EMailReader *reader, + GtkUIManager *ui_manager, + guint merge_id); +void e_mail_reader_show_search_bar (EMailReader *reader); + +G_END_DECLS + +#endif /* E_MAIL_READER_H */ diff --git a/mail/e-mail-search-bar.c b/mail/e-mail-search-bar.c new file mode 100644 index 0000000000..2d02d618c9 --- /dev/null +++ b/mail/e-mail-search-bar.c @@ -0,0 +1,664 @@ +/* + * e-mail-search-bar.c + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-search-bar.h" + +#include <glib/gi18n.h> +#include <gdk/gdkkeysyms.h> +#include <gtkhtml/gtkhtml-search.h> + +#include "e-util/e-binding.h" +#include "widgets/misc/e-icon-entry.h" + +#define E_MAIL_SEARCH_BAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_SEARCH_BAR, EMailSearchBarPrivate)) + +struct _EMailSearchBarPrivate { + GtkHTML *html; + GtkWidget *icon_entry; + GtkWidget *case_sensitive_button; + GtkWidget *matches_label; + + ESearchingTokenizer *tokenizer; + gchar *active_search; + + guint search_wrapped : 1; +}; + +enum { + PROP_0, + PROP_CASE_SENSITIVE, + PROP_HTML, + PROP_TEXT +}; + +enum { + CHANGED, + CLEAR, + LAST_SIGNAL +}; + +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; + +static void +mail_search_bar_update_matches (EMailSearchBar *search_bar) +{ + ESearchingTokenizer *tokenizer; + GtkWidget *matches_label; + gint matches; + gchar *text; + + tokenizer = e_mail_search_bar_get_tokenizer (search_bar); + matches_label = search_bar->priv->matches_label; + + matches = e_searching_tokenizer_match_count (tokenizer); + text = g_strdup_printf (_("Matches: %d"), matches); + + gtk_label_set_text (GTK_LABEL (matches_label), text); + gtk_widget_show (matches_label); + + g_free (text); +} + +static void +mail_search_bar_update_tokenizer (EMailSearchBar *search_bar) +{ + ESearchingTokenizer *tokenizer; + gboolean case_sensitive; + gchar *active_search; + + tokenizer = e_mail_search_bar_get_tokenizer (search_bar); + case_sensitive = e_mail_search_bar_get_case_sensitive (search_bar); + + if (GTK_WIDGET_VISIBLE (search_bar)) + active_search = search_bar->priv->active_search; + else + active_search = NULL; + + e_searching_tokenizer_set_primary_case_sensitivity ( + tokenizer, case_sensitive); + e_searching_tokenizer_set_primary_search_string ( + tokenizer, active_search); + + e_mail_search_bar_changed (search_bar); +} + +static void +mail_search_bar_find (EMailSearchBar *search_bar, + gboolean search_forward) +{ + GtkHTML *html; + gboolean case_sensitive; + gboolean new_search; + gchar *text; + + html = e_mail_search_bar_get_html (search_bar); + case_sensitive = e_mail_search_bar_get_case_sensitive (search_bar); + text = e_mail_search_bar_get_text (search_bar); + + if (text == NULL || *text == '\0') + gtk_widget_hide (search_bar->priv->matches_label); + + new_search = + (search_bar->priv->active_search == NULL) || + (g_strcmp0 (text, search_bar->priv->active_search) != 0); + + if (new_search) { + g_free (search_bar->priv->active_search); + search_bar->priv->active_search = text; + mail_search_bar_update_tokenizer (search_bar); + } else { + gtk_html_engine_search_set_forward (html, search_forward); + if (!gtk_html_engine_search_next (html)) + new_search = TRUE; + g_free (text); + } + + if (new_search) + gtk_html_engine_search ( + html, search_bar->priv->active_search, + case_sensitive, search_forward, FALSE); +} + +static void +mail_search_bar_changed_cb (EMailSearchBar *search_bar) +{ + g_object_notify (G_OBJECT (search_bar), "text"); +} + +static void +mail_search_bar_find_next_cb (EMailSearchBar *search_bar) +{ + mail_search_bar_find (search_bar, TRUE); +} + +static void +mail_search_bar_find_previous_cb (EMailSearchBar *search_bar) +{ + mail_search_bar_find (search_bar, FALSE); +} + +static void +mail_search_bar_toggled_cb (EMailSearchBar *search_bar) +{ + g_free (search_bar->priv->active_search); + search_bar->priv->active_search = NULL; + + g_object_notify (G_OBJECT (search_bar), "case-sensitive"); +} + +static void +mail_search_bar_set_html (EMailSearchBar *search_bar, + GtkHTML *html) +{ + ESearchingTokenizer *tokenizer; + + g_return_if_fail (search_bar->priv->html == NULL); + + search_bar->priv->html = g_object_ref (html); + + tokenizer = e_mail_search_bar_get_tokenizer (search_bar); + gtk_html_set_tokenizer (html, HTML_TOKENIZER (tokenizer)); +} + +static void +mail_search_bar_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CASE_SENSITIVE: + e_mail_search_bar_set_case_sensitive ( + E_MAIL_SEARCH_BAR (object), + g_value_get_boolean (value)); + return; + + case PROP_HTML: + mail_search_bar_set_html ( + E_MAIL_SEARCH_BAR (object), + g_value_get_object (value)); + return; + + case PROP_TEXT: + e_mail_search_bar_set_text ( + E_MAIL_SEARCH_BAR (object), + g_value_get_string (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_search_bar_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CASE_SENSITIVE: + g_value_set_boolean ( + value, e_mail_search_bar_get_case_sensitive ( + E_MAIL_SEARCH_BAR (object))); + return; + + case PROP_HTML: + g_value_set_object ( + value, e_mail_search_bar_get_html ( + E_MAIL_SEARCH_BAR (object))); + return; + + case PROP_TEXT: + g_value_take_string ( + value, e_mail_search_bar_get_text ( + E_MAIL_SEARCH_BAR (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_search_bar_dispose (GObject *object) +{ + EMailSearchBarPrivate *priv; + + priv = E_MAIL_SEARCH_BAR_GET_PRIVATE (object); + + if (priv->html != NULL) { + g_object_unref (priv->html); + priv->html = NULL; + } + + if (priv->icon_entry != NULL) { + g_object_unref (priv->icon_entry); + priv->icon_entry = NULL; + } + + if (priv->case_sensitive_button != NULL) { + g_object_unref (priv->case_sensitive_button); + priv->case_sensitive_button = NULL; + } + + if (priv->matches_label != NULL) { + g_object_unref (priv->matches_label); + priv->matches_label = NULL; + } + + if (priv->tokenizer != NULL) { + g_object_unref (priv->tokenizer); + priv->tokenizer = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +mail_search_bar_finalize (GObject *object) +{ + EMailSearchBarPrivate *priv; + + priv = E_MAIL_SEARCH_BAR_GET_PRIVATE (object); + + g_free (priv->active_search); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +mail_search_bar_constructed (GObject *object) +{ + EMailSearchBarPrivate *priv; + + priv = E_MAIL_SEARCH_BAR_GET_PRIVATE (object); + + e_mutual_binding_new ( + G_OBJECT (object), "case-sensitive", + G_OBJECT (priv->case_sensitive_button), "active"); +} + +static void +mail_search_bar_show (GtkWidget *widget) +{ + EMailSearchBar *search_bar; + EIconEntry *icon_entry; + GtkWidget *entry; + + search_bar = E_MAIL_SEARCH_BAR (widget); + + /* Chain up to parent's show() method. */ + GTK_WIDGET_CLASS (parent_class)->show (widget); + + icon_entry = E_ICON_ENTRY (search_bar->priv->icon_entry); + entry = e_icon_entry_get_entry (icon_entry); + gtk_widget_grab_focus (entry); + + mail_search_bar_update_tokenizer (search_bar); +} + +static void +mail_search_bar_hide (GtkWidget *widget) +{ + EMailSearchBar *search_bar; + + search_bar = E_MAIL_SEARCH_BAR (widget); + + /* Chain up to parent's hide() method. */ + GTK_WIDGET_CLASS (parent_class)->hide (widget); + + mail_search_bar_update_tokenizer (search_bar); +} + +static gboolean +mail_search_bar_key_press_event (GtkWidget *widget, + GdkEventKey *event) +{ + if (event->keyval == GDK_Escape) { + gtk_widget_hide (widget); + return TRUE; + } + + /* Chain up to parent's key_press_event() method. */ + return GTK_WIDGET_CLASS (parent_class)-> + key_press_event (widget, event); +} + +static void +mail_search_bar_clear (EMailSearchBar *search_bar) +{ + g_free (search_bar->priv->active_search); + search_bar->priv->active_search = NULL; + + gtk_widget_hide (search_bar->priv->matches_label); + + mail_search_bar_update_tokenizer (search_bar); +} + +static void +mail_search_bar_class_init (EMailSearchBarClass *class) +{ + GObjectClass *object_class; + GtkWidgetClass *widget_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMailSearchBarPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_search_bar_set_property; + object_class->get_property = mail_search_bar_get_property; + object_class->dispose = mail_search_bar_dispose; + object_class->finalize = mail_search_bar_finalize; + object_class->constructed = mail_search_bar_constructed; + + widget_class = GTK_WIDGET_CLASS (class); + widget_class->show = mail_search_bar_show; + widget_class->hide = mail_search_bar_hide; + widget_class->key_press_event = mail_search_bar_key_press_event; + + class->clear = mail_search_bar_clear; + + g_object_class_install_property ( + object_class, + PROP_CASE_SENSITIVE, + g_param_spec_boolean ( + "case-sensitive", + "Case Sensitive", + NULL, + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_HTML, + g_param_spec_object ( + "html", + "HTML Display", + NULL, + GTK_TYPE_HTML, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property ( + object_class, + PROP_TEXT, + g_param_spec_string ( + "text", + "Search Text", + NULL, + NULL, + G_PARAM_READWRITE)); + + signals[CHANGED] = g_signal_new ( + "changed", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (EMailSearchBarClass, changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[CLEAR] = g_signal_new ( + "clear", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (EMailSearchBarClass, clear), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +mail_search_bar_init (EMailSearchBar *search_bar) +{ + GtkWidget *label; + GtkWidget *widget; + GtkWidget *container; + + search_bar->priv = E_MAIL_SEARCH_BAR_GET_PRIVATE (search_bar); + search_bar->priv->tokenizer = e_searching_tokenizer_new (); + + g_signal_connect_swapped ( + search_bar->priv->tokenizer, "match", + G_CALLBACK (mail_search_bar_update_matches), search_bar); + + gtk_box_set_spacing (GTK_BOX (search_bar), 6); + + container = GTK_WIDGET (search_bar); + + widget = gtk_alignment_new (1.0, 0.5, 1.0, 1.0); + gtk_alignment_set_padding (GTK_ALIGNMENT (widget), 0, 0, 6, 0); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_label_new_with_mnemonic (_("Fin_d:")); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); + + container = GTK_WIDGET (search_bar); + label = widget; + + widget = e_icon_entry_new (); + gtk_label_set_mnemonic_widget ( + GTK_LABEL (label), + e_icon_entry_get_entry (E_ICON_ENTRY (widget))); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + search_bar->priv->icon_entry = g_object_ref (widget); + gtk_widget_show (widget); + + widget = e_icon_entry_get_entry (E_ICON_ENTRY (widget)); + + g_signal_connect_swapped ( + widget, "activate", + G_CALLBACK (mail_search_bar_find_next_cb), search_bar); + + g_signal_connect_swapped ( + widget, "changed", + G_CALLBACK (mail_search_bar_changed_cb), search_bar); + + widget = gtk_button_new_with_mnemonic (_("Find _Previous")); + gtk_button_set_image ( + GTK_BUTTON (widget), gtk_image_new_from_stock ( + GTK_STOCK_GO_BACK, GTK_ICON_SIZE_MENU)); + gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (mail_search_bar_find_previous_cb), search_bar); + + widget = gtk_button_new_with_mnemonic (_("Find _Next")); + gtk_button_set_image ( + GTK_BUTTON (widget), gtk_image_new_from_stock ( + GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_MENU)); + gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (mail_search_bar_find_next_cb), search_bar); + + widget = gtk_check_button_new_with_mnemonic (_("C_ase sensitive")); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + search_bar->priv->case_sensitive_button = g_object_ref (widget); + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "toggled", + G_CALLBACK (mail_search_bar_toggled_cb), search_bar); + + g_signal_connect_swapped ( + widget, "toggled", + G_CALLBACK (mail_search_bar_find_next_cb), search_bar); + + widget = gtk_button_new (); + gtk_button_set_image ( + GTK_BUTTON (widget), gtk_image_new_from_stock ( + GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU)); + gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE); + gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (gtk_widget_hide), search_bar); + + widget = gtk_label_new (NULL); + gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 0); + search_bar->priv->matches_label = g_object_ref (widget); + gtk_widget_show (widget); +} + +GType +e_mail_search_bar_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMailSearchBarClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) mail_search_bar_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMailSearchBar), + 0, /* n_preallocs */ + (GInstanceInitFunc) mail_search_bar_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_HBOX, "EMailSearchBar", &type_info, 0); + } + + return type; +} + +GtkWidget * +e_mail_search_bar_new (GtkHTML *html) +{ + g_return_val_if_fail (GTK_IS_HTML (html), NULL); + + return g_object_new (E_TYPE_MAIL_SEARCH_BAR, "html", html, NULL); +} + +void +e_mail_search_bar_clear (EMailSearchBar *search_bar) +{ + g_return_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar)); + + g_signal_emit (search_bar, signals[CLEAR], 0); +} + +void +e_mail_search_bar_changed (EMailSearchBar *search_bar) +{ + g_return_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar)); + + g_signal_emit (search_bar, signals[CHANGED], 0); +} + +GtkHTML * +e_mail_search_bar_get_html (EMailSearchBar *search_bar) +{ + g_return_val_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar), NULL); + + return search_bar->priv->html; +} + +ESearchingTokenizer * +e_mail_search_bar_get_tokenizer (EMailSearchBar *search_bar) +{ + g_return_val_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar), NULL); + + return search_bar->priv->tokenizer; +} + +gboolean +e_mail_search_bar_get_case_sensitive (EMailSearchBar *search_bar) +{ + GtkToggleButton *button; + + g_return_val_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar), FALSE); + + button = GTK_TOGGLE_BUTTON (search_bar->priv->case_sensitive_button); + + return gtk_toggle_button_get_active (button); +} + +void +e_mail_search_bar_set_case_sensitive (EMailSearchBar *search_bar, + gboolean case_sensitive) +{ + GtkToggleButton *button; + + g_return_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar)); + + button = GTK_TOGGLE_BUTTON (search_bar->priv->case_sensitive_button); + + gtk_toggle_button_set_active (button, case_sensitive); + + g_object_notify (G_OBJECT (search_bar), "case-sensitive"); +} + +gchar * +e_mail_search_bar_get_text (EMailSearchBar *search_bar) +{ + EIconEntry *icon_entry; + GtkWidget *entry; + const gchar *text; + + g_return_val_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar), NULL); + + icon_entry = E_ICON_ENTRY (search_bar->priv->icon_entry); + entry = e_icon_entry_get_entry (icon_entry); + text = gtk_entry_get_text (GTK_ENTRY (entry)); + + return g_strstrip (g_strdup (text)); +} + +void +e_mail_search_bar_set_text (EMailSearchBar *search_bar, + const gchar *text) +{ + EIconEntry *icon_entry; + GtkWidget *entry; + + g_return_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar)); + + icon_entry = E_ICON_ENTRY (search_bar->priv->icon_entry); + entry = e_icon_entry_get_entry (icon_entry); + + if (text == NULL) + text = ""; + + /* This will trigger a "notify::text" signal. */ + gtk_entry_set_text (GTK_ENTRY (entry), text); +} diff --git a/mail/e-mail-search-bar.h b/mail/e-mail-search-bar.h new file mode 100644 index 0000000000..7f19e176b7 --- /dev/null +++ b/mail/e-mail-search-bar.h @@ -0,0 +1,85 @@ +/* + * e-mail-search-bar.h + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MAIL_SEARCH_BAR_H +#define E_MAIL_SEARCH_BAR_H + +#include <gtk/gtk.h> +#include <gtkhtml/gtkhtml.h> +#include <mail/e-searching-tokenizer.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_SEARCH_BAR \ + (e_mail_search_bar_get_type ()) +#define E_MAIL_SEARCH_BAR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_SEARCH_BAR, EMailSearchBar)) +#define E_MAIL_SEARCH_BAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_SEARCH_BAR, EMailSearchBarClass)) +#define E_IS_MAIL_SEARCH_BAR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_SEARCH_BAR)) +#define E_IS_MAIL_SEARCH_BAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_SEARCH_BAR)) +#define E_MAIL_SEARCH_BAR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_SEARCH_BAR, EMailSearchBarClass)) + +G_BEGIN_DECLS + +typedef struct _EMailSearchBar EMailSearchBar; +typedef struct _EMailSearchBarClass EMailSearchBarClass; +typedef struct _EMailSearchBarPrivate EMailSearchBarPrivate; + +struct _EMailSearchBar { + GtkHBox parent; + EMailSearchBarPrivate *priv; +}; + +struct _EMailSearchBarClass { + GtkHBoxClass parent_class; + + /* Signals */ + void (*changed) (EMailSearchBar *search_bar); + void (*clear) (EMailSearchBar *search_bar); +}; + +GType e_mail_search_bar_get_type (void); +GtkWidget * e_mail_search_bar_new (GtkHTML *html); +void e_mail_search_bar_clear (EMailSearchBar *search_bar); +void e_mail_search_bar_changed (EMailSearchBar *search_bar); +GtkHTML * e_mail_search_bar_get_html (EMailSearchBar *search_bar); +ESearchingTokenizer * + e_mail_search_bar_get_tokenizer (EMailSearchBar *search_bar); +gboolean e_mail_search_bar_get_case_sensitive + (EMailSearchBar *search_bar); +void e_mail_search_bar_set_case_sensitive + (EMailSearchBar *search_bar, + gboolean case_sensitive); +gchar * e_mail_search_bar_get_text (EMailSearchBar *search_bar); +void e_mail_search_bar_set_text (EMailSearchBar *search_bar, + const gchar *text); + +G_END_DECLS + +#endif /* E_MAIL_SEARCH_BAR_H */ diff --git a/mail/e-mail-shell-content.c b/mail/e-mail-shell-content.c new file mode 100644 index 0000000000..9f6de123aa --- /dev/null +++ b/mail/e-mail-shell-content.c @@ -0,0 +1,1014 @@ +/* + * e-mail-shell-content.c + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-shell-content.h" + +#include <glib/gi18n.h> +#include <camel/camel-store.h> +#include <libedataserver/e-data-server-util.h> + +#include "e-util/gconf-bridge.h" +#include "widgets/menus/gal-view-etable.h" +#include "widgets/menus/gal-view-instance.h" + +#include "em-folder-view.h" +#include "em-search-context.h" +#include "em-utils.h" +#include "mail-config.h" +#include "mail-ops.h" + +#include "e-mail-reader.h" +#include "e-mail-search-bar.h" +#include "e-mail-shell-module.h" +#include "e-mail-shell-view-actions.h" + +#define E_MAIL_SHELL_CONTENT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_SHELL_CONTENT, EMailShellContentPrivate)) + +struct _EMailShellContentPrivate { + GtkWidget *paned; + GtkWidget *message_list; + GtkWidget *search_bar; + + EMFormatHTMLDisplay *html_display; + GalViewInstance *view_instance; + + gchar *selected_uid; + + /* ETable scrolling hack */ + gdouble default_scrollbar_position; + + guint paned_binding_id; + guint scroll_timeout_id; + + /* Signal handler IDs */ + guint message_list_built_id; + guint message_list_scrolled_id; + + guint preview_visible : 1; + guint suppress_message_selection : 1; + guint vertical_view : 1; + guint show_deleted : 1; +}; + +enum { + PROP_0, + PROP_PREVIEW_VISIBLE, + PROP_SHOW_DELETED, + PROP_VERTICAL_VIEW +}; + +static gpointer parent_class; + +static void +mail_shell_content_etree_unfreeze (MessageList *message_list, + GdkEvent *event) +{ + ETableItem *item; + GObject *object; + + item = e_tree_get_item (message_list->tree); + object = G_OBJECT (((GnomeCanvasItem *) item)->canvas); + + g_object_set_data (object, "freeze-cursor", 0); +} + +static void +mail_shell_content_message_list_scrolled_cb (EMailShellContent *mail_shell_content, + MessageList *message_list) +{ + const gchar *key; + gdouble position; + gchar *value; + + /* Save the scrollbar position for the current folder. */ + + if (message_list->folder == NULL) + return; + + key = "evolution:list_scroll_position"; + position = message_list_get_scrollbar_position (message_list); + value = g_strdup_printf ("%f", position); + + if (camel_object_meta_set (message_list->folder, key, value)) + camel_object_state_write (message_list->folder); + + g_free (value); +} + +static gboolean +mail_shell_content_scroll_timeout_cb (EMailShellContent *mail_shell_content) +{ + EMailShellContentPrivate *priv = mail_shell_content->priv; + MessageList *message_list; + EMailReader *reader; + const gchar *key; + gdouble position; + gchar *value; + + /* Initialize the scrollbar position for the current folder + * and setup a callback to handle scrollbar position changes. */ + + reader = E_MAIL_READER (mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + position = priv->default_scrollbar_position; + + key = "evolution:list_scroll_position"; + value = camel_object_meta_get (message_list->folder, key); + + if (value != NULL) { + position = strtod (value, NULL); + g_free (value); + } + + message_list_set_scrollbar_position (message_list, position); + + priv->message_list_scrolled_id = g_signal_connect_swapped ( + message_list, "message-list-scrolled", + G_CALLBACK (mail_shell_content_message_list_scrolled_cb), + mail_shell_content); + + priv->scroll_timeout_id = 0; + + return FALSE; +} + +static void +mail_shell_content_message_list_built_cb (EMailShellContent *mail_shell_content, + MessageList *message_list) +{ + EMailShellContentPrivate *priv = mail_shell_content->priv; + GtkScrolledWindow *scrolled_window; + GtkWidget *vscrollbar; + gdouble position = 0.0; + + g_signal_handler_disconnect ( + message_list, priv->message_list_built_id); + priv->message_list_built_id = 0; + + if (message_list->cursor_uid == NULL && priv->selected_uid != NULL) { + CamelMessageInfo *info; + + /* If the message isn't in the folder yet, keep selected_uid + * around, as it could be caught by a set_folder() at some + * later date. */ + info = camel_folder_get_message_info ( + message_list->folder, priv->selected_uid); + if (info != NULL) { + camel_folder_free_message_info ( + message_list->folder, info); + e_mail_reader_set_message ( + E_MAIL_READER (mail_shell_content), + priv->selected_uid, TRUE); + g_free (priv->selected_uid); + priv->selected_uid = NULL; + } + + position = message_list_get_scrollbar_position (message_list); + } + + priv->default_scrollbar_position = position; + + /* FIXME This is a gross workaround for an ETable bug that I can't + * fix (Ximian bug #55303). + * + * Since e_canvas_item_region_show_relay() uses a timeout, + * we have to use a timeout of the same interval but a lower + * priority. */ + priv->scroll_timeout_id = g_timeout_add_full ( + G_PRIORITY_LOW, 250, (GSourceFunc) + mail_shell_content_scroll_timeout_cb, + mail_shell_content, NULL); + + /* FIXME This is another ugly hack to hide a side-effect of the + * previous workaround. */ + scrolled_window = GTK_SCROLLED_WINDOW (message_list); + vscrollbar = gtk_scrolled_window_get_vscrollbar (scrolled_window); + g_signal_connect_swapped ( + vscrollbar, "button-press-event", + G_CALLBACK (mail_shell_content_etree_unfreeze), + message_list); +} + +static void +mail_shell_content_display_view_cb (EMailShellContent *mail_shell_content, + GalView *gal_view) +{ + EMailReader *reader; + MessageList *message_list; + + reader = E_MAIL_READER (mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + if (GAL_IS_VIEW_ETABLE (gal_view)) + gal_view_etable_attach_tree ( + GAL_VIEW_ETABLE (gal_view), message_list->tree); +} + +static void +mail_shell_content_message_selected_cb (EMailShellContent *mail_shell_content, + const gchar *selected_uid, + MessageList *message_list) +{ + const gchar *key = "evolution:selected_uid"; + CamelFolder *folder; + + folder = message_list->folder; + + /* This also gets triggered when selecting a store name on + * the sidebar such as "On This Computer", in which case + * 'folder' will be NULL. */ + if (folder == NULL) + return; + + if (camel_object_meta_set (folder, key, selected_uid)) + camel_object_state_write (folder); + + g_free (mail_shell_content->priv->selected_uid); + mail_shell_content->priv->selected_uid = NULL; +} + +static void +mail_shell_content_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_PREVIEW_VISIBLE: + e_mail_shell_content_set_preview_visible ( + E_MAIL_SHELL_CONTENT (object), + g_value_get_boolean (value)); + return; + + case PROP_SHOW_DELETED: + e_mail_shell_content_set_show_deleted ( + E_MAIL_SHELL_CONTENT (object), + g_value_get_boolean (value)); + return; + + case PROP_VERTICAL_VIEW: + e_mail_shell_content_set_vertical_view ( + E_MAIL_SHELL_CONTENT (object), + g_value_get_boolean (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_shell_content_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_PREVIEW_VISIBLE: + g_value_set_boolean ( + value, + e_mail_shell_content_get_preview_visible ( + E_MAIL_SHELL_CONTENT (object))); + return; + + case PROP_SHOW_DELETED: + g_value_set_boolean ( + value, + e_mail_shell_content_get_show_deleted ( + E_MAIL_SHELL_CONTENT (object))); + return; + + case PROP_VERTICAL_VIEW: + g_value_set_boolean ( + value, + e_mail_shell_content_get_vertical_view ( + E_MAIL_SHELL_CONTENT (object))); + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_shell_content_dispose (GObject *object) +{ + EMailShellContentPrivate *priv; + + priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (object); + + if (priv->paned != NULL) { + g_object_unref (priv->paned); + priv->paned = NULL; + } + + if (priv->message_list != NULL) { + g_object_unref (priv->message_list); + priv->message_list = NULL; + } + + if (priv->search_bar != NULL) { + g_object_unref (priv->search_bar); + priv->search_bar = NULL; + } + + if (priv->html_display != NULL) { + g_object_unref (priv->html_display); + priv->html_display = NULL; + } + + if (priv->view_instance != NULL) { + g_object_unref (priv->view_instance); + priv->view_instance = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +mail_shell_content_finalize (GObject *object) +{ + EMailShellContentPrivate *priv; + + priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (object); + + g_free (priv->selected_uid); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +mail_shell_content_constructed (GObject *object) +{ + EMailShellContentPrivate *priv; + EShellContent *shell_content; + EShellModule *shell_module; + EShellView *shell_view; + EShellViewClass *shell_view_class; + EMailReader *reader; + MessageList *message_list; + GConfBridge *bridge; + GtkWidget *container; + GtkWidget *widget; + GtkHTML *html; + GalViewCollection *view_collection; + const gchar *key; + + priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (object); + priv->html_display = em_format_html_display_new (); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + shell_content = E_SHELL_CONTENT (object); + shell_view = e_shell_content_get_shell_view (shell_content); + shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); + shell_module = e_shell_view_get_shell_module (shell_view); + view_collection = shell_view_class->view_collection; + + html = EM_FORMAT_HTML (priv->html_display)->html; + + /* Build content widgets. */ + + container = GTK_WIDGET (object); + + widget = gtk_vpaned_new (); + gtk_container_add (GTK_CONTAINER (container), widget); + priv->paned = g_object_ref (widget); + gtk_widget_show (widget); + + container = widget; + + widget = message_list_new (shell_module); + gtk_paned_add1 (GTK_PANED (container), widget); + priv->message_list = g_object_ref (widget); + gtk_widget_show (widget); + + widget = gtk_vbox_new (FALSE, 0); + gtk_paned_add2 (GTK_PANED (container), widget); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_container_add (GTK_CONTAINER (widget), GTK_WIDGET (html)); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + gtk_widget_show (GTK_WIDGET (html)); + gtk_widget_show (widget); + + widget = e_mail_search_bar_new (html); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + priv->search_bar = g_object_ref (widget); + gtk_widget_hide (widget); + + g_signal_connect_swapped ( + widget, "changed", + G_CALLBACK (em_format_redraw), priv->html_display); + + /* Load the view instance. */ + + e_mail_shell_content_update_view_instance ( + E_MAIL_SHELL_CONTENT (shell_content)); + + /* Bind GObject properties to GConf keys. */ + + bridge = gconf_bridge_get (); + + object = G_OBJECT (priv->paned); + key = "/apps/evolution/mail/display/paned_size"; + gconf_bridge_bind_property_delayed (bridge, key, object, "position"); + + object = G_OBJECT (shell_content); + key = "/apps/evolution/mail/display/show_deleted"; + gconf_bridge_bind_property (bridge, key, object, "show-deleted"); + + /* Message list customizations. */ + + reader = E_MAIL_READER (shell_content); + message_list = e_mail_reader_get_message_list (reader); + + g_signal_connect_swapped ( + message_list, "message-selected", + G_CALLBACK (mail_shell_content_message_selected_cb), + shell_content); +} + +static guint32 +mail_shell_content_check_state (EShellContent *shell_content) +{ + return e_mail_reader_check_state (E_MAIL_READER (shell_content)); +} + +static GtkActionGroup * +mail_shell_content_get_action_group (EMailReader *reader) +{ + EShellContent *shell_content; + EShellWindow *shell_window; + EShellView *shell_view; + + shell_content = E_SHELL_CONTENT (reader); + shell_view = e_shell_content_get_shell_view (shell_content); + shell_window = e_shell_view_get_shell_window (shell_view); + + return E_SHELL_WINDOW_ACTION_GROUP_MAIL (shell_window); +} + +static gboolean +mail_shell_content_get_hide_deleted (EMailReader *reader) +{ + EMailShellContent *mail_shell_content; + + mail_shell_content = E_MAIL_SHELL_CONTENT (reader); + + return !e_mail_shell_content_get_show_deleted (mail_shell_content); +} + +static EMFormatHTMLDisplay * +mail_shell_content_get_html_display (EMailReader *reader) +{ + EMailShellContentPrivate *priv; + + priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (reader); + + return priv->html_display; +} + +static MessageList * +mail_shell_content_get_message_list (EMailReader *reader) +{ + EMailShellContentPrivate *priv; + + priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (reader); + + return MESSAGE_LIST (priv->message_list); +} + +static EShellModule * +mail_shell_content_get_shell_module (EMailReader *reader) +{ + EShellContent *shell_content; + EShellView *shell_view; + + shell_content = E_SHELL_CONTENT (reader); + shell_view = e_shell_content_get_shell_view (shell_content); + + return e_shell_view_get_shell_module (shell_view); +} + +static GtkWindow * +mail_shell_content_get_window (EMailReader *reader) +{ + EShellContent *shell_content; + EShellWindow *shell_window; + EShellView *shell_view; + + shell_content = E_SHELL_CONTENT (reader); + shell_view = e_shell_content_get_shell_view (shell_content); + shell_window = e_shell_view_get_shell_window (shell_view); + + return GTK_WINDOW (shell_window); +} + +static void +mail_shell_content_set_folder (EMailReader *reader, + CamelFolder *folder, + const gchar *folder_uri) +{ + EMailShellContentPrivate *priv; + EMailReaderIface *default_iface; + MessageList *message_list; + gboolean different_folder; + gchar *meta_data; + + priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (reader); + + message_list = e_mail_reader_get_message_list (reader); + + message_list_freeze (message_list); + + different_folder = + message_list->folder != NULL && + folder != message_list->folder; + + /* Chain up to interface's default set_folder() method. */ + default_iface = g_type_default_interface_peek (E_TYPE_MAIL_READER); + default_iface->set_folder (reader, folder, folder_uri); + + if (folder == NULL) + goto exit; + + mail_refresh_folder (folder, NULL, NULL); + + /* This function gets triggered several times at startup, + * so we don't want to reset the message suppression state + * unless we're actually switching to a different folder. */ + if (different_folder) + priv->suppress_message_selection = FALSE; + + if (!priv->suppress_message_selection) + meta_data = camel_object_meta_get ( + folder, "evolution:selected_uid"); + else + meta_data = NULL; + + g_free (priv->selected_uid); + priv->selected_uid = meta_data; + + /* This is a one-time-only callback. */ + if (message_list->cursor_uid == NULL && priv->message_list_built_id == 0) + priv->message_list_built_id = g_signal_connect_swapped ( + message_list, "message-list-built", + G_CALLBACK (mail_shell_content_message_list_built_cb), + reader); + +exit: + message_list_thaw (message_list); +} + +static void +mail_shell_content_show_search_bar (EMailReader *reader) +{ + EMailShellContentPrivate *priv; + + priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (reader); + + gtk_widget_show (priv->search_bar); +} + +static void +mail_shell_content_class_init (EMailShellContentClass *class) +{ + GObjectClass *object_class; + EShellContentClass *shell_content_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMailShellContentPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = mail_shell_content_set_property; + object_class->get_property = mail_shell_content_get_property; + object_class->dispose = mail_shell_content_dispose; + object_class->finalize = mail_shell_content_finalize; + object_class->constructed = mail_shell_content_constructed; + + shell_content_class = E_SHELL_CONTENT_CLASS (class); + shell_content_class->new_search_context = em_search_context_new; + shell_content_class->check_state = mail_shell_content_check_state; + + g_object_class_install_property ( + object_class, + PROP_PREVIEW_VISIBLE, + g_param_spec_boolean ( + "preview-visible", + _("Preview is Visible"), + _("Whether the preview pane is visible"), + TRUE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SHOW_DELETED, + g_param_spec_boolean ( + "show-deleted", + "Show Deleted", + NULL, + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_VERTICAL_VIEW, + g_param_spec_boolean ( + "vertical-view", + _("Vertical View"), + _("Whether vertical view is enabled"), + FALSE, + G_PARAM_READWRITE)); +} + +static void +mail_shell_content_iface_init (EMailReaderIface *iface) +{ + iface->get_action_group = mail_shell_content_get_action_group; + iface->get_hide_deleted = mail_shell_content_get_hide_deleted; + iface->get_html_display = mail_shell_content_get_html_display; + iface->get_message_list = mail_shell_content_get_message_list; + iface->get_shell_module = mail_shell_content_get_shell_module; + iface->get_window = mail_shell_content_get_window; + iface->set_folder = mail_shell_content_set_folder; + iface->show_search_bar = mail_shell_content_show_search_bar; +} + +static void +mail_shell_content_init (EMailShellContent *mail_shell_content) +{ + mail_shell_content->priv = + E_MAIL_SHELL_CONTENT_GET_PRIVATE (mail_shell_content); + + mail_shell_content->priv->preview_visible = TRUE; + + /* Postpone widget construction until we have a shell view. */ +} + +GType +e_mail_shell_content_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMailShellContentClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) mail_shell_content_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMailShellContent), + 0, /* n_preallocs */ + (GInstanceInitFunc) mail_shell_content_init, + NULL /* value_table */ + }; + + static const GInterfaceInfo iface_info = { + (GInterfaceInitFunc) mail_shell_content_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL /* interface_data */ + }; + + type = g_type_register_static ( + E_TYPE_SHELL_CONTENT, "EMailShellContent", + &type_info, 0); + + g_type_add_interface_static ( + type, E_TYPE_MAIL_READER, &iface_info); + } + + return type; +} + +GtkWidget * +e_mail_shell_content_new (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_MAIL_SHELL_CONTENT, + "shell-view", shell_view, NULL); +} + +gboolean +e_mail_shell_content_get_preview_visible (EMailShellContent *mail_shell_content) +{ + g_return_val_if_fail ( + E_IS_MAIL_SHELL_CONTENT (mail_shell_content), FALSE); + + return mail_shell_content->priv->preview_visible; +} + +void +e_mail_shell_content_set_preview_visible (EMailShellContent *mail_shell_content, + gboolean preview_visible) +{ + GtkPaned *paned; + GtkWidget *child; + + g_return_if_fail (E_IS_MAIL_SHELL_CONTENT (mail_shell_content)); + + if (preview_visible == mail_shell_content->priv->preview_visible) + return; + + paned = GTK_PANED (mail_shell_content->priv->paned); + child = gtk_paned_get_child2 (paned); + + if (preview_visible) + gtk_widget_show (child); + else + gtk_widget_hide (child); + + mail_shell_content->priv->preview_visible = preview_visible; + + g_object_notify (G_OBJECT (mail_shell_content), "preview-visible"); +} + +gboolean +e_mail_shell_content_get_show_deleted (EMailShellContent *mail_shell_content) +{ + g_return_val_if_fail ( + E_IS_MAIL_SHELL_CONTENT (mail_shell_content), FALSE); + + return mail_shell_content->priv->show_deleted; +} + +void +e_mail_shell_content_set_show_deleted (EMailShellContent *mail_shell_content, + gboolean show_deleted) +{ + g_return_if_fail (E_IS_MAIL_SHELL_CONTENT (mail_shell_content)); + + mail_shell_content->priv->show_deleted = show_deleted; + + g_object_notify (G_OBJECT (mail_shell_content), "show-deleted"); +} + +gboolean +e_mail_shell_content_get_vertical_view (EMailShellContent *mail_shell_content) +{ + g_return_val_if_fail ( + E_IS_MAIL_SHELL_CONTENT (mail_shell_content), FALSE); + + return mail_shell_content->priv->vertical_view; +} + +void +e_mail_shell_content_set_vertical_view (EMailShellContent *mail_shell_content, + gboolean vertical_view) +{ + GConfBridge *bridge; + GtkWidget *old_paned; + GtkWidget *new_paned; + GtkWidget *child1; + GtkWidget *child2; + guint binding_id; + const gchar *key; + + g_return_if_fail (E_IS_MAIL_SHELL_CONTENT (mail_shell_content)); + + if (vertical_view == mail_shell_content->priv->vertical_view) + return; + + bridge = gconf_bridge_get (); + old_paned = mail_shell_content->priv->paned; + binding_id = mail_shell_content->priv->paned_binding_id; + + child1 = gtk_paned_get_child1 (GTK_PANED (old_paned)); + child2 = gtk_paned_get_child2 (GTK_PANED (old_paned)); + + if (binding_id > 0) + gconf_bridge_unbind (bridge, binding_id); + + if (vertical_view) { + new_paned = gtk_hpaned_new (); + key = "/apps/evolution/mail/display/hpaned_size"; + } else { + new_paned = gtk_vpaned_new (); + key = "/apps/evolution/mail/display/paned_size"; + } + + gtk_widget_reparent (child1, new_paned); + gtk_widget_reparent (child2, new_paned); + gtk_widget_show (new_paned); + + gtk_widget_destroy (old_paned); + gtk_container_add (GTK_CONTAINER (mail_shell_content), new_paned); + + binding_id = gconf_bridge_bind_property_delayed ( + bridge, key, G_OBJECT (new_paned), "position"); + + mail_shell_content->priv->vertical_view = vertical_view; + mail_shell_content->priv->paned_binding_id = binding_id; + mail_shell_content->priv->paned = g_object_ref (new_paned); + + e_mail_shell_content_update_view_instance (mail_shell_content); + + g_object_notify (G_OBJECT (mail_shell_content), "vertical-view"); +} + +GalViewInstance * +e_mail_shell_content_get_view_instance (EMailShellContent *mail_shell_content) +{ + g_return_val_if_fail ( + E_IS_MAIL_SHELL_CONTENT (mail_shell_content), NULL); + + return mail_shell_content->priv->view_instance; +} + +void +e_mail_shell_content_set_search_strings (EMailShellContent *mail_shell_content, + GSList *search_strings) +{ + EMailSearchBar *search_bar; + ESearchingTokenizer *tokenizer; + + g_return_if_fail (E_IS_MAIL_SHELL_CONTENT (mail_shell_content)); + + search_bar = E_MAIL_SEARCH_BAR (mail_shell_content->priv->search_bar); + tokenizer = e_mail_search_bar_get_tokenizer (search_bar); + + e_searching_tokenizer_set_secondary_case_sensitivity (tokenizer, FALSE); + e_searching_tokenizer_set_secondary_search_string (tokenizer, NULL); + + while (search_strings != NULL) { + e_searching_tokenizer_add_secondary_search_string ( + tokenizer, search_strings->data); + search_strings = g_slist_next (search_strings); + } + + e_mail_search_bar_changed (search_bar); +} + +void +e_mail_shell_content_update_view_instance (EMailShellContent *mail_shell_content) +{ + EMailReader *reader; + EShellContent *shell_content; + EShellView *shell_view; + EShellViewClass *shell_view_class; + GalViewCollection *view_collection; + GalViewInstance *view_instance; + MessageList *message_list; + gboolean outgoing_folder; + gboolean show_vertical_view; + gchar *view_id; + + g_return_if_fail (E_IS_MAIL_SHELL_CONTENT (mail_shell_content)); + + shell_content = E_SHELL_CONTENT (mail_shell_content); + shell_view = e_shell_content_get_shell_view (shell_content); + shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); + view_collection = shell_view_class->view_collection; + + reader = E_MAIL_READER (mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + /* If no folder is selected, return silently. */ + if (message_list->folder == NULL) + return; + + /* If we have a folder, we should also have a URI. */ + g_return_if_fail (message_list->folder_uri != NULL); + + if (mail_shell_content->priv->view_instance != NULL) { + g_object_unref (mail_shell_content->priv->view_instance); + mail_shell_content->priv->view_instance = NULL; + } + + view_id = mail_config_folder_to_safe_url (message_list->folder); + view_instance = e_shell_view_new_view_instance (shell_view, view_id); + mail_shell_content->priv->view_instance = view_instance; + + show_vertical_view = + e_mail_shell_content_get_vertical_view (mail_shell_content); + + if (show_vertical_view) { + gchar *filename; + gchar *safe_view_id; + + /* Force the view instance into vertical view. */ + + g_free (view_instance->custom_filename); + g_free (view_instance->current_view_filename); + + safe_view_id = g_strdup (view_id); + e_filename_make_safe (safe_view_id); + + filename = g_strdup_printf ( + "custom_wide_view-%s.xml", safe_view_id); + view_instance->custom_filename = g_build_filename ( + view_collection->local_dir, filename, NULL); + g_free (filename); + + filename = g_strdup_printf ( + "current_wide_view-%s.xml", safe_view_id); + view_instance->current_view_filename = g_build_filename ( + view_collection->local_dir, filename, NULL); + g_free (filename); + + g_free (safe_view_id); + } + + g_free (view_id); + + outgoing_folder = + em_utils_folder_is_drafts ( + message_list->folder, message_list->folder_uri) || + em_utils_folder_is_outbox ( + message_list->folder, message_list->folder_uri) || + em_utils_folder_is_sent ( + message_list->folder, message_list->folder_uri); + + if (outgoing_folder) { + if (show_vertical_view) + gal_view_instance_set_default_view ( + view_instance, "Wide_View_Sent"); + else + gal_view_instance_set_default_view ( + view_instance, "As_Sent_Folder"); + } else if (show_vertical_view) { + gal_view_instance_set_default_view ( + view_instance, "Wide_View_Normal"); + } + + gal_view_instance_load (view_instance); + + if (!gal_view_instance_exists (view_instance)) { + gchar *state_filename; + + state_filename = mail_config_folder_to_cachename ( + message_list->folder, "et-header-"); + + if (g_file_test (state_filename, G_FILE_TEST_IS_REGULAR)) { + ETableSpecification *spec; + ETableState *state; + GalView *view; + gchar *spec_filename; + + spec = e_table_specification_new (); + spec_filename = g_build_filename ( + EVOLUTION_ETSPECDIR, + "message-list.etspec", + NULL); + e_table_specification_load_from_file ( + spec, spec_filename); + g_free (spec_filename); + + state = e_table_state_new (); + view = gal_view_etable_new (spec, ""); + + e_table_state_load_from_file ( + state, state_filename); + gal_view_etable_set_state ( + GAL_VIEW_ETABLE (view), state); + gal_view_instance_set_custom_view ( + view_instance, view); + + g_object_unref (state); + g_object_unref (view); + g_object_unref (spec); + } + + g_free (state_filename); + } + + g_signal_connect ( + view_instance, "display-view", + G_CALLBACK (mail_shell_content_display_view_cb), + mail_shell_content); + + mail_shell_content_display_view_cb ( + mail_shell_content, + gal_view_instance_get_current_view (view_instance)); +} diff --git a/mail/e-mail-shell-content.h b/mail/e-mail-shell-content.h new file mode 100644 index 0000000000..485a9a8233 --- /dev/null +++ b/mail/e-mail-shell-content.h @@ -0,0 +1,92 @@ +/* + * e-mail-shell-content.h + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MAIL_SHELL_CONTENT_H +#define E_MAIL_SHELL_CONTENT_H + +#include <shell/e-shell-content.h> +#include <shell/e-shell-view.h> + +#include "em-format-html-display.h" + +/* Standard GObject macros */ +#define E_TYPE_MAIL_SHELL_CONTENT \ + (e_mail_shell_content_get_type ()) +#define E_MAIL_SHELL_CONTENT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_SHELL_CONTENT, EMailShellContent)) +#define E_MAIL_SHELL_CONTENT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_SHELL_CONTENT, EMailShellContentClass)) +#define E_IS_MAIL_SHELL_CONTENT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_SHELL_CONTENT)) +#define E_IS_MAIL_SHELL_CONTENT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_SHELL_CONTENT)) +#define E_MAIL_SHELL_CONTENT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_SHELL_CONTENT, EMailShellContentClass)) + +G_BEGIN_DECLS + +typedef struct _EMailShellContent EMailShellContent; +typedef struct _EMailShellContentClass EMailShellContentClass; +typedef struct _EMailShellContentPrivate EMailShellContentPrivate; + +struct _EMailShellContent { + EShellContent parent; + EMailShellContentPrivate *priv; +}; + +struct _EMailShellContentClass { + EShellContentClass parent_class; +}; + +GType e_mail_shell_content_get_type (void); +GtkWidget * e_mail_shell_content_new (EShellView *shell_view); +gboolean e_mail_shell_content_get_preview_visible + (EMailShellContent *mail_shell_content); +void e_mail_shell_content_set_preview_visible + (EMailShellContent *mail_shell_content, + gboolean preview_visible); +gboolean e_mail_shell_content_get_show_deleted + (EMailShellContent *mail_shell_content); +void e_mail_shell_content_set_show_deleted + (EMailShellContent *mail_shell_content, + gboolean show_deleted); +gboolean e_mail_shell_content_get_vertical_view + (EMailShellContent *mail_shell_content); +void e_mail_shell_content_set_vertical_view + (EMailShellContent *mail_shell_content, + gboolean vertical_view); +GalViewInstance * + e_mail_shell_content_get_view_instance + (EMailShellContent *mail_shell_content); +void e_mail_shell_content_set_search_strings + (EMailShellContent *mail_shell_content, + GSList *search_strings); +void e_mail_shell_content_update_view_instance + (EMailShellContent *mail_shell_content); + +G_END_DECLS + +#endif /* E_MAIL_SHELL_CONTENT_H */ diff --git a/mail/em-migrate.c b/mail/e-mail-shell-module-migrate.c index 97a05c8a7a..e318dee267 100644 --- a/mail/em-migrate.c +++ b/mail/e-mail-shell-module-migrate.c @@ -1,4 +1,6 @@ /* + * e-mail-shell-module-migrate.c + * * 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 @@ -10,19 +12,14 @@ * 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/> - * + * License along with the program; if not, see <http://www.gnu.org/licenses/> * - * Authors: - * Jeffrey Stedfast <fejj@ximian.com> * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif +#include "e-mail-shell-module-migrate.h" #include <stdio.h> #include <stdlib.h> @@ -37,6 +34,7 @@ #include <ctype.h> #include <glib.h> +#include <glib/gi18n.h> #include <glib/gstdio.h> #include <gtk/gtk.h> @@ -54,26 +52,24 @@ #include <libxml/parser.h> #include <libxml/xmlmemory.h> -#include <glib/gi18n.h> - #include <e-util/e-util.h> #include <libedataserver/e-data-server-util.h> #include <e-util/e-xml-utils.h> +#include "e-util/e-account-utils.h" #include "e-util/e-bconf-map.h" -#include "libedataserver/e-account-list.h" -#include "e-util/e-signature-list.h" #include "e-util/e-error.h" #include "e-util/e-util-private.h" #include "e-util/e-plugin.h" +#include "e-util/e-signature-utils.h" + +#include "e-mail-shell-module.h" +#include "shell/e-shell-migrate.h" -#include "mail-component.h" #include "mail-config.h" -#include "mail-session.h" #include "em-utils.h" -#include "em-migrate.h" -#define d(x) +#define d(x) x #ifndef G_OS_WIN32 /* No versions previous to 2.8 or thereabouts have been available on @@ -380,7 +376,7 @@ parse_lsub (const char *lsub, char *dir_sep) return NULL; } -static int +static gboolean read_imap_storeinfo (struct _account_info_1_0 *si) { FILE *storeinfo; @@ -433,7 +429,7 @@ read_imap_storeinfo (struct _account_info_1_0 *si) g_free (path); if (storeinfo == NULL) { g_warning ("could not find imap store info '%s'", path); - return -1; + return FALSE; } /* ignore version */ @@ -473,10 +469,10 @@ read_imap_storeinfo (struct _account_info_1_0 *si) fclose (storeinfo); - return 0; + return TRUE; } -static int +static gboolean load_accounts_1_0 (xmlDocPtr doc) { xmlNodePtr source; @@ -485,7 +481,7 @@ load_accounts_1_0 (xmlDocPtr doc) char key[32]; if (!(source = e_bconf_get_path (doc, "/Mail/Accounts"))) - return 0; + return TRUE; if ((val = e_bconf_get_value (source, "num"))) { count = atoi (val); @@ -536,11 +532,11 @@ load_accounts_1_0 (xmlDocPtr doc) g_hash_table_insert (accounts_name_1_0, ai->name, ai); } - return 0; + return TRUE; } -static int -em_migrate_1_0 (const char *evolution_dir, xmlDocPtr config_xmldb, xmlDocPtr filters, xmlDocPtr vfolders, CamelException *ex) +static gboolean +em_migrate_1_0 (const char *data_dir, xmlDocPtr config_xmldb, xmlDocPtr filters, xmlDocPtr vfolders, GError **error) { accounts_1_0 = g_hash_table_new_full ( g_str_hash, g_str_equal, @@ -555,11 +551,11 @@ em_migrate_1_0 (const char *evolution_dir, xmlDocPtr config_xmldb, xmlDocPtr fil g_hash_table_destroy (accounts_1_0); g_hash_table_destroy (accounts_name_1_0); - return 0; + return TRUE; } /* 1.2 upgrade functions */ -static int +static gboolean is_xml1encoded (const char *txt) { const unsigned char *p; @@ -653,7 +649,7 @@ utf8_reencode (const char *txt) } } -static int +static gboolean upgrade_xml_1_2_rec (xmlNodePtr node) { const char *value_tags[] = { "string", "address", "regex", "file", "command", NULL }; @@ -718,29 +714,30 @@ upgrade_xml_1_2_rec (xmlNodePtr node) node = node->next; } - return 0; + return TRUE; } -static int +static gboolean em_upgrade_xml_1_2 (xmlDocPtr doc) { xmlNodePtr root; if (!doc || !(root = xmlDocGetRootElement (doc))) - return 0; + return TRUE; return upgrade_xml_1_2_rec (root); } /* converts passwords from ~/evolution/private/config.xmldb to gnome_private() */ -static int +static gboolean upgrade_passwords_1_2(void) { xmlNodePtr root, entry; char *filename; xmlDocPtr priv_doc = NULL; struct stat st; - int work = 0, res = -1; + int work = 0; + gboolean success = FALSE; filename = g_build_filename(g_get_home_dir(), "evolution/private/config.xmldb", NULL); if (lstat(filename, &st) == 0 && S_ISREG(st.st_mode)) @@ -748,12 +745,12 @@ upgrade_passwords_1_2(void) g_free(filename); if (priv_doc == NULL) - return 0; + return TRUE; root = priv_doc->children; if (strcmp((char *)root->name, "bonobo-config") != 0) { xmlFreeDoc(priv_doc); - return 0; + return TRUE; } root = root->children; @@ -822,12 +819,12 @@ upgrade_passwords_1_2(void) if (work) { if (gnome_config_private_sync_file("/Evolution")) - res = 0; + success = TRUE; } else { - res = 0; + success = TRUE; } - return res; + return success; } /* ********************************************************************** */ @@ -1061,7 +1058,7 @@ static struct { }; /* remaps mail config from bconf to gconf */ -static int +static gboolean bconf_import(GConfClient *gconf, xmlDocPtr config_xmldb) { xmlNodePtr source; @@ -1112,11 +1109,11 @@ bconf_import(GConfClient *gconf, xmlDocPtr config_xmldb) e_bconf_import_xml_blob(gconf, config_xmldb, signature_map, "/Mail/Signatures", "/apps/evolution/mail/signatures", "signature", NULL); - return 0; + return TRUE; } -static int -em_migrate_1_2(const char *evolution_dir, xmlDocPtr config_xmldb, xmlDocPtr filters, xmlDocPtr vfolders, CamelException *ex) +static gboolean +em_migrate_1_2(const char *data_dir, xmlDocPtr config_xmldb, xmlDocPtr filters, xmlDocPtr vfolders, GError **error) { GConfClient *gconf; @@ -1128,7 +1125,7 @@ em_migrate_1_2(const char *evolution_dir, xmlDocPtr config_xmldb, xmlDocPtr filt em_upgrade_xml_1_2(vfolders); upgrade_passwords_1_2(); - return 0; + return TRUE; } /* 1.4 upgrade functions */ @@ -1199,71 +1196,50 @@ static GtkLabel *label; static GtkProgressBar *progress; static void -em_migrate_setup_progress_dialog (const char *title, const char *desc) +em_migrate_setup_progress_dialog (const char *desc) { GtkWidget *vbox, *hbox, *w; - gchar *markup; window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title ((GtkWindow *) window, _("Migrating...")); + gtk_window_set_modal ((GtkWindow *) window, TRUE); + gtk_container_set_border_width ((GtkContainer *) window, 6); - gtk_window_set_title (GTK_WINDOW (window), _("Migrating...")); - gtk_window_set_modal (GTK_WINDOW (window), TRUE); - gtk_window_set_resizable (GTK_WINDOW (window), FALSE); - gtk_container_set_border_width (GTK_CONTAINER (window), 6); + vbox = gtk_vbox_new (FALSE, 6); + gtk_widget_show (vbox); + gtk_container_add ((GtkContainer *) window, vbox); - hbox = gtk_hbox_new (FALSE, 24); + w = gtk_label_new (desc); - /* Install the info image */ - w = gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG); - gtk_misc_set_alignment (GTK_MISC (w), 0.5, 0.0); - gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0); + gtk_label_set_line_wrap ((GtkLabel *) w, TRUE); + gtk_widget_show (w); + gtk_box_pack_start_defaults ((GtkBox *) vbox, w); + + hbox = gtk_hbox_new (FALSE, 6); + gtk_widget_show (hbox); + gtk_box_pack_start_defaults ((GtkBox *) vbox, hbox); + + label = (GtkLabel *) gtk_label_new (""); + gtk_widget_show ((GtkWidget *) label); + gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) label); + + progress = (GtkProgressBar *) gtk_progress_bar_new (); + gtk_widget_show ((GtkWidget *) progress); + gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) progress); - /* Prepare the message */ - vbox = gtk_vbox_new (FALSE, 12); - gtk_widget_show (vbox); - gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); - - w = gtk_label_new (NULL); - gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.0); - markup = g_strconcat ("<big><b>", title ? title : _("Migration"), "</b></big>", NULL); - gtk_label_set_markup (GTK_LABEL (w), markup); - gtk_box_pack_start (GTK_BOX (vbox), w, TRUE, TRUE, 0); - g_free (markup); - - w = gtk_label_new (desc); - gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.0); - gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); - gtk_box_pack_start (GTK_BOX (vbox), w, TRUE, TRUE, 0); - - /* Progress bar */ - w = gtk_vbox_new (FALSE, 6); - gtk_box_pack_start (GTK_BOX (vbox), w, TRUE, TRUE, 0); - - label = GTK_LABEL (gtk_label_new ("")); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0); - gtk_label_set_line_wrap (label, TRUE); - gtk_widget_show (GTK_WIDGET (label)); - gtk_box_pack_start (GTK_BOX (w), GTK_WIDGET (label), TRUE, TRUE, 0); - - progress = GTK_PROGRESS_BAR (gtk_progress_bar_new ()); - gtk_widget_show (GTK_WIDGET (progress)); - gtk_box_pack_start (GTK_BOX (w), GTK_WIDGET (progress), TRUE, TRUE, 0); - - gtk_container_add (GTK_CONTAINER (window), hbox); - gtk_widget_show_all (hbox); gtk_widget_show (window); } static void em_migrate_close_progress_dialog (void) { - gtk_widget_destroy (GTK_WIDGET (window)); + gtk_widget_destroy ((GtkWidget *) window); } static void em_migrate_set_folder_name (const char *folder_name) { - gchar *text; + char *text; text = g_strdup_printf (_("Migrating '%s':"), folder_name); gtk_label_set_text (label, text); @@ -1338,7 +1314,7 @@ is_mail_folder (const char *metadata) return FALSE; } -static int +static gboolean get_local_et_expanded (const char *dirname) { xmlNodePtr node; @@ -1353,24 +1329,24 @@ get_local_et_expanded (const char *dirname) if (stat (buf, &st) == -1) { g_free (buf); - return -1; + return FALSE; } if (!(doc = xmlParseFile (buf))) { g_free (buf); - return -1; + return FALSE; } g_free (buf); if (!(node = xmlDocGetRootElement (doc)) || strcmp ((char *)node->name, "expanded_state") != 0) { xmlFreeDoc (doc); - return -1; + return FALSE; } if (!(buf = (char *)xmlGetProp (node, (const unsigned char *)"default"))) { xmlFreeDoc (doc); - return -1; + return FALSE; } thread_list = strcmp (buf, "0") == 0 ? 0 : 1; @@ -1456,7 +1432,7 @@ static int open_flags[3] = { O_WRONLY | O_CREAT | O_APPEND, }; -static int +static gboolean cp (const char *src, const char *dest, gboolean show_progress, int mode) { unsigned char readbuf[65536]; @@ -1470,18 +1446,18 @@ cp (const char *src, const char *dest, gboolean show_progress, int mode) * want to corrupt their existing data */ if (g_stat (dest, &st) == 0 && st.st_size > 0 && mode == CP_UNIQUE) { errno = EEXIST; - return -1; + return FALSE; } if (g_stat (src, &st) == -1 || (readfd = g_open (src, O_RDONLY | O_BINARY, 0)) == -1) - return -1; + return FALSE; if ((writefd = g_open (dest, open_flags[mode] | O_BINARY, 0666)) == -1) { errnosav = errno; close (readfd); errno = errnosav; - return -1; + return FALSE; } do { @@ -1518,7 +1494,7 @@ cp (const char *src, const char *dest, gboolean show_progress, int mode) utime (dest, &ut); chmod (dest, st.st_mode); - return 0; + return TRUE; exception: @@ -1533,12 +1509,12 @@ cp (const char *src, const char *dest, gboolean show_progress, int mode) unlink (dest); errno = errnosav; - return -1; + return FALSE; } #ifndef G_OS_WIN32 -static int +static gboolean cp_r (const char *src, const char *dest, const char *pattern, int mode) { GString *srcpath, *destpath; @@ -1548,10 +1524,10 @@ cp_r (const char *src, const char *dest, const char *pattern, int mode) DIR *dir; if (g_mkdir_with_parents (dest, 0777) == -1) - return -1; + return FALSE; if (!(dir = opendir (src))) - return -1; + return FALSE; srcpath = g_string_new (src); g_string_append_c (srcpath, '/'); @@ -1586,7 +1562,7 @@ cp_r (const char *src, const char *dest, const char *pattern, int mode) g_string_free (destpath, TRUE); g_string_free (srcpath, TRUE); - return 0; + return TRUE; } static void @@ -1623,18 +1599,21 @@ mbox_build_filename (GString *path, const char *toplevel_dir, const char *full_n } } -static int -em_migrate_folder(EMMigrateSession *session, const char *dirname, const char *full_name, CamelException *ex) +static gboolean +em_migrate_folder(EMMigrateSession *session, const char *dirname, const char *full_name, GError **error) { CamelFolder *old_folder = NULL, *new_folder = NULL; CamelStore *local_store = NULL; + CamelException ex; char *name, *uri; GPtrArray *uids; struct stat st; - int thread_list; + gboolean thread_list; int index, i; GString *src, *dest; - int res = -1; + gboolean success = FALSE; + + camel_exception_init (&ex); src = g_string_new(""); @@ -1644,7 +1623,7 @@ em_migrate_folder(EMMigrateSession *session, const char *dirname, const char *fu || !is_mail_folder(src->str)) { /* Not an evolution mail folder */ g_string_free(src, TRUE); - return 0; + return TRUE; } dest = g_string_new(""); @@ -1669,16 +1648,18 @@ em_migrate_folder(EMMigrateSession *session, const char *dirname, const char *fu dlen = dest->len; if (g_mkdir_with_parents (dest->str, 0777) == -1 && errno != EEXIST) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Unable to create new folder `%s': %s"), - dest->str, g_strerror(errno)); + g_set_error ( + error, E_SHELL_MIGRATE_ERROR, + E_SHELL_MIGRATE_ERROR_FAILED, + _("Unable to create new folder `%s': %s"), + dest->str, g_strerror (errno)); goto fatal; } *p = '/'; mode = CP_UNIQUE; retry_copy: - if (cp (src->str, dest->str, TRUE, mode) == -1) { + if (!cp (src->str, dest->str, TRUE, mode)) { if (errno == EEXIST) { int save = errno; @@ -1695,9 +1676,11 @@ em_migrate_folder(EMMigrateSession *session, const char *dirname, const char *fu errno = save; } - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Unable to copy folder `%s' to `%s': %s"), - src->str, dest->str, g_strerror(errno)); + g_set_error ( + error, E_SHELL_MIGRATE_ERROR, + E_SHELL_MIGRATE_ERROR_FAILED, + _("Unable to copy folder `%s' to `%s': %s"), + src->str, dest->str, g_strerror (errno)); goto fatal; } ignore: @@ -1717,14 +1700,14 @@ em_migrate_folder(EMMigrateSession *session, const char *dirname, const char *fu goto cmeta_err; /* write the meta count */ - if (camel_file_util_encode_uint32 (fp, thread_list != -1 ? 1 : 0) == -1) + if (camel_file_util_encode_uint32 (fp, thread_list ? 1 : 0) == -1) goto cmeta_err; - if (thread_list != -1) { + if (!thread_list) { if (camel_file_util_encode_string (fp, "evolution:thread_list") == -1) goto cmeta_err; - if (camel_file_util_encode_string (fp, thread_list ? "1" : "0") == -1) + if (camel_file_util_encode_string (fp, !thread_list ? "1" : "0") == -1) goto cmeta_err; } @@ -1763,16 +1746,16 @@ em_migrate_folder(EMMigrateSession *session, const char *dirname, const char *fu } else { guint32 flags = CAMEL_STORE_FOLDER_CREATE; - if (!(local_store = camel_session_get_store ((CamelSession *) session, uri, ex)) - || !(old_folder = camel_store_get_folder (local_store, name, 0, ex))) + if (!(local_store = camel_session_get_store ((CamelSession *) session, uri, &ex)) + || !(old_folder = camel_store_get_folder (local_store, name, 0, &ex))) goto fatal; flags |= (index ? CAMEL_STORE_FOLDER_BODY_INDEX : 0); - if (!(new_folder = camel_store_get_folder (session->store, full_name, flags, ex))) + if (!(new_folder = camel_store_get_folder (session->store, full_name, flags, &ex))) goto fatal; - if (thread_list != -1) { - camel_object_meta_set (new_folder, "evolution:thread_list", thread_list ? "1" : "0"); + if (!thread_list) { + camel_object_meta_set (new_folder, "evolution:thread_list", !thread_list ? "1" : "0"); camel_object_state_write (new_folder); } @@ -1784,17 +1767,17 @@ em_migrate_folder(EMMigrateSession *session, const char *dirname, const char *fu if (!(info = camel_folder_get_message_info (old_folder, uids->pdata[i]))) continue; - if (!(message = camel_folder_get_message (old_folder, uids->pdata[i], ex))) { + if (!(message = camel_folder_get_message (old_folder, uids->pdata[i], &ex))) { camel_folder_free_message_info (old_folder, info); camel_folder_free_uids (old_folder, uids); goto fatal; } - camel_folder_append_message (new_folder, message, info, NULL, ex); + camel_folder_append_message (new_folder, message, info, NULL, &ex); camel_folder_free_message_info (old_folder, info); camel_object_unref (message); - if (camel_exception_is_set (ex)) + if (camel_exception_is_set (&ex)) break; em_migrate_set_progress (((double) i + 1) / ((double) uids->len)); @@ -1802,10 +1785,10 @@ em_migrate_folder(EMMigrateSession *session, const char *dirname, const char *fu camel_folder_free_uids (old_folder, uids); - if (camel_exception_is_set (ex)) + if (camel_exception_is_set (&ex)) goto fatal; } - res = 0; + success = TRUE; fatal: g_free (uri); g_free (name); @@ -1818,34 +1801,42 @@ fatal: if (new_folder) camel_object_unref(new_folder); - return res; + if (camel_exception_is_set (&ex)) { + g_set_error ( + error, E_SHELL_MIGRATE_ERROR, + E_SHELL_MIGRATE_ERROR_FAILED, + "%s", camel_exception_get_description (&ex)); + camel_exception_clear (&ex); + } + + return success; } -static int -em_migrate_dir (EMMigrateSession *session, const char *dirname, const char *full_name, CamelException *ex) +static gboolean +em_migrate_dir (EMMigrateSession *session, const char *dirname, const char *full_name, GError **error) { char *path; DIR *dir; struct stat st; struct dirent *dent; - int res = 0; + gboolean success = TRUE; - if (em_migrate_folder(session, dirname, full_name, ex) == -1) - return -1; + if (!em_migrate_folder(session, dirname, full_name, error)) + return FALSE; /* no subfolders, not readable, don't care */ path = g_strdup_printf ("%s/subfolders", dirname); if (stat (path, &st) == -1 || !S_ISDIR (st.st_mode)) { g_free (path); - return 0; + return TRUE; } if (!(dir = opendir (path))) { g_free (path); - return 0; + return TRUE; } - while (res == 0 && (dent = readdir (dir))) { + while (success && (dent = readdir (dir))) { char *full_path; char *name; @@ -1859,7 +1850,7 @@ em_migrate_dir (EMMigrateSession *session, const char *dirname, const char *full } name = g_strdup_printf ("%s/%s", full_name, dent->d_name); - res = em_migrate_dir (session, full_path, name, ex); + success = em_migrate_dir (session, full_path, name, error); g_free (full_path); g_free (name); } @@ -1868,29 +1859,31 @@ em_migrate_dir (EMMigrateSession *session, const char *dirname, const char *full g_free (path); - return res; + return success; } -static int -em_migrate_local_folders_1_4 (EMMigrateSession *session, CamelException *ex) +static gboolean +em_migrate_local_folders_1_4 (EMMigrateSession *session, GError **error) { struct dirent *dent; struct stat st; DIR *dir; - int res = 0; + gboolean success = TRUE; if (!(dir = opendir (session->srcdir))) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Unable to scan for existing mailboxes at `%s': %s"), - session->srcdir, g_strerror(errno)); - return -1; + g_set_error ( + error, E_SHELL_MIGRATE_ERROR, + E_SHELL_MIGRATE_ERROR_FAILED, + _("Unable to scan for existing mailboxes at " + "`%s': %s"), session->srcdir, g_strerror (errno)); + return FALSE; } - em_migrate_setup_progress_dialog (NULL, _("The location and hierarchy of the Evolution mailbox " + em_migrate_setup_progress_dialog (_("The location and hierarchy of the Evolution mailbox " "folders has changed since Evolution 1.x.\n\nPlease be " "patient while Evolution migrates your folders...")); - while (res == 0 && (dent = readdir (dir))) { + while (success && (dent = readdir (dir))) { char *full_path; if (dent->d_name[0] == '.') @@ -1902,7 +1895,7 @@ em_migrate_local_folders_1_4 (EMMigrateSession *session, CamelException *ex) continue; } - res = em_migrate_dir (session, full_path, dent->d_name, ex); + success = em_migrate_dir (session, full_path, dent->d_name, error); g_free (full_path); } @@ -1910,7 +1903,7 @@ em_migrate_local_folders_1_4 (EMMigrateSession *session, CamelException *ex) em_migrate_close_progress_dialog (); - return res; + return success; } static char * @@ -2006,7 +1999,7 @@ get_nth_sig (int id) char *uid = NULL; int i = 0; - list = mail_config_get_signatures (); + list = e_get_signature_list (); iter = e_list_get_iterator ((EList *) list); while (e_iterator_is_valid (iter) && i < id) { @@ -2030,7 +2023,7 @@ em_upgrade_accounts_1_4 (void) EAccountList *accounts; EIterator *iter; - if (!(accounts = mail_config_get_accounts ())) + if (!(accounts = e_get_account_list ())) return; iter = e_list_get_iterator ((EList *) accounts); @@ -2063,18 +2056,18 @@ em_upgrade_accounts_1_4 (void) g_object_unref (iter); - mail_config_save_accounts (); + e_account_list_save (accounts); } -static int -em_migrate_pop_uid_caches_1_4 (const char *evolution_dir, CamelException *ex) +static gboolean +em_migrate_pop_uid_caches_1_4 (const char *data_dir, GError **error) { GString *oldpath, *newpath; struct dirent *dent; size_t olen, nlen; char *cache_dir; DIR *dir; - int res = 0; + gboolean success = TRUE; /* Sigh, too many unique strings to translate, for cases which shouldn't ever happen */ @@ -2083,14 +2076,16 @@ em_migrate_pop_uid_caches_1_4 (const char *evolution_dir, CamelException *ex) if (!(dir = opendir (cache_dir))) { if (errno == ENOENT) { g_free(cache_dir); - return 0; + return TRUE; } - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Unable to open old POP keep-on-server data `%s': %s"), - cache_dir, g_strerror (errno)); + g_set_error ( + error, E_SHELL_MIGRATE_ERROR, + E_SHELL_MIGRATE_ERROR_FAILED, + _("Unable to open old POP keep-on-server data " + "`%s': %s"), cache_dir, g_strerror (errno)); g_free (cache_dir); - return -1; + return FALSE; } oldpath = g_string_new (cache_dir); @@ -2098,15 +2093,18 @@ em_migrate_pop_uid_caches_1_4 (const char *evolution_dir, CamelException *ex) olen = oldpath->len; g_free (cache_dir); - cache_dir = g_build_filename (evolution_dir, "mail", "pop", NULL); + cache_dir = g_build_filename (data_dir, "pop", NULL); if (g_mkdir_with_parents (cache_dir, 0777) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Unable to create POP3 keep-on-server data directory `%s': %s"), - cache_dir, g_strerror(errno)); + g_set_error ( + error, E_SHELL_MIGRATE_ERROR, + E_SHELL_MIGRATE_ERROR_FAILED, + _("Unable to create POP3 keep-on-server data " + "directory `%s': %s"), cache_dir, + g_strerror (errno)); g_string_free (oldpath, TRUE); g_free (cache_dir); closedir (dir); - return -1; + return FALSE; } newpath = g_string_new (cache_dir); @@ -2114,7 +2112,7 @@ em_migrate_pop_uid_caches_1_4 (const char *evolution_dir, CamelException *ex) nlen = newpath->len; g_free (cache_dir); - while (res == 0 && (dent = readdir (dir))) { + while (success && (dent = readdir (dir))) { if (strncmp (dent->d_name, "cache-pop:__", 12) != 0) continue; @@ -2128,11 +2126,14 @@ em_migrate_pop_uid_caches_1_4 (const char *evolution_dir, CamelException *ex) g_string_truncate (newpath, newpath->len - 1); if (g_mkdir_with_parents (newpath->str, 0777) == -1 - || cp(oldpath->str, (g_string_append(newpath, "/uid-cache"))->str, FALSE, CP_UNIQUE)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Unable to copy POP3 keep-on-server data `%s': %s"), - oldpath->str, g_strerror(errno)); - res = -1; + || !cp(oldpath->str, (g_string_append(newpath, "/uid-cache"))->str, FALSE, CP_UNIQUE)) { + g_set_error ( + error, E_SHELL_MIGRATE_ERROR, + E_SHELL_MIGRATE_ERROR_FAILED, + _("Unable to copy POP3 keep-on-server data " + "`%s': %s"), oldpath->str, + g_strerror (errno)); + success = FALSE; } } @@ -2142,11 +2143,11 @@ em_migrate_pop_uid_caches_1_4 (const char *evolution_dir, CamelException *ex) closedir (dir); - return res; + return success; } -static int -em_migrate_imap_caches_1_4 (const char *evolution_dir, CamelException *ex) +static gboolean +em_migrate_imap_caches_1_4 (const char *data_dir, GError **error) { char *src, *dest; struct stat st; @@ -2154,10 +2155,10 @@ em_migrate_imap_caches_1_4 (const char *evolution_dir, CamelException *ex) src = g_build_filename (g_get_home_dir (), "evolution", "mail", "imap", NULL); if (stat (src, &st) == -1 || !S_ISDIR (st.st_mode)) { g_free (src); - return 0; + return TRUE; } - dest = g_build_filename (evolution_dir, "mail", "imap", NULL); + dest = g_build_filename (data_dir, "imap", NULL); /* we don't care if this fails, it's only a cache... */ cp_r (src, dest, "summary", CP_OVERWRITE); @@ -2165,11 +2166,11 @@ em_migrate_imap_caches_1_4 (const char *evolution_dir, CamelException *ex) g_free (dest); g_free (src); - return 0; + return TRUE; } -static int -em_migrate_folder_expand_state_1_4 (const char *evolution_dir, CamelException *ex) +static gboolean +em_migrate_folder_expand_state_1_4 (const char *data_dir, GError **error) { GString *srcpath, *destpath; size_t slen, dlen, rlen; @@ -2182,15 +2183,15 @@ em_migrate_folder_expand_state_1_4 (const char *evolution_dir, CamelException *e g_string_append (srcpath, "/evolution/config"); if (stat (srcpath->str, &st) == -1 || !S_ISDIR (st.st_mode)) { g_string_free (srcpath, TRUE); - return 0; + return TRUE; } - destpath = g_string_new (evolution_dir); - g_string_append (destpath, "/mail/config"); + destpath = g_string_new (data_dir); + g_string_append (destpath, "/config"); if (g_mkdir_with_parents (destpath->str, 0777) == -1 || !(dir = opendir (srcpath->str))) { g_string_free (destpath, TRUE); g_string_free (srcpath, TRUE); - return 0; + return TRUE; } g_string_append (srcpath, "/et-expanded-"); @@ -2221,7 +2222,7 @@ em_migrate_folder_expand_state_1_4 (const char *evolution_dir, CamelException *e /* this should always be the case afaik... */ inptr += rlen; new = g_string_new ("mbox:"); - g_string_append_printf (new, "%s/mail/local#", evolution_dir); + g_string_append_printf (new, "%s/local#", data_dir); full_name = g_strdup (inptr); inptr = full_name + strlen (full_name) - 12; @@ -2263,11 +2264,11 @@ em_migrate_folder_expand_state_1_4 (const char *evolution_dir, CamelException *e g_string_free (destpath, TRUE); g_string_free (srcpath, TRUE); - return 0; + return TRUE; } -static int -em_migrate_folder_view_settings_1_4 (const char *evolution_dir, CamelException *ex) +static gboolean +em_migrate_folder_view_settings_1_4 (const char *data_dir, GError **error) { GString *srcpath, *destpath; size_t slen, dlen, rlen; @@ -2280,15 +2281,15 @@ em_migrate_folder_view_settings_1_4 (const char *evolution_dir, CamelException * g_string_append (srcpath, "/evolution/views/mail"); if (stat (srcpath->str, &st) == -1 || !S_ISDIR (st.st_mode)) { g_string_free (srcpath, TRUE); - return 0; + return TRUE; } - destpath = g_string_new (evolution_dir); - g_string_append (destpath, "/mail/views"); + destpath = g_string_new (data_dir); + g_string_append (destpath, "/views"); if (g_mkdir_with_parents (destpath->str, 0777) == -1 || !(dir = opendir (srcpath->str))) { g_string_free (destpath, TRUE); g_string_free (srcpath, TRUE); - return 0; + return TRUE; } g_string_append_c (srcpath, '/'); @@ -2340,7 +2341,7 @@ em_migrate_folder_view_settings_1_4 (const char *evolution_dir, CamelException * /* this should always be the case afaik... */ inptr += rlen; new = g_string_new ("mbox:"); - g_string_append_printf (new, "%s/mail/local#", evolution_dir); + g_string_append_printf (new, "%s/local#", data_dir); full_name = g_strdup (inptr); inptr = full_name + strlen (full_name) - 12; @@ -2385,7 +2386,7 @@ em_migrate_folder_view_settings_1_4 (const char *evolution_dir, CamelException * g_string_free (destpath, TRUE); g_string_free (srcpath, TRUE); - return 0; + return TRUE; } #define SUBFOLDER_DIR_NAME "subfolders" @@ -2466,16 +2467,16 @@ e_path_to_physical (const char *prefix, const char *vpath) return ppath; } -static int -em_migrate_imap_cmeta_1_4(const char *evolution_dir, CamelException *ex) +static gboolean +em_migrate_imap_cmeta_1_4(const char *data_dir, GError **error) { GConfClient *gconf; GSList *paths, *p; EAccountList *accounts; const EAccount *account; - if (!(accounts = mail_config_get_accounts())) - return 0; + if (!(accounts = e_get_account_list ())) + return TRUE; gconf = gconf_client_get_default(); paths = gconf_client_get_list(gconf, "/apps/evolution/shell/offline/folder_paths", GCONF_VALUE_STRING, NULL); @@ -2495,8 +2496,8 @@ em_migrate_imap_cmeta_1_4(const char *evolution_dir, CamelException *ex) if (url) { char *dir, *base; - base = g_strdup_printf("%s/mail/imap/%s@%s/folders", - evolution_dir, + base = g_strdup_printf("%s/imap/%s@%s/folders", + data_dir, url->user?url->user:"", url->host?url->host:""); @@ -2540,7 +2541,7 @@ em_migrate_imap_cmeta_1_4(const char *evolution_dir, CamelException *ex) /* we couldn't care less if this doesn't work */ - return 0; + return TRUE; } static void @@ -2579,52 +2580,53 @@ remove_system_searches(xmlDocPtr searches) } } -static int -em_migrate_1_4 (const char *evolution_dir, xmlDocPtr filters, xmlDocPtr vfolders, CamelException *ex) +static gboolean +em_migrate_1_4 (const char *data_dir, xmlDocPtr filters, xmlDocPtr vfolders, GError **error) { EMMigrateSession *session; CamelException lex; struct stat st; - char *path; + gchar *path; xmlDocPtr searches; - path = g_build_filename (evolution_dir, "mail", NULL); - - camel_init (path, TRUE); + camel_init (data_dir, TRUE); camel_provider_init(); - session = (EMMigrateSession *) em_migrate_session_new (path); - g_free (path); + session = (EMMigrateSession *) em_migrate_session_new (data_dir); session->srcdir = g_build_filename (g_get_home_dir (), "evolution", "local", NULL); path = g_strdup_printf ("mbox:%s/.evolution/mail/local", g_get_home_dir ()); if (stat (path + 5, &st) == -1) { if (errno != ENOENT || g_mkdir_with_parents (path + 5, 0777) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to create local mail storage `%s': %s"), - path + 5, g_strerror (errno)); + g_set_error ( + error, E_SHELL_MIGRATE_ERROR, + E_SHELL_MIGRATE_ERROR_FAILED, + _("Failed to create local mail storage " + "`%s': %s"), path + 5, g_strerror (errno)); g_free (session->srcdir); camel_object_unref (session); g_free (path); - return -1; + return FALSE; } } camel_exception_init (&lex); if (!(session->store = camel_session_get_store ((CamelSession *) session, path, &lex))) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to create local mail storage `%s': %s"), - path, lex.desc); + g_set_error ( + error, E_SHELL_MIGRATE_ERROR, + E_SHELL_MIGRATE_ERROR_FAILED, + _("Failed to create local mail storage `%s': %s"), + path, lex.desc); g_free (session->srcdir); camel_object_unref (session); camel_exception_clear (&lex); g_free (path); - return -1; + return FALSE; } g_free (path); - if (em_migrate_local_folders_1_4 (session, ex) == -1) - return -1; + if (!em_migrate_local_folders_1_4 (session, error)) + return FALSE; camel_object_unref (session->store); g_free (session->srcdir); @@ -2642,26 +2644,24 @@ em_migrate_1_4 (const char *evolution_dir, xmlDocPtr filters, xmlDocPtr vfolders g_free(path); if (searches) { remove_system_searches(searches); - path = g_build_filename(evolution_dir, "mail", NULL); - emm_save_xml(searches, path, "searches.xml"); - g_free(path); + emm_save_xml(searches, data_dir, "searches.xml"); xmlFreeDoc(searches); } - if (em_migrate_pop_uid_caches_1_4 (evolution_dir, ex) == -1) - return -1; + if (!em_migrate_pop_uid_caches_1_4 (data_dir, error)) + return FALSE; /* these are non-fatal */ - em_migrate_imap_caches_1_4 (evolution_dir, ex); - camel_exception_clear(ex); - em_migrate_folder_expand_state_1_4 (evolution_dir, ex); - camel_exception_clear(ex); - em_migrate_folder_view_settings_1_4 (evolution_dir, ex); - camel_exception_clear(ex); - em_migrate_imap_cmeta_1_4(evolution_dir, ex); - camel_exception_clear(ex); - - return 0; + em_migrate_imap_caches_1_4 (data_dir, error); + g_clear_error (error); + em_migrate_folder_expand_state_1_4 (data_dir, error); + g_clear_error (error); + em_migrate_folder_view_settings_1_4 (data_dir, error); + g_clear_error (error); + em_migrate_imap_cmeta_1_4 (data_dir, error); + g_clear_error (error); + + return TRUE; } static void @@ -2671,7 +2671,7 @@ em_update_accounts_2_11 (void) EIterator *iter; gboolean changed = FALSE; - if (!(accounts = mail_config_get_accounts ())) + if (!(accounts = e_get_account_list ())) return; iter = e_list_get_iterator ((EList *) accounts); @@ -2694,13 +2694,13 @@ em_update_accounts_2_11 (void) g_object_unref (iter); if (changed) - mail_config_save_accounts (); + e_account_list_save (accounts); } #endif /* !G_OS_WIN32 */ -static int -emm_setup_initial(const char *evolution_dir) +static gboolean +emm_setup_initial(const gchar *data_dir) { GDir *dir; const char *d; @@ -2712,10 +2712,10 @@ emm_setup_initial(const char *evolution_dir) d(printf("Setting up initial mail tree\n")); - base = g_build_filename(evolution_dir, "mail", "local", NULL); + base = g_build_filename(data_dir, "local", NULL); if (g_mkdir_with_parents(base, 0777) == -1 && errno != EEXIST) { g_free(base); - return -1; + return FALSE; } /* e.g. try en-AU then en, etc */ @@ -2731,7 +2731,7 @@ emm_setup_initial(const char *evolution_dir) } /* Make sure we found one. */ - g_return_val_if_fail (*language_names != NULL, 0); + g_return_val_if_fail (*language_names != NULL, FALSE); dir = g_dir_open(local, 0, NULL); if (dir) { @@ -2751,7 +2751,7 @@ emm_setup_initial(const char *evolution_dir) g_free(local); g_free(base); - return 0; + return TRUE; } static gboolean @@ -2863,207 +2863,148 @@ em_update_sa_junk_setting_2_23 (void) g_object_unref (client); } -static gboolean -update_progress_in_main_thread (double *progress) -{ - em_migrate_set_progress (*progress); - return FALSE; -} static void -migrate_folders(CamelStore *store, gboolean is_local, CamelFolderInfo *fi, const char *acc, CamelException *ex, gboolean *done, int *nth_folder, int total_folders) +migrate_folders(CamelStore *store, CamelFolderInfo *fi, const char *acc, CamelException *ex) { CamelFolder *folder; while (fi) { - double progress; - char *tmp; - - *nth_folder = *nth_folder + 1; - - tmp = g_strdup_printf ("%s/%s", acc, fi->full_name); + char *tmp = g_strdup_printf ("%s/%s", acc, fi->full_name); em_migrate_set_folder_name (tmp); g_free (tmp); - - progress = (double) (*nth_folder) / total_folders; - g_idle_add ((GSourceFunc) update_progress_in_main_thread, &progress); - - if (is_local) - folder = camel_store_get_folder (store, fi->full_name, CAMEL_STORE_IS_MIGRATING, ex); - else - folder = camel_store_get_folder (store, fi->full_name, 0, ex); - + folder = camel_store_get_folder (store, fi->full_name, 0, ex); if (folder != NULL) camel_folder_summary_migrate_infos (folder->summary); - - migrate_folders(store, is_local, fi->child, acc, ex, done, nth_folder, total_folders); - - fi = fi->next; - } - - if ( (*nth_folder) == (total_folders - 1)) - *done = TRUE; -} - -/* This could be in CamelStore.ch */ -static void -count_folders (CamelFolderInfo *fi, int *count) -{ - while (fi) { - *count = *count + 1; - count_folders (fi->child , count); + migrate_folders(store, fi->child, acc, ex); fi = fi->next; } } static CamelStore * -setup_local_store (MailComponent *mc) +setup_local_store (EShellModule *shell_module, + EMMigrateSession *session) { CamelURL *url; + const gchar *data_dir; char *tmp; CamelStore *store; - + url = camel_url_new("mbox:", NULL); - tmp = g_build_filename (mail_component_peek_base_directory(mc), "local", NULL); + data_dir = e_shell_module_get_data_dir (shell_module); + tmp = g_build_filename (data_dir, "local", NULL); camel_url_set_path(url, tmp); g_free(tmp); tmp = camel_url_to_string(url, 0); - store = (CamelStore *)camel_session_get_service(session, tmp, CAMEL_PROVIDER_STORE, NULL); + store = (CamelStore *)camel_session_get_service(CAMEL_SESSION (session), tmp, CAMEL_PROVIDER_STORE, NULL); g_free(tmp); return store; - -} -struct migrate_folders_to_db_structure { - char *account_name; - CamelException ex; - CamelStore *store; - CamelFolderInfo *info; - gboolean done; - gboolean is_local_store; -}; - -static void migrate_folders_to_db_thread (struct migrate_folders_to_db_structure *migrate_dbs) -{ - int num_of_folders = 0, nth_folder = 0; - count_folders (migrate_dbs->info, &num_of_folders); - migrate_folders (migrate_dbs->store, migrate_dbs->is_local_store, migrate_dbs->info, - migrate_dbs->account_name, &(migrate_dbs->ex), &(migrate_dbs->done), - &nth_folder, num_of_folders); } - static void -migrate_to_db() +migrate_to_db (EShellModule *shell_module) { - EAccountList *accounts; - EIterator *iter; - int i=0, len; - MailComponent *component = mail_component_peek (); - CamelStore *store = NULL; - CamelFolderInfo *info; - - if (!(accounts = mail_config_get_accounts ())) - return; - - iter = e_list_get_iterator ((EList *) accounts); - len = e_list_length ((EList *) accounts); - - camel_session_set_online ((CamelSession *) session, FALSE); - - em_migrate_setup_progress_dialog (_("Migrating Folders"), _("The summary format of the Evolution mailbox " - "folders has been moved to SQLite since Evolution 2.24.\n\nPlease be " - "patient while Evolution migrates your folders...")); - - store = setup_local_store (component); - info = camel_store_get_folder_info (store, NULL, CAMEL_STORE_FOLDER_INFO_RECURSIVE|CAMEL_STORE_FOLDER_INFO_FAST|CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, NULL); - - if (info) { - GThread *thread; - struct migrate_folders_to_db_structure migrate_dbs; - - if (g_str_has_suffix (((CamelService *)store)->url->path, ".evolution/mail/local")) - migrate_dbs.is_local_store = TRUE; - else - migrate_dbs.is_local_store = FALSE; - camel_exception_init (&migrate_dbs.ex); - migrate_dbs.account_name = _("On This Computer"); - migrate_dbs.info = info; - migrate_dbs.store = store; - migrate_dbs.done = FALSE; - - thread = g_thread_create ((GThreadFunc) migrate_folders_to_db_thread, &migrate_dbs, TRUE, NULL); - while (!migrate_dbs.done) - g_main_context_iteration (NULL, TRUE); + EMMigrateSession *session; + EAccountList *accounts; + EIterator *iter; + int i=0, len; + CamelStore *store = NULL; + CamelFolderInfo *info; + const gchar *data_dir; + + if (!(accounts = e_get_account_list ())) + return; + + iter = e_list_get_iterator ((EList *) accounts); + len = e_list_length ((EList *) accounts); + + data_dir = e_shell_module_get_data_dir (shell_module); + session = (EMMigrateSession *) em_migrate_session_new (data_dir); + camel_session_set_online ((CamelSession *) session, FALSE); + em_migrate_setup_progress_dialog (_("The summary format of the Evolution mailbox " + "folders has been moved to SQLite since Evolution 2.24.\n\nPlease be " + "patient while Evolution migrates your folders...")); + + em_migrate_set_progress ( (double)i/(len+1)); + store = setup_local_store (shell_module, session); + info = camel_store_get_folder_info (store, NULL, CAMEL_STORE_FOLDER_INFO_RECURSIVE|CAMEL_STORE_FOLDER_INFO_FAST|CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, NULL); + if (info) { + migrate_folders(store, info, _("On This Computer"), NULL); + } + i++; + em_migrate_set_progress ( (double)i/(len+1)); + + + while (e_iterator_is_valid (iter)) { + EAccount *account = (EAccount *) e_iterator_get (iter); + EAccountService *service; + const char *name; + + + service = account->source; + name = account->name; + em_migrate_set_progress ( (double)i/(len+1)); + if (account->enabled + && service->url != NULL + && service->url[0] + && strncmp(service->url, "mbox:", 5) != 0) { + + CamelException ex; + + camel_exception_init (&ex); + e_mail_shell_module_load_store_by_uri ( + shell_module, service->url, name); + + store = (CamelStore *) camel_session_get_service (CAMEL_SESSION (session), service->url, CAMEL_PROVIDER_STORE, &ex); + info = camel_store_get_folder_info (store, NULL, CAMEL_STORE_FOLDER_INFO_RECURSIVE|CAMEL_STORE_FOLDER_INFO_FAST|CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, &ex); + if (info) { + migrate_folders(store, info, account->name, &ex); + + } else + printf("%s:%s: failed to get folder infos \n", G_STRLOC, G_STRFUNC); + camel_exception_clear(&ex); + } i++; - while (e_iterator_is_valid (iter)) { - EAccount *account = (EAccount *) e_iterator_get (iter); - EAccountService *service; - const char *name; - - service = account->source; - name = account->name; - if (account->enabled - && service->url != NULL - && service->url[0] - && strncmp(service->url, "mbox:", 5) != 0) { - - CamelException ex; - - camel_exception_init (&ex); - mail_component_load_store_by_uri (component, service->url, name); - - store = (CamelStore *) camel_session_get_service (session, service->url, CAMEL_PROVIDER_STORE, &ex); - info = camel_store_get_folder_info (store, NULL, CAMEL_STORE_FOLDER_INFO_RECURSIVE|CAMEL_STORE_FOLDER_INFO_FAST|CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, &ex); - if (info) { - GThread *thread; - struct migrate_folders_to_db_structure migrate_dbs; - - migrate_dbs.ex = ex; - migrate_dbs.account_name = account->name; - migrate_dbs.info = info; - migrate_dbs.store = store; - migrate_dbs.done = FALSE; - - thread = g_thread_create ((GThreadFunc) migrate_folders_to_db_thread, &migrate_dbs, TRUE, NULL); - while (!migrate_dbs.done) - g_main_context_iteration (NULL, TRUE); - } else - printf("%s:%s: failed to get folder infos \n", G_STRLOC, G_STRFUNC); - camel_exception_clear(&ex); - } - i++; - e_iterator_next (iter); - } - //camel_session_set_online ((CamelSession *) session, TRUE); - g_object_unref (iter); - em_migrate_close_progress_dialog (); + e_iterator_next (iter); + + } + + //camel_session_set_online ((CamelSession *) session, TRUE); + + g_object_unref (iter); + em_migrate_close_progress_dialog (); + + g_object_unref (session); } - -int -em_migrate (const char *evolution_dir, int major, int minor, int revision, CamelException *ex) +gboolean +e_mail_shell_module_migrate (EShellModule *shell_module, + gint major, + gint minor, + gint micro, + GError **error) { struct stat st; - char *path; + const gchar *data_dir; + gchar *path; /* make sure ~/.evolution/mail exists */ - path = g_build_filename (evolution_dir, "mail", NULL); - if (g_stat (path, &st) == -1) { - if (errno != ENOENT || g_mkdir_with_parents (path, 0777) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Unable to create local mail folders at `%s': %s"), - path, g_strerror (errno)); - g_free (path); - return -1; + data_dir = e_shell_module_get_data_dir (shell_module); + if (g_stat (data_dir, &st) == -1) { + if (errno != ENOENT || g_mkdir_with_parents (data_dir, 0777) == -1) { + g_set_error ( + error, E_SHELL_MIGRATE_ERROR, + E_SHELL_MIGRATE_ERROR_FAILED, + _("Unable to create local mail folders at " + "`%s': %s"), data_dir, g_strerror (errno)); + return FALSE; } } - g_free (path); - if (major == 0) - return emm_setup_initial(evolution_dir); + return emm_setup_initial (data_dir); if (major == 1 && minor < 5) { #ifndef G_OS_WIN32 @@ -3071,46 +3012,46 @@ em_migrate (const char *evolution_dir, int major, int minor, int revision, Camel path = g_build_filename (g_get_home_dir (), "evolution", NULL); if (minor <= 2 && !(config_xmldb = emm_load_xml (path, "config.xmldb"))) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Unable to read settings from previous Evolution install, " - "`evolution/config.xmldb' does not exist or is corrupt.")); - g_free (path); - return -1; + g_set_error ( + error, E_SHELL_MIGRATE_ERROR, + E_SHELL_MIGRATE_ERROR_FAILED, + _("Unable to read settings from previous " + "Evolution install, `evolution/config.xmldb' " + "does not exist or is corrupt.")); + return FALSE; } filters = emm_load_xml (path, "filters.xml"); vfolders = emm_load_xml (path, "vfolders.xml"); g_free (path); if (minor == 0) { - if (em_migrate_1_0 (evolution_dir, config_xmldb, filters, vfolders, ex) == -1) { + if (!em_migrate_1_0 (data_dir, config_xmldb, filters, vfolders, error)) { xmlFreeDoc (config_xmldb); xmlFreeDoc (filters); xmlFreeDoc (vfolders); - return -1; + return FALSE; } } if (minor <= 2) { - if (em_migrate_1_2 (evolution_dir, config_xmldb, filters, vfolders, ex) == -1) { + if (!em_migrate_1_2 (data_dir, config_xmldb, filters, vfolders, error)) { xmlFreeDoc (config_xmldb); xmlFreeDoc (filters); xmlFreeDoc (vfolders); - return -1; + return FALSE; } xmlFreeDoc (config_xmldb); } if (minor <= 4) { - if (em_migrate_1_4 (evolution_dir, filters, vfolders, ex) == -1) { + if (!em_migrate_1_4 (data_dir, filters, vfolders, error)) { xmlFreeDoc (filters); xmlFreeDoc (vfolders); - return -1; + return FALSE; } } - path = g_build_filename (evolution_dir, "mail", NULL); - if (filters) { emm_save_xml (filters, path, "filters.xml"); xmlFreeDoc (filters); @@ -3141,8 +3082,8 @@ em_migrate (const char *evolution_dir, int major, int minor, int revision, Camel if (major < 2 || (major == 2 && minor < 24)) { em_update_sa_junk_setting_2_23 (); - migrate_to_db (); + migrate_to_db (shell_module); } - return 0; + return TRUE; } diff --git a/mail/em-migrate.h b/mail/e-mail-shell-module-migrate.h index c755ef9b39..e9ec2115c0 100644 --- a/mail/em-migrate.h +++ b/mail/e-mail-shell-module-migrate.h @@ -1,4 +1,6 @@ /* + * e-mail-shell-module-migrate.h + * * 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 @@ -13,27 +15,24 @@ * License along with the program; if not, see <http://www.gnu.org/licenses/> * * - * Authors: - * Jeffrey Stedfast <fejj@ximian.com> - * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * */ -#ifndef __EM_MIGRATE_H__ -#define __EM_MIGRATE_H__ +#ifndef E_MAIL_SHELL_MODULE_MIGRATE_H +#define E_MAIL_SHELL_MODULE_MIGRATE_H -#include <camel/camel-exception.h> +#include <glib.h> +#include <shell/e-shell-module.h> -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ +G_BEGIN_DECLS -int em_migrate (const char *evolution_dir, int major, int minor, int revision, CamelException *ex); +gboolean e_mail_shell_module_migrate (EShellModule *shell_module, + gint major, + gint minor, + gint micro, + GError **error); -#ifdef __cplusplus -} -#endif /* __cplusplus */ +G_END_DECLS -#endif /* __EM_MIGRATE_H__ */ +#endif /* E_MAIL_SHELL_MODULE_MIGRATE_H */ diff --git a/mail/e-mail-shell-module-settings.c b/mail/e-mail-shell-module-settings.c new file mode 100644 index 0000000000..94bfd1ac11 --- /dev/null +++ b/mail/e-mail-shell-module-settings.c @@ -0,0 +1,521 @@ +/* + * e-mail-shell-module-settings.c + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-shell-module-settings.h" + +#include <gconf/gconf-client.h> +#include <libedataserver/e-account-list.h> + +#include "e-util/e-signature-list.h" +#include "mail/e-mail-label-list-store.h" +#include "mail/mail-session.h" + +void +e_mail_shell_module_init_settings (EShell *shell) +{ + EShellSettings *shell_settings; + gpointer object; + + shell_settings = e_shell_get_shell_settings (shell); + + /* XXX Default values should match the GConf schema. + * Yes it's redundant, but we're stuck with GConf. */ + + /*** Global Objects ***/ + + e_shell_settings_install_property ( + g_param_spec_object ( + "mail-label-list-store", + NULL, + NULL, + E_TYPE_MAIL_LABEL_LIST_STORE, + G_PARAM_READWRITE)); + + object = e_mail_label_list_store_new (); + e_shell_settings_set_object ( + shell_settings, "mail-label-list-store", object); + g_object_unref (object); + + e_shell_settings_install_property ( + g_param_spec_pointer ( + "mail-session", + NULL, + NULL, + G_PARAM_READWRITE)); + + camel_object_ref (session); + e_shell_settings_set_pointer ( + shell_settings, "mail-session", session); + + /*** Mail Preferences ***/ + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-address-compress", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-address-compress", + "/apps/evolution/mail/display/address_compress"); + + e_shell_settings_install_property ( + g_param_spec_int ( + "mail-address-count", + NULL, + NULL, + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-address-count", + "/apps/evolution/mail/display/address_count"); + + e_shell_settings_install_property ( + g_param_spec_string ( + "mail-charset-default", + NULL, + NULL, + NULL, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-charset-default", + "/apps/evolution/mail/display/charset"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-check-for-junk", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-check-for-junk", + "/apps/evolution/mail/junk/check_incoming"); + + e_shell_settings_install_property ( + g_param_spec_string ( + "mail-citation-color", + NULL, + NULL, + "#737373", + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-citation-color", + "/apps/evolution/mail/display/citation_colour"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-confirm-expunge", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-confirm-expunge", + "/apps/evolution/mail/prompts/expunge"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-confirm-unwanted-html", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-confirm-unwanted-html", + "/apps/evolution/mail/prompts/unwanted_html"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-empty-trash-on-exit", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-empty-trash-on-exit", + "/apps/evolution/mail/trash/empty_on_exit"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-enable-search-folders", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-enable-search-folders", + "/apps/evolution/mail/display/enable_vfolders"); + + e_shell_settings_install_property ( + g_param_spec_string ( + "mail-font-monospace", + NULL, + NULL, + "", + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-font-monospace", + "/apps/evolution/mail/display/fonts/monospace"); + + e_shell_settings_install_property ( + g_param_spec_string ( + "mail-font-variable", + NULL, + NULL, + "", + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-font-variable", + "/apps/evolution/mail/display/fonts/variable"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-force-message-limit", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-force-message-limit", + "/apps/evolution/mail/display/force_message_limit"); + + /* This value corresponds to MailConfigForwardStyle enum. */ + e_shell_settings_install_property ( + g_param_spec_int ( + "mail-forward-style", + NULL, + NULL, + 0, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-forward-style", + "/apps/evolution/mail/format/forward_style"); + + /* This value corresponds to MailConfigHTTPMode enum. */ + e_shell_settings_install_property ( + g_param_spec_int ( + "mail-image-loading-policy", + NULL, + NULL, + 0, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-image-loading-policy", + "/apps/evolution/mail/display/load_http_images"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-magic-spacebar", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-magic-spacebar", + "/apps/evolution/mail/display/magic_spacebar"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-mark-citations", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-mark-citations", + "/apps/evolution/mail/display/mark_citations"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-mark-seen", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-mark-seen", + "/apps/evolution/mail/display/mark_seen"); + + e_shell_settings_install_property ( + g_param_spec_int ( + "mail-mark-seen-timeout", + NULL, + NULL, + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-mark-seen-timeout", + "/apps/evolution/mail/display/mark_seen_timeout"); + + e_shell_settings_install_property ( + g_param_spec_int ( + "mail-message-text-part-limit", + NULL, + NULL, + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-message-text-part-limit", + "/apps/evolution/mail/display/message_text_part_limit"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-only-local-photos", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-only-local-photos", + "/apps/evolution/mail/display/photo_local"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-prompt-delete-in-vfolder", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-prompt-delete-in-vfolder", + "/apps/evolution/mail/prompts/delete_in_vfolder"); + + /* This value corresponds to MailConfigReplyStyle enum, + * but the ordering of the combo box items in preferences + * has changed. We use transformation functions there. */ + e_shell_settings_install_property ( + g_param_spec_int ( + "mail-reply-style", + NULL, + NULL, + 0, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-reply-style", + "/apps/evolution/mail/format/reply_style"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-show-animated-images", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-show-animated-images", + "/apps/evolution/mail/display/animated_images"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-show-sender-photo", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-show-sender-photo", + "/apps/evolution/mail/display/sender_photo"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "mail-use-custom-fonts", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "mail-use-custom-fonts", + "/apps/evolution/mail/display/fonts/use_custom"); + + + /*** Composer Preferences ***/ + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "composer-format-html", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "composer-format-html", + "/apps/evolution/mail/composer/send_html"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "composer-inline-spelling", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "composer-inline-spelling", + "/apps/evolution/mail/composer/inline_spelling"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "composer-magic-links", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "composer-magic-links", + "/apps/evolution/mail/composer/magic_links"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "composer-magic-smileys", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "composer-magic-smileys", + "/apps/evolution/mail/composer/magic_smileys"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "composer-outlook-filenames", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "composer-outlook-filenames", + "/apps/evolution/mail/composer/outlook_filenames"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "composer-prompt-only-bcc", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "composer-prompt-only-bcc", + "/apps/evolution/mail/prompts/only_bcc"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "composer-prompt-empty-subject", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "composer-prompt-empty-subject", + "/apps/evolution/mail/prompts/empty_subject"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "composer-reply-start-bottom", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "composer-reply-start-bottom", + "/apps/evolution/mail/composer/reply_start_bottom"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "composer-request-receipt", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "composer-request-receipt", + "/apps/evolution/mail/composer/request_receipt"); + + e_shell_settings_install_property ( + g_param_spec_string ( + "composer-spell-color", + NULL, + NULL, + "#ff0000", + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "composer-spell-color", + "/apps/evolution/mail/composer/spell_color"); + + e_shell_settings_install_property ( + g_param_spec_boolean ( + "composer-top-signature", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_shell_settings_bind_to_gconf ( + shell_settings, "composer-top-signature", + "/apps/evolution/mail/composer/top_signature"); +} diff --git a/mail/mail-crypto.h b/mail/e-mail-shell-module-settings.h index dbe1e6f86b..a5528463c7 100644 --- a/mail/mail-crypto.h +++ b/mail/e-mail-shell-module-settings.h @@ -1,4 +1,6 @@ /* + * e-mail-shell-module-settings.h + * * 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 @@ -10,31 +12,22 @@ * 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/> - * + * License along with the program; if not, see <http://www.gnu.org/licenses/> * - * Authors: - * Jeffrey Stedfast <fejj@ximian.com> * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * */ -#ifndef MAIL_CRYPTO_H -#define MAIL_CRYPTO_H +#ifndef E_MAIL_SHELL_MODULE_SETTINGS_H +#define E_MAIL_SHELL_MODULE_SETTINGS_H -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ +#include <shell/e-shell.h> -struct _EAccount; +G_BEGIN_DECLS -/* PGP/MIME convenience wrappers */ -struct _CamelCipherContext *mail_crypto_get_pgp_cipher_context(struct _EAccount *account); +void e_mail_shell_module_init_settings (EShell *shell); -#ifdef __cplusplus -} -#endif /* __cplusplus */ +G_END_DECLS -#endif /* ! MAIL_CRYPTO_H */ +#endif /* E_MAIL_SHELL_MODULE_SETTINGS_H */ diff --git a/mail/e-mail-shell-module.c b/mail/e-mail-shell-module.c new file mode 100644 index 0000000000..4a0fcf0b38 --- /dev/null +++ b/mail/e-mail-shell-module.c @@ -0,0 +1,1166 @@ +/* + * e-mail-shell-module.c + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <glib/gi18n.h> +#include <camel/camel-disco-store.h> +#include <camel/camel-offline-store.h> +#include <camel/camel-session.h> +#include <camel/camel-url.h> + +#include "e-util/e-account-utils.h" +#include "e-util/e-binding.h" +#include "e-util/e-import.h" +#include "e-util/e-util.h" +#include "shell/e-shell.h" +#include "shell/e-shell-window.h" +#include "composer/e-msg-composer.h" +#include "widgets/misc/e-preferences-window.h" + +#include "e-mail-shell-view.h" +#include "e-mail-shell-module.h" +#include "e-mail-shell-module-migrate.h" +#include "e-mail-shell-module-settings.h" + +#include "e-attachment-handler-mail.h" +#include "e-mail-browser.h" +#include "e-mail-reader.h" +#include "em-account-prefs.h" +#include "em-composer-prefs.h" +#include "em-composer-utils.h" +#include "em-config.h" +#include "em-event.h" +#include "em-folder-tree-model.h" +#include "em-folder-utils.h" +#include "em-format-hook.h" +#include "em-format-html-display.h" +#include "em-junk-hook.h" +#include "em-mailer-prefs.h" +#include "em-network-prefs.h" +#include "em-utils.h" +#include "mail-config.h" +#include "mail-folder-cache.h" +#include "mail-mt.h" +#include "mail-ops.h" +#include "mail-send-recv.h" +#include "mail-session.h" +#include "mail-vfolder.h" +#include "importers/mail-importer.h" + +#define MODULE_NAME "mail" +#define MODULE_ALIASES "" +#define MODULE_SCHEMES "mailto:email" +#define MODULE_SORT_ORDER 200 + +typedef struct _StoreInfo StoreInfo; + +/* XXX Temporary */ +CamelStore *vfolder_store; + +struct _StoreInfo { + CamelStore *store; + gint ref_count; + gchar *name; + + /* Keep a reference to these so they remain around for the session. */ + CamelFolder *vtrash; + CamelFolder *vjunk; + + /* Initialization callback. */ + void (*done) (CamelStore *store, + CamelFolderInfo *info, + gpointer user_data); + gpointer done_user_data; + + guint removed : 1; +}; + +/* Module Entry Point */ +void e_shell_module_init (GTypeModule *type_module); + +/* The array elements correspond to EMailFolderType. */ +static struct { + gchar *name; + gchar *uri; + CamelFolder *folder; +} default_local_folders[] = { + { N_("Inbox") }, + { N_("Drafts") }, + { N_("Outbox") }, + { N_("Sent") }, + { N_("Templates") }, + { "Inbox" } /* "always local" inbox */ +}; + +/* XXX So many things need the shell module that it's + * just easier for now to make it globally available. + * We should fix this, though. */ +EShellModule *mail_shell_module = NULL; + +static GHashTable *store_hash; +static MailAsyncEvent *async_event; +static EMFolderTreeModel *folder_tree_model; +static CamelStore *local_store; + +static gint mail_sync_in_progress; +static guint mail_sync_timeout_source_id; + +extern gint camel_application_is_exiting; + +static StoreInfo * +store_info_new (CamelStore *store, + const gchar *name) +{ + CamelService *service; + StoreInfo *si; + + g_return_val_if_fail (CAMEL_IS_STORE (store), NULL); + + service = CAMEL_SERVICE (store); + + si = g_slice_new0 (StoreInfo); + si->ref_count = 1; + + if (name == NULL) + si->name = camel_service_get_name (service, TRUE); + else + si->name = g_strdup (name); + + si->store = store; + camel_object_ref (store); + + /* If these are vfolders then they need to be opened now, + * otherwise they won't keep track of all folders. */ + if (store->flags & CAMEL_STORE_VTRASH) + si->vtrash = camel_store_get_trash (store, NULL); + if (store->flags & CAMEL_STORE_VJUNK) + si->vjunk = camel_store_get_junk (store, NULL); + + return si; +} + +static StoreInfo * +store_info_ref (StoreInfo *si) +{ + g_return_val_if_fail (si != NULL, si); + g_return_val_if_fail (si->ref_count > 0, si); + + g_atomic_int_add (&si->ref_count, 1); + + return si; +} + +static void +store_info_unref (StoreInfo *si) +{ + g_return_if_fail (si != NULL); + g_return_if_fail (si->ref_count > 0); + + if (g_atomic_int_exchange_and_add (&si->ref_count, -1) > 1) + return; + + if (si->vtrash != NULL) + camel_object_unref (si->vtrash); + if (si->vjunk != NULL) + camel_object_unref (si->vjunk); + camel_object_unref (si->store); + g_free (si->name); + + g_slice_free (StoreInfo, si); +} + +static void +store_hash_free (StoreInfo *si) +{ + si->removed = 1; + store_info_unref (si); +} + +static gboolean +mail_shell_module_add_store_done (CamelStore *store, + CamelFolderInfo *info, + gpointer user_data) +{ + StoreInfo *si = user_data; + + if (si->done != NULL) + si->done (store, info, si); + + if (!si->removed) { + /* Let the counters know about the already-opened + * junk and trash folders. */ + if (si->vtrash != NULL) + mail_note_folder (si->vtrash); + if (si->vjunk != NULL) + mail_note_folder (si->vjunk); + } + + store_info_unref (si); + + return TRUE; +} + +static void +mail_shell_module_add_store (EShellModule *shell_module, + CamelStore *store, + const gchar *name, + void (*done) (CamelStore *store, + CamelFolderInfo *info, + gpointer user_data)) +{ + StoreInfo *si; + + si = store_info_new (store, name); + si->done = done; + g_hash_table_insert (store_hash, store, si); + + em_folder_tree_model_add_store (folder_tree_model, store, si->name); + + mail_note_store ( + shell_module, store, NULL, + mail_shell_module_add_store_done, store_info_ref (si)); +} + +static void +mail_shell_module_add_local_store_done (CamelStore *store, + CamelFolderInfo *info, + gpointer unused) +{ + gint ii; + + for (ii = 0; ii < G_N_ELEMENTS (default_local_folders); ii++) { + if (default_local_folders[ii].folder != NULL) + mail_note_folder (default_local_folders[ii].folder); + } +} + +static void +mail_shell_module_add_local_store (EShellModule *shell_module, + CamelStore *local_store, + const gchar *name) +{ + mail_shell_module_add_store ( + shell_module, local_store, name, + mail_shell_module_add_local_store_done); +} + +static void +mail_shell_module_init_hooks (void) +{ + e_plugin_hook_register_type (em_config_hook_get_type ()); + e_plugin_hook_register_type (em_event_hook_get_type ()); + e_plugin_hook_register_type (em_junk_hook_get_type ()); + + /* EMFormat classes must be registered before EMFormatHook. */ + em_format_hook_register_type (em_format_get_type ()); + em_format_hook_register_type (em_format_html_get_type ()); + em_format_hook_register_type (em_format_html_display_get_type ()); + e_plugin_hook_register_type (em_format_hook_get_type ()); + + em_junk_hook_register_type (emj_get_type ()); +} + +static void +mail_shell_module_init_importers (void) +{ + EImportClass *import_class; + EImportImporter *importer; + + import_class = g_type_class_ref (e_import_get_type ()); + + importer = mbox_importer_peek (); + e_import_class_add_importer (import_class, importer, NULL, NULL); + + importer = elm_importer_peek (); + e_import_class_add_importer (import_class, importer, NULL, NULL); + + importer = pine_importer_peek (); + e_import_class_add_importer (import_class, importer, NULL, NULL); +} + +static void +mail_shell_module_init_local_store (EShellModule *shell_module) +{ + CamelException ex; + CamelService *service; + CamelURL *url; + const gchar *data_dir; + gchar *temp; + gint ii; + + camel_exception_init (&ex); + + url = camel_url_new ("mbox:", NULL); + data_dir = e_shell_module_get_data_dir (shell_module); + temp = g_build_filename (data_dir, "local", NULL); + camel_url_set_path (url, temp); + g_free (temp); + + temp = camel_url_to_string (url, 0); + service = camel_session_get_service ( + session, temp, CAMEL_PROVIDER_STORE, &ex); + g_free (temp); + + if (service == NULL) + goto fail; + + for (ii = 0; ii < G_N_ELEMENTS (default_local_folders); ii++) { + /* FIXME Should this URI be account relative? */ + camel_url_set_fragment (url, default_local_folders[ii].name); + default_local_folders[ii].uri = camel_url_to_string (url, 0); + default_local_folders[ii].folder = camel_store_get_folder ( + CAMEL_STORE (service), default_local_folders[ii].name, + CAMEL_STORE_FOLDER_CREATE, &ex); + camel_exception_clear (&ex); + } + + camel_url_free (url); + + camel_object_ref (service); + g_object_ref (shell_module); + + mail_async_event_emit ( + async_event, MAIL_ASYNC_GUI, + (MailAsyncFunc) mail_shell_module_add_local_store, + shell_module, service, _("On This Computer")); + + local_store = CAMEL_STORE (service); + + return; + +fail: + g_warning ("Could not initialize local store/folder: %s", ex.desc); + + camel_exception_clear (&ex); + camel_url_free (url); +} + +static void +mail_shell_module_load_accounts (EShellModule *shell_module) +{ + EAccountList *account_list; + EIterator *iter; + + account_list = e_get_account_list (); + + for (iter = e_list_get_iterator ((EList *) account_list); + e_iterator_is_valid (iter); e_iterator_next (iter)) { + + EAccountService *service; + EAccount *account; + const gchar *name; + const gchar *url; + + account = (EAccount *) e_iterator_get (iter); + service = account->source; + name = account->name; + url = service->url; + + if (!account->enabled) + continue; + + if (url == NULL || *url == '\0') + continue; + + /* HACK: mbox URL's are handled by the local store setup + * above. Any that come through as account sources + * are really movemail sources! */ + if (g_str_has_prefix (url, "mbox:")) + continue; + + e_mail_shell_module_load_store_by_uri ( + shell_module, url, name); + } + + g_object_unref (iter); +} + +static void +mail_shell_module_mail_icon_cb (EShellWindow *shell_window, + const gchar *icon_name) +{ + GtkAction *action; + + action = e_shell_window_get_shell_view_action ( + shell_window, MODULE_NAME); + g_object_set (action, "icon-name", icon_name, NULL); +} + +static void +action_mail_folder_new_cb (GtkAction *action, + EShellWindow *shell_window) +{ + EMFolderTree *folder_tree = NULL; + EMailShellSidebar *mail_shell_sidebar; + EShellSidebar *shell_sidebar; + EShellView *shell_view; + const gchar *view_name; + + /* Take care not to unnecessarily load the mail shell view. */ + view_name = e_shell_window_get_active_view (shell_window); + if (g_strcmp0 (view_name, MODULE_NAME) != 0) + goto exit; + + shell_view = e_shell_window_get_shell_view (shell_window, view_name); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + + mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar); + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + +exit: + em_folder_utils_create_folder ( + NULL, folder_tree, GTK_WINDOW (shell_window)); +} + +static void +action_mail_message_new_cb (GtkAction *action, + EShellWindow *shell_window) +{ + GtkWindow *window = GTK_WINDOW (shell_window); + EMailShellSidebar *mail_shell_sidebar; + EShellSidebar *shell_sidebar; + EShellView *shell_view; + EMFolderTree *folder_tree; + const gchar *view_name; + gchar *uri = NULL; + + if (!em_utils_check_user_can_send_mail (window)) + return; + + /* Take care not to unnecessarily load the mail shell view. */ + view_name = e_shell_window_get_active_view (shell_window); + if (g_strcmp0 (view_name, MODULE_NAME) != 0) + goto exit; + + shell_view = e_shell_window_get_shell_view (shell_window, view_name); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + + mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar); + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + uri = em_folder_tree_get_selected_uri (folder_tree); + +exit: + em_utils_compose_new_message (uri); + + g_free (uri); +} + +static GtkActionEntry item_entries[] = { + + { "mail-message-new", + "mail-message-new", + NC_("New", "_Mail Message"), + "<Shift><Control>m", + N_("Compose a new mail message"), + G_CALLBACK (action_mail_message_new_cb) } +}; + +static GtkActionEntry source_entries[] = { + + { "mail-folder-new", + "folder-new", + NC_("New", "Mail _Folder"), + NULL, + N_("Create a new mail folder"), + G_CALLBACK (action_mail_folder_new_cb) } +}; + +static void +mail_shell_module_init_preferences (EShell *shell) +{ + GtkWidget *preferences_window; + + preferences_window = e_shell_get_preferences_window (shell); + + e_preferences_window_add_page ( + E_PREFERENCES_WINDOW (preferences_window), + "mail-accounts", + "preferences-mail-accounts", + _("Mail Accounts"), + em_account_prefs_new (), + 100); + + e_preferences_window_add_page ( + E_PREFERENCES_WINDOW (preferences_window), + "mail", + "preferences-mail", + _("Mail Preferences"), + em_mailer_prefs_new (shell), + 300); + + e_preferences_window_add_page ( + E_PREFERENCES_WINDOW (preferences_window), + "composer", + "preferences-composer", + _("Composer Preferences"), + em_composer_prefs_new (shell), + 400); + + e_preferences_window_add_page ( + E_PREFERENCES_WINDOW (preferences_window), + "system-network-proxy", + "preferences-system-network-proxy", + _("Network Preferences"), + em_network_prefs_new (), + 500); +} + +static void +mail_shell_module_sync_store_done_cb (CamelStore *store, + gpointer user_data) +{ + mail_sync_in_progress--; +} + +static void +mail_shell_module_sync_store_cb (CamelStore *store) +{ + if (!camel_application_is_exiting) { + mail_sync_in_progress++; + mail_sync_store ( + store, FALSE, + mail_shell_module_sync_store_done_cb, NULL); + } +} + +static gboolean +mail_shell_module_mail_sync (EShellModule *shell_module) +{ + if (camel_application_is_exiting) + return FALSE; + + if (mail_sync_in_progress) + goto exit; + + if (session == NULL || !camel_session_is_online (session)) + goto exit; + + e_mail_shell_module_stores_foreach ( + shell_module, (GHFunc) + mail_shell_module_sync_store_cb, NULL); + +exit: + return !camel_application_is_exiting; +} + +static void +mail_shell_module_notify_online_cb (EShell *shell, + GParamSpec *pspec, + EShellModule *shell_module) +{ + gboolean online; + + online = e_shell_get_online (shell); + camel_session_set_online (session, online); +} + +static void +mail_shell_module_handle_email_uri_cb (gchar *folder_uri, + CamelFolder *folder, + gpointer user_data) +{ + CamelURL *url = user_data; + const gchar *forward; + const gchar *reply; + const gchar *uid; + + if (folder == NULL) { + g_warning ("Could not open folder '%s'", folder_uri); + goto exit; + } + + forward = camel_url_get_param (url, "forward"); + reply = camel_url_get_param (url, "reply"); + uid = camel_url_get_param (url, "uid"); + + if (reply != NULL) { + gint mode; + + if (g_strcmp0 (reply, "all") == 0) + mode = REPLY_MODE_ALL; + else if (g_strcmp0 (reply, "list") == 0) + mode = REPLY_MODE_LIST; + else + mode = REPLY_MODE_SENDER; + + em_utils_reply_to_message (folder, uid, NULL, mode, NULL); + + } else if (forward != NULL) { + GPtrArray *uids; + + uids = g_ptr_array_new (); + g_ptr_array_add (uids, g_strdup (uid)); + + if (g_strcmp0 (forward, "attached") == 0) + em_utils_forward_attached (folder, uids, folder_uri); + else if (g_strcmp0 (forward, "inline") == 0) + em_utils_forward_inline (folder, uids, folder_uri); + else if (g_strcmp0 (forward, "quoted") == 0) + em_utils_forward_quoted (folder, uids, folder_uri); + else + em_utils_forward_messages (folder, uids, folder_uri); + + } else { + GtkWidget *browser; + + /* FIXME Should pass in the shell module. */ + browser = e_mail_browser_new (mail_shell_module); + e_mail_reader_set_folder ( + E_MAIL_READER (browser), folder, folder_uri); + e_mail_reader_set_message ( + E_MAIL_READER (browser), uid, FALSE); + gtk_widget_show (browser); + } + +exit: + camel_url_free (url); +} + +static gboolean +mail_shell_module_handle_uri_cb (EShell *shell, + const gchar *uri, + EShellModule *shell_module) +{ + gboolean handled = TRUE; + + if (g_str_has_prefix (uri, "mailto:")) { + if (em_utils_check_user_can_send_mail (NULL)) + em_utils_compose_new_message_with_mailto (uri, NULL); + + } else if (g_str_has_prefix (uri, "email:")) { + CamelURL *url; + + url = camel_url_new (uri, NULL); + if (camel_url_get_param (url, "uid") != NULL) { + gchar *curi = em_uri_to_camel (uri); + + mail_get_folder ( + curi, 0, + mail_shell_module_handle_email_uri_cb, + url, mail_msg_unordered_push); + g_free (curi); + + } else { + g_warning ("Email URI's must include a uid parameter"); + camel_url_free (url); + } + } else + handled = FALSE; + + return TRUE; +} + +/* Helper for mail_shell_module_prepare_for_[off|on]line_cb() */ +static void +mail_shell_store_line_transition_done_cb (CamelStore *store, + gpointer user_data) +{ + EActivity *activity = user_data; + + g_object_unref (activity); +} + +/* Helper for mail_shell_module_prepare_for_offline_cb() */ +static void +mail_shell_store_prepare_for_offline_cb (CamelService *service, + gpointer unused, + EActivity *activity) +{ + if (CAMEL_IS_DISCO_STORE (service) || CAMEL_IS_OFFLINE_STORE (service)) + mail_store_set_offline ( + CAMEL_STORE (service), TRUE, + mail_shell_store_line_transition_done_cb, + g_object_ref (activity)); +} + +static void +mail_shell_module_prepare_for_offline_cb (EShell *shell, + EActivity *activity, + EShellModule *shell_module) +{ + GList *watched_windows; + GtkWidget *parent = NULL; + gboolean synchronize = FALSE; + + watched_windows = e_shell_get_watched_windows (shell); + if (watched_windows != NULL) + parent = GTK_WIDGET (watched_windows->data); + + if (e_shell_get_network_available (shell)) + synchronize = em_utils_prompt_user ( + GTK_WINDOW (parent), + "/apps/evolution/mail/prompts/quick_offline", + "mail:ask-quick-offline", NULL); + + if (!synchronize) { + mail_cancel_all (); + camel_session_set_network_state (session, FALSE); + } + + e_mail_shell_module_stores_foreach ( + shell_module, (GHFunc) + mail_shell_store_prepare_for_offline_cb, activity); +} + +/* Helper for mail_shell_module_prepare_for_online_cb() */ +static void +mail_shell_store_prepare_for_online_cb (CamelService *service, + gpointer unused, + EActivity *activity) +{ + if (CAMEL_IS_DISCO_STORE (service) || CAMEL_IS_OFFLINE_STORE (service)) + mail_store_set_offline ( + CAMEL_STORE (service), FALSE, + mail_shell_store_line_transition_done_cb, + g_object_ref (activity)); +} + +static void +mail_shell_module_prepare_for_online_cb (EShell *shell, + EActivity *activity, + EShellModule *shell_module) +{ + camel_session_set_online (session, TRUE); + + e_mail_shell_module_stores_foreach ( + shell_module, (GHFunc) + mail_shell_store_prepare_for_online_cb, activity); +} + +static void +mail_shell_module_send_receive_cb (EShell *shell, + GtkWindow *parent, + EShellModule *shell_module) +{ + em_utils_clear_get_password_canceled_accounts_flag (); + mail_send_receive (parent); +} + +static void +mail_shell_module_window_weak_notify_cb (EShell *shell, + GObject *where_the_object_was) +{ + g_signal_handlers_disconnect_by_func ( + shell, mail_shell_module_mail_icon_cb, + where_the_object_was); +} + +static void +mail_shell_module_window_created_cb (EShell *shell, + GtkWindow *window, + EShellModule *shell_module) +{ + EShellSettings *shell_settings; + static gboolean first_time = TRUE; + const gchar *module_name; + + shell_settings = e_shell_get_shell_settings (shell); + + /* This applies to both the composer and signature editor. */ + if (GTKHTML_IS_EDITOR (window)) { + GList *spell_languages; + + e_binding_new ( + G_OBJECT (shell_settings), "composer-inline-spelling", + G_OBJECT (window), "inline-spelling"); + + e_binding_new ( + G_OBJECT (shell_settings), "composer-magic-links", + G_OBJECT (window), "magic-links"); + + e_binding_new ( + G_OBJECT (shell_settings), "composer-magic-smileys", + G_OBJECT (window), "magic-smileys"); + + spell_languages = e_load_spell_languages (); + gtkhtml_editor_set_spell_languages ( + GTKHTML_EDITOR (window), spell_languages); + g_list_free (spell_languages); + } + + if (E_IS_MSG_COMPOSER (window)) { + /* Integrate the new composer into the mail module. */ + em_configure_new_composer (E_MSG_COMPOSER (window)); + return; + } + + if (!E_IS_SHELL_WINDOW (window)) + return; + + module_name = G_TYPE_MODULE (shell_module)->name; + + e_shell_window_register_new_item_actions ( + E_SHELL_WINDOW (window), module_name, + item_entries, G_N_ELEMENTS (item_entries)); + + e_shell_window_register_new_source_actions ( + E_SHELL_WINDOW (window), module_name, + source_entries, G_N_ELEMENTS (source_entries)); + + g_signal_connect_swapped ( + shell, "event::mail-icon", + G_CALLBACK (mail_shell_module_mail_icon_cb), window); + + g_object_weak_ref ( + G_OBJECT (window), (GWeakNotify) + mail_shell_module_window_weak_notify_cb, shell); + + if (first_time) { + g_signal_connect ( + window, "map-event", + G_CALLBACK (e_msg_composer_check_autosave), NULL); + first_time = FALSE; + } +} + +static void +mail_shell_module_start (EShellModule *shell_module) +{ + EShell *shell; + EShellSettings *shell_settings; + gboolean enable_search_folders; + + shell = e_shell_module_get_shell (shell_module); + shell_settings = e_shell_get_shell_settings (shell); + + /* XXX Do we really still need this flag? */ + mail_session_set_interactive (TRUE); + + enable_search_folders = e_shell_settings_get_boolean ( + shell_settings, "mail-enable-search-folders"); + if (enable_search_folders) + vfolder_load_storage (); + + mail_autoreceive_init (shell_module, session); + + if (g_getenv ("CAMEL_FLUSH_CHANGES") != NULL) + mail_sync_timeout_source_id = g_timeout_add_seconds ( + mail_config_get_sync_timeout (), + (GSourceFunc) mail_shell_module_mail_sync, + shell_module); +} + +static EShellModuleInfo module_info = { + + MODULE_NAME, + MODULE_ALIASES, + MODULE_SCHEMES, + MODULE_SORT_ORDER, + + mail_shell_module_start, + /* is_busy */ NULL, + /* shutdown */ NULL, + e_mail_shell_module_migrate +}; + +void +e_shell_module_init (GTypeModule *type_module) +{ + EShell *shell; + EShellModule *shell_module; + + shell_module = E_SHELL_MODULE (type_module); + shell = e_shell_module_get_shell (shell_module); + + e_shell_module_set_info ( + shell_module, &module_info, + e_mail_shell_view_get_type (type_module)); + + /* This also initializes Camel, so it needs to happen early. */ + mail_session_init (shell_module); + + mail_shell_module_init_hooks (); + mail_shell_module_init_importers (); + + e_attachment_handler_mail_get_type (); + + /* XXX This never gets unreffed. */ + mail_shell_module = g_object_ref (shell_module); + + store_hash = g_hash_table_new_full ( + g_direct_hash, g_direct_equal, + (GDestroyNotify) NULL, + (GDestroyNotify) store_hash_free); + + async_event = mail_async_event_new (); + + folder_tree_model = em_folder_tree_model_new (shell_module); + + g_signal_connect ( + shell, "notify::online", + G_CALLBACK (mail_shell_module_notify_online_cb), + shell_module); + + g_signal_connect ( + shell, "handle-uri", + G_CALLBACK (mail_shell_module_handle_uri_cb), + shell_module); + + g_signal_connect ( + shell, "prepare-for-offline", + G_CALLBACK (mail_shell_module_prepare_for_offline_cb), + shell_module); + + g_signal_connect ( + shell, "prepare-for-online", + G_CALLBACK (mail_shell_module_prepare_for_online_cb), + shell_module); + + g_signal_connect ( + shell, "send-receive", + G_CALLBACK (mail_shell_module_send_receive_cb), + shell_module); + + g_signal_connect ( + shell, "window-created", + G_CALLBACK (mail_shell_module_window_created_cb), + shell_module); + + mail_config_init (); + mail_msg_init (); + + mail_shell_module_init_local_store (shell_module); + mail_shell_module_load_accounts (shell_module); + + /* Initialize settings before initializing preferences, + * since the preferences bind to the shell settings. */ + e_mail_shell_module_init_settings (shell); + mail_shell_module_init_preferences (shell); +} + +/******************************** Public API *********************************/ + +CamelFolder * +e_mail_shell_module_get_folder (EShellModule *shell_module, + EMailFolderType folder_type) +{ + g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), NULL); + + return default_local_folders[folder_type].folder; +} + +const gchar * +e_mail_shell_module_get_folder_uri (EShellModule *shell_module, + EMailFolderType folder_type) +{ + g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), NULL); + + return default_local_folders[folder_type].uri; +} + +EMFolderTreeModel * +e_mail_shell_module_get_folder_tree_model (EShellModule *shell_module) +{ + /* Require a shell module in case we need it in the future. */ + g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), NULL); + + return folder_tree_model; +} + +void +e_mail_shell_module_add_store (EShellModule *shell_module, + CamelStore *store, + const gchar *name) +{ + g_return_if_fail (E_IS_SHELL_MODULE (shell_module)); + g_return_if_fail (CAMEL_IS_STORE (store)); + g_return_if_fail (name != NULL); + + mail_shell_module_add_store (shell_module, store, name, NULL); +} + +CamelStore * +e_mail_shell_module_get_local_store (EShellModule *shell_module) +{ + g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), NULL); + g_return_val_if_fail (local_store != NULL, NULL); + + return local_store; +} + +CamelStore * +e_mail_shell_module_load_store_by_uri (EShellModule *shell_module, + const gchar *uri, + const gchar *name) +{ + CamelStore *store; + CamelProvider *provider; + CamelException ex; + + g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), NULL); + g_return_val_if_fail (uri != NULL, NULL); + g_return_val_if_fail (name != NULL, NULL); + + camel_exception_init (&ex); + + /* Load the service, but don't connect. Check its provider, + * and if this belongs in the shell's folder list, add it. */ + + provider = camel_provider_get (uri, &ex); + if (provider == NULL) + goto fail; + + if (!(provider->flags & CAMEL_PROVIDER_IS_STORAGE)) + return NULL; + + store = (CamelStore *) camel_session_get_service ( + session, uri, CAMEL_PROVIDER_STORE, &ex); + if (store == NULL) + goto fail; + + e_mail_shell_module_add_store (shell_module, store, name); + + camel_object_unref (store); + + return store; + +fail: + /* FIXME: Show an error dialog. */ + g_warning ( + "Couldn't get service: %s: %s", uri, + camel_exception_get_description (&ex)); + camel_exception_clear (&ex); + + return NULL; +} + +/* Helper for e_mail_shell_module_remove_store() */ +static void +mail_shell_module_remove_store_cb (CamelStore *store, + gpointer event_data, + gpointer user_data) +{ + camel_service_disconnect (CAMEL_SERVICE (store), TRUE, NULL); + camel_object_unref (store); +} + +void +e_mail_shell_module_remove_store (EShellModule *shell_module, + CamelStore *store) +{ + g_return_if_fail (E_IS_SHELL_MODULE (shell_module)); + g_return_if_fail (CAMEL_IS_STORE (store)); + + /* Because the store hash holds a reference to each store used + * as a key in it, none of them will ever be gc'ed, meaning any + * call to camel_session_get_{service,store} with the same URL + * will always return the same object. So this works. */ + + if (g_hash_table_lookup (store_hash, store) == NULL) + return; + + camel_object_ref (store); + g_hash_table_remove (store_hash, store); + mail_note_store_remove (store); + em_folder_tree_model_remove_store (folder_tree_model, store); + + mail_async_event_emit ( + async_event, MAIL_ASYNC_THREAD, + (MailAsyncFunc) mail_shell_module_remove_store_cb, + store, NULL, NULL); +} + +void +e_mail_shell_module_remove_store_by_uri (EShellModule *shell_module, + const gchar *uri) +{ + CamelStore *store; + CamelProvider *provider; + + g_return_if_fail (E_IS_SHELL_MODULE (shell_module)); + g_return_if_fail (uri != NULL); + + provider = camel_provider_get (uri, NULL); + if (provider == NULL) + return; + + if (!(provider->flags & CAMEL_PROVIDER_IS_STORAGE)) + return; + + store = (CamelStore *) camel_session_get_service ( + session, uri, CAMEL_PROVIDER_STORE, NULL); + if (store != NULL) { + e_mail_shell_module_remove_store (shell_module, store); + camel_object_unref (store); + } +} + +void +e_mail_shell_module_stores_foreach (EShellModule *shell_module, + GHFunc func, + gpointer user_data) +{ + GHashTableIter iter; + gpointer key, value; + + g_return_if_fail (E_IS_SHELL_MODULE (shell_module)); + g_return_if_fail (func != NULL); + + g_hash_table_iter_init (&iter, store_hash); + + while (g_hash_table_iter_next (&iter, &key, &value)) + func (key, ((StoreInfo *) value)->name, user_data); +} + +/******************* Code below here belongs elsewhere. *******************/ + +#include "filter/filter-option.h" +#include "shell/e-shell-settings.h" +#include "mail/e-mail-label-list-store.h" + +GSList * +e_mail_labels_get_filter_options (void) +{ + EShell *shell; + EShellSettings *shell_settings; + EMailLabelListStore *list_store; + GtkTreeModel *model; + GtkTreeIter iter; + GSList *list = NULL; + gboolean valid; + + shell = e_shell_get_default (); + shell_settings = e_shell_get_shell_settings (shell); + list_store = e_shell_settings_get_object ( + shell_settings, "mail-label-list-store"); + + model = GTK_TREE_MODEL (list_store); + valid = gtk_tree_model_get_iter_first (model, &iter); + + while (valid) { + struct _filter_option *option; + gchar *name, *tag; + + name = e_mail_label_list_store_get_name (list_store, &iter); + tag = e_mail_label_list_store_get_tag (list_store, &iter); + + option = g_new0 (struct _filter_option, 1); + option->title = e_str_without_underscores (name); + option->value = tag; /* takes ownership */ + + g_free (name); + + valid = gtk_tree_model_iter_next (model, &iter); + } + + g_object_unref (list_store); + + return list; +} diff --git a/mail/e-mail-shell-module.h b/mail/e-mail-shell-module.h new file mode 100644 index 0000000000..d72df698a5 --- /dev/null +++ b/mail/e-mail-shell-module.h @@ -0,0 +1,84 @@ +/* + * e-mail-shell-module.h + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MAIL_SHELL_MODULE_H +#define E_MAIL_SHELL_MODULE_H + +#include <shell/e-shell-module.h> + +#include <camel/camel-folder.h> +#include <camel/camel-store.h> +#include <e-util/e-signature-list.h> +#include <libedataserver/e-account-list.h> + +G_BEGIN_DECLS + +/* Globally available shell module. + * + * XXX I don't like having this globally available but passing it around + * to all the various utilities that need to access the module's data + * directory and local folders is too much of a pain for now. */ +extern EShellModule *mail_shell_module; + +typedef enum { + E_MAIL_FOLDER_INBOX, + E_MAIL_FOLDER_DRAFTS, + E_MAIL_FOLDER_OUTBOX, + E_MAIL_FOLDER_SENT, + E_MAIL_FOLDER_TEMPLATES, + E_MAIL_FOLDER_LOCAL_INBOX +} EMailFolderType; + +struct _EMFolderTreeModel; + +CamelFolder * e_mail_shell_module_get_folder (EShellModule *shell_module, + EMailFolderType folder_type); +const gchar * e_mail_shell_module_get_folder_uri + (EShellModule *shell_module, + EMailFolderType folder_type); +struct _EMFolderTreeModel * + e_mail_shell_module_get_folder_tree_model + (EShellModule *shell_module); +void e_mail_shell_module_add_store (EShellModule *shell_module, + CamelStore *store, + const gchar *name); +CamelStore * e_mail_shell_module_get_local_store + (EShellModule *shell_module); +CamelStore * e_mail_shell_module_load_store_by_uri + (EShellModule *shell_module, + const gchar *uri, + const gchar *name); +void e_mail_shell_module_remove_store(EShellModule *shell_module, + CamelStore *store); +void e_mail_shell_module_remove_store_by_uri + (EShellModule *shell_module, + const gchar *uri); +void e_mail_shell_module_stores_foreach + (EShellModule *shell_module, + GHFunc func, + gpointer user_data); + +/* XXX Find a better place for this function. */ +GSList * e_mail_labels_get_filter_options(void); + +G_END_DECLS + +#endif /* E_MAIL_SHELL_MODULE_H */ diff --git a/mail/e-mail-shell-sidebar.c b/mail/e-mail-shell-sidebar.c new file mode 100644 index 0000000000..c448be9782 --- /dev/null +++ b/mail/e-mail-shell-sidebar.c @@ -0,0 +1,341 @@ +/* + * e-mail-shell-sidebar.c + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-shell-sidebar.h" + +#include <string.h> +#include <camel/camel.h> + +#include "em-utils.h" +#include "em-folder-utils.h" + +#include "e-mail-shell-module.h" + +#define E_MAIL_SHELL_SIDEBAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_SHELL_SIDEBAR, EMailShellSidebarPrivate)) + +struct _EMailShellSidebarPrivate { + GtkWidget *folder_tree; +}; + +enum { + PROP_0, + PROP_FOLDER_TREE +}; + +static gpointer parent_class; + +static void +mail_shell_sidebar_selection_changed_cb (EShellSidebar *shell_sidebar, + GtkTreeSelection *selection) +{ + EShellView *shell_view; + EShellViewClass *shell_view_class; + GtkTreeModel *model; + GtkTreeIter iter; + const gchar *icon_name; + gchar *display_name = NULL; + gboolean is_folder = FALSE; + guint flags = 0; + + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); + + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + gtk_tree_model_get ( + model, &iter, + COL_STRING_DISPLAY_NAME, &display_name, + COL_BOOL_IS_FOLDER, &is_folder, + COL_UINT_FLAGS, &flags, -1); + + if (is_folder) + icon_name = em_folder_utils_get_icon_name (flags); + else { + icon_name = shell_view_class->icon_name; + display_name = g_strdup (shell_view_class->label); + } + + e_shell_sidebar_set_icon_name (shell_sidebar, icon_name); + e_shell_sidebar_set_primary_text (shell_sidebar, display_name); + + g_free (display_name); +} + +static void +mail_shell_sidebar_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_FOLDER_TREE: + g_value_set_object ( + value, e_mail_shell_sidebar_get_folder_tree ( + E_MAIL_SHELL_SIDEBAR (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +mail_shell_sidebar_dispose (GObject *object) +{ + EMailShellSidebarPrivate *priv; + + priv = E_MAIL_SHELL_SIDEBAR_GET_PRIVATE (object); + + if (priv->folder_tree != NULL) { + g_object_unref (priv->folder_tree); + priv->folder_tree = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +mail_shell_sidebar_finalize (GObject *object) +{ + EMailShellSidebarPrivate *priv; + + priv = E_MAIL_SHELL_SIDEBAR_GET_PRIVATE (object); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +mail_shell_sidebar_constructed (GObject *object) +{ + EMailShellSidebarPrivate *priv; + EShellSidebar *shell_sidebar; + EShellModule *shell_module; + EShellView *shell_view; + GtkTreeSelection *selection; + GtkTreeView *tree_view; + GtkWidget *container; + GtkWidget *widget; + + priv = E_MAIL_SHELL_SIDEBAR_GET_PRIVATE (object); + + /* Chain up to parent's constructed method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + shell_sidebar = E_SHELL_SIDEBAR (object); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_module = e_shell_view_get_shell_module (shell_view); + + /* Build sidebar widgets. */ + + container = GTK_WIDGET (object); + + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); + + container = widget; + + widget = em_folder_tree_new (shell_module); + em_folder_tree_set_excluded (EM_FOLDER_TREE (widget), 0); + em_folder_tree_enable_drag_and_drop (EM_FOLDER_TREE (widget)); + gtk_container_add (GTK_CONTAINER (container), widget); + priv->folder_tree = g_object_ref (widget); + gtk_widget_show (widget); + + tree_view = GTK_TREE_VIEW (priv->folder_tree); + selection = gtk_tree_view_get_selection (tree_view); + + g_signal_connect_swapped ( + selection, "changed", + G_CALLBACK (mail_shell_sidebar_selection_changed_cb), + shell_sidebar); +} + +static guint32 +mail_shell_sidebar_check_state (EShellSidebar *shell_sidebar) +{ + EMailShellSidebar *mail_shell_sidebar; + EShellModule *shell_module; + EShellView *shell_view; + EMFolderTree *folder_tree; + GtkTreeSelection *selection; + GtkTreeView *tree_view; + GtkTreeModel *model; + GtkTreeIter iter; + CamelFolder *folder; + CamelStore *local_store; + CamelStore *store; + gchar *full_name; + gchar *uri; + gboolean allows_children = TRUE; + gboolean can_delete = TRUE; + gboolean is_junk = FALSE; + gboolean is_outbox = FALSE; + gboolean is_store; + gboolean is_trash = FALSE; + guint32 folder_flags = 0; + guint32 state = 0; + + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + shell_module = e_shell_view_get_shell_module (shell_view); + local_store = e_mail_shell_module_get_local_store (shell_module); + + mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar); + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + tree_view = GTK_TREE_VIEW (folder_tree); + + selection = gtk_tree_view_get_selection (tree_view); + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + return 0; + + gtk_tree_model_get ( + model, &iter, + COL_POINTER_CAMEL_STORE, &store, + COL_STRING_FULL_NAME, &full_name, + COL_BOOL_IS_STORE, &is_store, + COL_UINT_FLAGS, &folder_flags, + COL_STRING_URI, &uri, -1); + + if (!is_store) { + is_junk = (strcmp (full_name, CAMEL_VJUNK_NAME) == 0); + is_trash = (strcmp (full_name, CAMEL_VTRASH_NAME) == 0); + allows_children = !(is_junk || is_trash); + + /* Don't allow deletion of special local folders. */ + if (store == local_store) + can_delete = + (strcmp (full_name, "Drafts") != 0) && + (strcmp (full_name, "Inbox") != 0) && + (strcmp (full_name, "Outbox") != 0) && + (strcmp (full_name, "Sent") != 0) && + (strcmp (full_name, "Templates") != 0); + + folder = em_folder_tree_get_selected_folder (folder_tree); + is_outbox = em_utils_folder_is_outbox (folder, NULL); + can_delete &= !(folder_flags & CAMEL_FOLDER_SYSTEM); + } + + if (allows_children) + state |= E_MAIL_SHELL_SIDEBAR_FOLDER_ALLOWS_CHILDREN; + if (can_delete) + state |= E_MAIL_SHELL_SIDEBAR_FOLDER_CAN_DELETE; + if (is_junk) + state |= E_MAIL_SHELL_SIDEBAR_FOLDER_IS_JUNK; + if (is_outbox) + state |= E_MAIL_SHELL_SIDEBAR_FOLDER_IS_OUTBOX; + if (is_store) + state |= E_MAIL_SHELL_SIDEBAR_FOLDER_IS_STORE; + if (is_trash) + state |= E_MAIL_SHELL_SIDEBAR_FOLDER_IS_TRASH; + + return state; +} + +static void +mail_shell_sidebar_class_init (EMailShellSidebarClass *class) +{ + GObjectClass *object_class; + EShellSidebarClass *shell_sidebar_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMailShellSidebarPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->get_property = mail_shell_sidebar_get_property; + object_class->dispose = mail_shell_sidebar_dispose; + object_class->finalize = mail_shell_sidebar_finalize; + object_class->constructed = mail_shell_sidebar_constructed; + + shell_sidebar_class = E_SHELL_SIDEBAR_CLASS (class); + shell_sidebar_class->check_state = mail_shell_sidebar_check_state; + + g_object_class_install_property ( + object_class, + PROP_FOLDER_TREE, + g_param_spec_object ( + "folder-tree", + NULL, + NULL, + EM_TYPE_FOLDER_TREE, + G_PARAM_READABLE)); +} + +static void +mail_shell_sidebar_init (EMailShellSidebar *mail_shell_sidebar) +{ + mail_shell_sidebar->priv = + E_MAIL_SHELL_SIDEBAR_GET_PRIVATE (mail_shell_sidebar); + + /* Postpone widget construction until we have a shell view. */ +} + +GType +e_mail_shell_sidebar_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMailShellSidebarClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) mail_shell_sidebar_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMailShellSidebar), + 0, /* n_preallocs */ + (GInstanceInitFunc) mail_shell_sidebar_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + E_TYPE_SHELL_SIDEBAR, "EMailShellSidebar", + &type_info, 0); + } + + return type; +} + +GtkWidget * +e_mail_shell_sidebar_new (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_MAIL_SHELL_SIDEBAR, + "shell-view", shell_view, NULL); +} + +EMFolderTree * +e_mail_shell_sidebar_get_folder_tree (EMailShellSidebar *mail_shell_sidebar) +{ + g_return_val_if_fail ( + E_IS_MAIL_SHELL_SIDEBAR (mail_shell_sidebar), NULL); + + return EM_FOLDER_TREE (mail_shell_sidebar->priv->folder_tree); +} diff --git a/mail/e-mail-shell-sidebar.h b/mail/e-mail-shell-sidebar.h new file mode 100644 index 0000000000..e53c803db0 --- /dev/null +++ b/mail/e-mail-shell-sidebar.h @@ -0,0 +1,79 @@ +/* + * e-mail-shell-sidebar.h + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MAIL_SHELL_SIDEBAR_H +#define E_MAIL_SHELL_SIDEBAR_H + +#include <shell/e-shell-sidebar.h> +#include <shell/e-shell-view.h> +#include <mail/em-folder-tree.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_SHELL_SIDEBAR \ + (e_mail_shell_sidebar_get_type ()) +#define E_MAIL_SHELL_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_SHELL_SIDEBAR, EMailShellSidebar)) +#define E_MAIL_SHELL_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_SHELL_SIDEBAR, EMailShellSidebarClass)) +#define E_IS_MAIL_SHELL_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_SHELL_SIDEBAR)) +#define E_IS_MAIL_SHELL_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_SHELL_SIDEBAR)) +#define E_MAIL_SHELL_SIDEBAR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_SHELL_SIDEBAR, EMailShellSidebarClass)) + +G_BEGIN_DECLS + +typedef struct _EMailShellSidebar EMailShellSidebar; +typedef struct _EMailShellSidebarClass EMailShellSidebarClass; +typedef struct _EMailShellSidebarPrivate EMailShellSidebarPrivate; + +enum { + E_MAIL_SHELL_SIDEBAR_FOLDER_ALLOWS_CHILDREN = 1 << 0, + E_MAIL_SHELL_SIDEBAR_FOLDER_CAN_DELETE = 1 << 1, + E_MAIL_SHELL_SIDEBAR_FOLDER_IS_JUNK = 1 << 2, + E_MAIL_SHELL_SIDEBAR_FOLDER_IS_OUTBOX = 1 << 3, + E_MAIL_SHELL_SIDEBAR_FOLDER_IS_STORE = 1 << 4, + E_MAIL_SHELL_SIDEBAR_FOLDER_IS_TRASH = 1 << 5 +}; + +struct _EMailShellSidebar { + EShellSidebar parent; + EMailShellSidebarPrivate *priv; +}; + +struct _EMailShellSidebarClass { + EShellSidebarClass parent_class; +}; + +GType e_mail_shell_sidebar_get_type (void); +GtkWidget * e_mail_shell_sidebar_new (EShellView *shell_view); +EMFolderTree * e_mail_shell_sidebar_get_folder_tree + (EMailShellSidebar *mail_shell_sidebar); + +G_END_DECLS + +#endif /* E_MAIL_SHELL_SIDEBAR_H */ diff --git a/mail/e-mail-shell-view-actions.c b/mail/e-mail-shell-view-actions.c new file mode 100644 index 0000000000..600d8e847c --- /dev/null +++ b/mail/e-mail-shell-view-actions.c @@ -0,0 +1,1715 @@ +/* + * e-mail-shell-view-actions.c + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-shell-view-private.h" + +static void +action_gal_save_custom_view_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailShellContent *mail_shell_content; + EShellView *shell_view; + GalViewInstance *view_instance; + + /* All shell views repond to the activation of this action, + * which is defined by EShellWindow. But only the currently + * active shell view proceeds with saving the custom view. */ + shell_view = E_SHELL_VIEW (mail_shell_view); + if (!e_shell_view_is_active (shell_view)) + return; + + mail_shell_content = mail_shell_view->priv->mail_shell_content; + view_instance = e_mail_shell_content_get_view_instance (mail_shell_content); + gal_view_instance_save_as (view_instance); +} + +static void +action_mail_account_disable_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailShellSidebar *mail_shell_sidebar; + EShellModule *shell_module; + EShellView *shell_view; + EMFolderTree *folder_tree; + EAccountList *account_list; + EAccount *account; + gchar *folder_uri; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_module = e_shell_view_get_shell_module (shell_view); + + mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + folder_uri = em_folder_tree_get_selected_uri (folder_tree); + g_return_if_fail (folder_uri != NULL); + + account_list = e_get_account_list (); + account = mail_config_get_account_by_source_url (folder_uri); + g_return_if_fail (account != NULL); + + if (e_account_list_account_has_proxies (account_list, account)) + e_account_list_remove_account_proxies (account_list, account); + + account->enabled = !account->enabled; + e_account_list_change (account_list, account); + e_mail_shell_module_remove_store_by_uri (shell_module, folder_uri); + + if (account->parent_uid != NULL) + e_account_list_remove (account_list, account); + + e_account_list_save (account_list); + + g_free (folder_uri); +} + +static void +action_mail_create_search_folder_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + /* FIXME */ + g_print ("Action: %s\n", gtk_action_get_name (GTK_ACTION (action))); +} + +static void +action_mail_download_foreach_cb (CamelService *service) +{ + if (CAMEL_IS_DISCO_STORE (service) || + CAMEL_IS_OFFLINE_STORE (service)) + mail_store_prepare_offline (CAMEL_STORE (service)); +} + +static void +action_mail_download_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EShellView *shell_view; + EShellModule *shell_module; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_module = e_shell_view_get_shell_module (shell_view); + + e_mail_shell_module_stores_foreach ( + shell_module, (GHFunc) action_mail_download_foreach_cb, NULL); +} + +static void +action_mail_empty_trash_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EShellWindow *shell_window; + EShellView *shell_view; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + em_utils_empty_trash (GTK_WIDGET (shell_window)); +} + +static void +action_mail_flush_outbox_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + mail_send (); +} + +static void +action_mail_folder_copy_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailShellSidebar *mail_shell_sidebar; + CamelFolderInfo *folder_info; + EMFolderTree *folder_tree; + + mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + folder_info = em_folder_tree_get_selected_folder_info (folder_tree); + g_return_if_fail (folder_info != NULL); + + /* XXX Leaking folder_info? */ + em_folder_utils_copy_folder (folder_info, FALSE); +} + +static void +action_mail_folder_delete_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailShellSidebar *mail_shell_sidebar; + EMFolderTree *folder_tree; + CamelFolder *folder; + + mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + folder = em_folder_tree_get_selected_folder (folder_tree); + g_return_if_fail (folder != NULL); + + em_folder_utils_delete_folder (folder); +} + +static void +action_mail_folder_expunge_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailReader *reader; + MessageList *message_list; + EShellWindow *shell_window; + EShellView *shell_view; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + g_return_if_fail (message_list->folder != NULL); + + em_utils_expunge_folder ( + GTK_WIDGET (shell_window), message_list->folder); +} + +static void +action_mail_folder_mark_all_as_read_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailReader *reader; + MessageList *message_list; + EShellWindow *shell_window; + EShellView *shell_view; + CamelFolder *folder; + GtkWindow *parent; + GPtrArray *uids; + const gchar *key; + const gchar *prompt; + guint ii; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + parent = GTK_WINDOW (shell_window); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + folder = message_list->folder; + g_return_if_fail (folder != NULL); + + key = "/apps/evolution/mail/prompts/mark_all_read"; + prompt = "mail:ask-mark-all-read"; + + if (!em_utils_prompt_user (parent, key, prompt, NULL)) + return; + + uids = message_list_get_uids (message_list); + + camel_folder_freeze (folder); + for (ii = 0; ii < uids->len; ii++) + camel_folder_set_message_flags ( + folder, uids->pdata[ii], + CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN); + camel_folder_thaw (folder); + + message_list_free_uids (message_list, uids); +} + +static void +action_mail_folder_move_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailShellSidebar *mail_shell_sidebar; + CamelFolderInfo *folder_info; + EMFolderTree *folder_tree; + + mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + folder_info = em_folder_tree_get_selected_folder_info (folder_tree); + g_return_if_fail (folder_info != NULL); + + /* XXX Leaking folder_info? */ + em_folder_utils_copy_folder (folder_info, TRUE); +} + +static void +action_mail_folder_new_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EMailShellSidebar *mail_shell_sidebar; + CamelFolderInfo *folder_info; + EMFolderTree *folder_tree; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + folder_info = em_folder_tree_get_selected_folder_info (folder_tree); + g_return_if_fail (folder_info != NULL); + + em_folder_utils_create_folder ( + folder_info, folder_tree, GTK_WINDOW (shell_window)); + camel_folder_info_free (folder_info); +} + +static void +action_mail_folder_properties_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailShellSidebar *mail_shell_sidebar; + EMFolderTree *folder_tree; + EShellView *shell_view; + GtkTreeSelection *selection; + GtkTreeView *tree_view; + GtkTreeModel *model; + GtkTreeIter iter; + gchar *uri; + + shell_view = E_SHELL_VIEW (mail_shell_view); + mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + + tree_view = GTK_TREE_VIEW (folder_tree); + selection = gtk_tree_view_get_selection (tree_view); + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + return; + + gtk_tree_model_get (model, &iter, COL_STRING_URI, &uri, -1); + em_folder_properties_show (shell_view, NULL, uri); + g_free (uri); +} + +static void +action_mail_folder_refresh_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailShellSidebar *mail_shell_sidebar; + EMFolderTree *folder_tree; + CamelFolder *folder; + + mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + folder = em_folder_tree_get_selected_folder (folder_tree); + g_return_if_fail (folder != NULL); + + mail_refresh_folder (folder, NULL, NULL); +} + +static void +action_mail_folder_rename_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailShellSidebar *mail_shell_sidebar; + EMFolderTree *folder_tree; + CamelFolder *folder; + + mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + folder = em_folder_tree_get_selected_folder (folder_tree); + g_return_if_fail (folder != NULL); + + em_folder_utils_rename_folder (folder); +} + +/* Helper for action_mail_folder_select_all_cb() */ +static gboolean +action_mail_folder_select_all_timeout_cb (MessageList *message_list) +{ + message_list_select_all (message_list); + gtk_widget_grab_focus (GTK_WIDGET (message_list)); + + return FALSE; +} + +static void +action_mail_folder_select_all_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EMailReader *reader; + MessageList *message_list; + EShellWindow *shell_window; + EShellView *shell_view; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + if (message_list->threaded) { + gtk_action_activate (ACTION (MAIL_THREADS_EXPAND_ALL)); + + /* XXX The timeout below is added so that the execution + * thread to expand all conversation threads would + * have completed. The timeout 505 is just to ensure + * that the value is a small delta more than the + * timeout value in mail_regen_list(). */ + g_timeout_add ( + 505, (GSourceFunc) + action_mail_folder_select_all_timeout_cb, + message_list); + } else + /* If there is no threading, just select all immediately. */ + action_mail_folder_select_all_timeout_cb (message_list); +} + +static void +action_mail_folder_select_thread_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + MessageList *message_list; + EMailReader *reader; + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + message_list_select_thread (message_list); +} + +static void +action_mail_folder_select_subthread_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + MessageList *message_list; + EMailReader *reader; + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + message_list_select_subthread (message_list); +} + +static void +action_mail_hide_deleted_cb (GtkToggleAction *action, + EMailShellView *mail_shell_view) +{ + MessageList *message_list; + EMailReader *reader; + gboolean active; + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + active = gtk_toggle_action_get_active (action); + message_list_set_hidedeleted (message_list, active); +} + +static void +action_mail_hide_read_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + MessageList *message_list; + EMailReader *reader; + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + message_list_hide_add ( + message_list, + "(match-all (system-flag \"seen\"))", + ML_HIDE_SAME, ML_HIDE_SAME); +} + +static void +action_mail_hide_selected_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + MessageList *message_list; + EMailReader *reader; + GPtrArray *uids; + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + uids = message_list_get_selected (message_list); + message_list_hide_uids (message_list, uids); + message_list_free_uids (message_list, uids); +} + +static void +action_mail_label_cb (GtkToggleAction *action, + EMailShellView *mail_shell_view) +{ + EMailReader *reader; + MessageList *message_list; + CamelFolder *folder; + GPtrArray *uids; + const gchar *tag; + gint ii; + + tag = g_object_get_data (G_OBJECT (action), "tag"); + g_return_if_fail (tag != NULL); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + folder = message_list->folder; + + uids = message_list_get_selected (message_list); + + for (ii = 0; ii < uids->len; ii++) { + if (gtk_toggle_action_get_active (action)) + camel_folder_set_message_user_flag ( + folder, uids->pdata[ii], tag, TRUE); + else { + camel_folder_set_message_user_flag ( + folder, uids->pdata[ii], tag, FALSE); + camel_folder_set_message_user_tag ( + folder, uids->pdata[ii], "label", NULL); + } + } + + message_list_free_uids (message_list, uids); +} + +static void +action_mail_label_new_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EShell *shell; + EShellSettings *shell_settings; + EShellWindow *shell_window; + EShellView *shell_view; + EMailLabelDialog *label_dialog; + EMailLabelListStore *store; + EMailReader *reader; + MessageList *message_list; + CamelFolder *folder; + GtkTreeModel *model; + GtkTreeIter iter; + GtkWidget *dialog; + GPtrArray *uids; + GdkColor label_color; + const gchar *property_name; + const gchar *label_name; + gchar *label_tag; + gint n_children; + guint ii; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + dialog = e_mail_label_dialog_new (GTK_WINDOW (shell_window)); + + gtk_window_set_title (GTK_WINDOW (dialog), _("Add Label")); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) + goto exit; + + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + label_dialog = E_MAIL_LABEL_DIALOG (dialog); + label_name = e_mail_label_dialog_get_label_name (label_dialog); + e_mail_label_dialog_get_label_color (label_dialog, &label_color); + + property_name = "mail-label-list-store"; + store = e_shell_settings_get_object (shell_settings, property_name); + e_mail_label_list_store_set (store, NULL, label_name, &label_color); + g_object_unref (store); + + /* XXX This is awkward. We've added a new label to the list store + * but we don't have the new label's tag nor an iterator to use + * to fetch it. We know the label was appended to the store, + * so we have to dig it out manually. EMailLabelListStore API + * probably needs some rethinking. */ + model = GTK_TREE_MODEL (store); + n_children = gtk_tree_model_iter_n_children (model, NULL); + gtk_tree_model_iter_nth_child (model, &iter, NULL, n_children - 1); + label_tag = e_mail_label_list_store_get_tag (store, &iter); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + folder = message_list->folder; + + uids = message_list_get_selected (message_list); + + for (ii = 0; ii < uids->len; ii++) + camel_folder_set_message_user_flag ( + folder, uids->pdata[ii], label_tag, TRUE); + + message_list_free_uids (message_list, uids); + + g_free (label_tag); + +exit: + gtk_widget_destroy (dialog); +} + +static void +action_mail_label_none_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EShell *shell; + EShellView *shell_view; + EShellSettings *shell_settings; + EShellWindow *shell_window; + EMailReader *reader; + MessageList *message_list; + GtkTreeModel *tree_model; + CamelFolder *folder; + GtkTreeIter iter; + GPtrArray *uids; + gboolean valid; + guint ii; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + tree_model = e_shell_settings_get_object ( + shell_settings, "mail-label-list-store"); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + uids = message_list_get_selected (message_list); + folder = message_list->folder; + + valid = gtk_tree_model_get_iter_first (tree_model, &iter); + + while (valid) { + gchar *tag; + + tag = e_mail_label_list_store_get_tag ( + E_MAIL_LABEL_LIST_STORE (tree_model), &iter); + + for (ii = 0; ii < uids->len; ii++) { + camel_folder_set_message_user_flag ( + folder, uids->pdata[ii], tag, FALSE); + camel_folder_set_message_user_tag ( + folder, uids->pdata[ii], "label", NULL); + } + + g_free (tag); + + valid = gtk_tree_model_iter_next (tree_model, &iter); + } + + message_list_free_uids (message_list, uids); +} + +static void +action_mail_preview_cb (GtkToggleAction *action, + EMailShellView *mail_shell_view) +{ + EMailShellContent *mail_shell_content; + gboolean active; + + mail_shell_content = mail_shell_view->priv->mail_shell_content; + active = gtk_toggle_action_get_active (action); + + e_mail_shell_content_set_preview_visible (mail_shell_content, active); +} + +static void +action_mail_show_hidden_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + MessageList *message_list; + EMailReader *reader; + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + message_list_hide_clear (message_list); +} + +static void +action_mail_smart_backward_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + EShellSettings *shell_settings; + EMailShellSidebar *mail_shell_sidebar; + EMFolderTree *folder_tree; + EMFormatHTMLDisplay *html_display; + EMailReader *reader; + MessageList *message_list; + GtkToggleAction *toggle_action; + GtkHTML *html; + gboolean caret_mode; + gboolean magic_spacebar; + + /* This implements the so-called "Magic Backspace". */ + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + html_display = e_mail_reader_get_html_display (reader); + message_list = e_mail_reader_get_message_list (reader); + + magic_spacebar = e_shell_settings_get_boolean ( + shell_settings, "mail-magic-spacebar"); + + toggle_action = GTK_TOGGLE_ACTION (ACTION (MAIL_CARET_MODE)); + caret_mode = gtk_toggle_action_get_active (toggle_action); + + html = EM_FORMAT_HTML (html_display)->html; + + if (gtk_html_command (html, "scroll-backward")) + return; + + if (caret_mode || !magic_spacebar) + return; + + /* XXX Are two separate calls really necessary? */ + + if (message_list_select ( + message_list, MESSAGE_LIST_SELECT_PREVIOUS, + 0, CAMEL_MESSAGE_SEEN)) + return; + + if (message_list_select ( + message_list, MESSAGE_LIST_SELECT_PREVIOUS | + MESSAGE_LIST_SELECT_WRAP, 0, CAMEL_MESSAGE_SEEN)) + return; + + em_folder_tree_select_prev_path (folder_tree, TRUE); + + gtk_widget_grab_focus (GTK_WIDGET (message_list)); +} + +static void +action_mail_smart_forward_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + EShellSettings *shell_settings; + EMailShellSidebar *mail_shell_sidebar; + EMFolderTree *folder_tree; + EMFormatHTMLDisplay *html_display; + EMailReader *reader; + MessageList *message_list; + GtkToggleAction *toggle_action; + GtkHTML *html; + gboolean caret_mode; + gboolean magic_spacebar; + + /* This implements the so-called "Magic Spacebar". */ + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + html_display = e_mail_reader_get_html_display (reader); + message_list = e_mail_reader_get_message_list (reader); + + magic_spacebar = e_shell_settings_get_boolean ( + shell_settings, "mail-magic-spacebar"); + + toggle_action = GTK_TOGGLE_ACTION (ACTION (MAIL_CARET_MODE)); + caret_mode = gtk_toggle_action_get_active (toggle_action); + + html = EM_FORMAT_HTML (html_display)->html; + + if (gtk_html_command (html, "scroll-forward")) + return; + + if (caret_mode || !magic_spacebar) + return; + + /* XXX Are two separate calls really necessary? */ + + if (message_list_select ( + message_list, MESSAGE_LIST_SELECT_NEXT, + 0, CAMEL_MESSAGE_SEEN)) + return; + + if (message_list_select ( + message_list, MESSAGE_LIST_SELECT_NEXT | + MESSAGE_LIST_SELECT_WRAP, 0, CAMEL_MESSAGE_SEEN)) + return; + + em_folder_tree_select_next_path (folder_tree, TRUE); + + gtk_widget_grab_focus (GTK_WIDGET (message_list)); +} + +static void +action_mail_stop_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + mail_cancel_all (); +} + +static void +action_mail_threads_collapse_all_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + MessageList *message_list; + EMailReader *reader; + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + message_list_set_threaded_collapse_all (message_list); +} + +static void +action_mail_threads_expand_all_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + MessageList *message_list; + EMailReader *reader; + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + message_list_set_threaded_expand_all (message_list); +} + +static void +action_mail_threads_group_by_cb (GtkToggleAction *action, + EMailShellView *mail_shell_view) +{ + EMailShellContent *mail_shell_content; + MessageList *message_list; + EMailReader *reader; + gboolean active; + + mail_shell_content = mail_shell_view->priv->mail_shell_content; + active = gtk_toggle_action_get_active (action); + + reader = E_MAIL_READER (mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + + message_list_set_threaded (message_list, active); +} + +static void +action_mail_tools_filters_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EShellWindow *shell_window; + EShellView *shell_view; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + em_utils_edit_filters (GTK_WIDGET (shell_window)); +} + +static void +action_mail_tools_search_folders_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + vfolder_edit (E_SHELL_VIEW (mail_shell_view)); +} + +static void +action_mail_tools_subscriptions_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EShellWindow *shell_window; + EShellView *shell_view; + GtkWidget *dialog; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + dialog = em_subscribe_editor_new (); + gtk_window_set_transient_for ( + GTK_WINDOW (dialog), GTK_WINDOW (shell_window)); + gtk_dialog_run (GTK_DIALOG (dialog)); + /* XXX Dialog destroys itself. */ +} + +static void +action_mail_view_cb (GtkRadioAction *action, + GtkRadioAction *current, + EMailShellView *mail_shell_view) +{ + EMailShellContent *mail_shell_content; + gboolean vertical_view; + + mail_shell_content = mail_shell_view->priv->mail_shell_content; + vertical_view = (gtk_radio_action_get_current_value (action) == 1); + + e_mail_shell_content_set_vertical_view ( + mail_shell_content, vertical_view); +} + +static void +action_search_execute_cb (GtkAction *action, + EMailShellView *mail_shell_view) +{ + EShellView *shell_view; + + /* All shell views respond to the activation of this action, + * which is defined by EShellWindow. But only the currently + * active shell view proceeds with executing the search. */ + shell_view = E_SHELL_VIEW (mail_shell_view); + if (!e_shell_view_is_active (shell_view)) + return; + + e_mail_shell_view_execute_search (mail_shell_view); +} + +static void +action_search_filter_cb (GtkRadioAction *action, + GtkRadioAction *current, + EMailShellView *mail_shell_view) +{ + e_mail_shell_view_execute_search (mail_shell_view); +} + +static void +action_search_scope_cb (GtkRadioAction *action, + GtkRadioAction *current, + EMailShellView *mail_shell_view) +{ + e_mail_shell_view_execute_search (mail_shell_view); +} + +static GtkActionEntry mail_entries[] = { + + { "mail-account-disable", + NULL, + N_("_Disable Account"), + NULL, + N_("Disable this account"), + G_CALLBACK (action_mail_account_disable_cb) }, + + { "mail-create-search-folder", + NULL, + N_("C_reate Search Folder From Search..."), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_mail_create_search_folder_cb) }, + + { "mail-download", + NULL, + N_("_Download Messages for Offline Usage"), + NULL, + N_("Download messages of accounts and folders marked for offline"), + G_CALLBACK (action_mail_download_cb) }, + + { "mail-empty-trash", + NULL, + N_("Empty _Trash"), + NULL, + N_("Permanently remove all the deleted messages from all folders"), + G_CALLBACK (action_mail_empty_trash_cb) }, + + { "mail-flush-outbox", + "mail-send", + N_("Fl_ush Outbox"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_mail_flush_outbox_cb) }, + + { "mail-folder-copy", + "folder-copy", + N_("_Copy Folder To..."), + NULL, + N_("Copy the selected folder into another folder"), + G_CALLBACK (action_mail_folder_copy_cb) }, + + { "mail-folder-delete", + GTK_STOCK_DELETE, + NULL, + NULL, + N_("Permanently remove this folder"), + G_CALLBACK (action_mail_folder_delete_cb) }, + + { "mail-folder-expunge", + NULL, + N_("E_xpunge"), + "<Control>e", + N_("Permanently remove all deleted messages from this folder"), + G_CALLBACK (action_mail_folder_expunge_cb) }, + + { "mail-folder-mark-all-as-read", + "mail-read", + N_("Mar_k All Messages as Read"), + NULL, + N_("Mark all messages in the folder as read"), + G_CALLBACK (action_mail_folder_mark_all_as_read_cb) }, + + { "mail-folder-move", + "folder-move", + N_("_Move Folder To..."), + NULL, + N_("Move the selected folder into another folder"), + G_CALLBACK (action_mail_folder_move_cb) }, + + { "mail-folder-new", + "folder-new", + N_("_New..."), + NULL, + N_("Create a new folder for storing mail"), + G_CALLBACK (action_mail_folder_new_cb) }, + + { "mail-folder-properties", + GTK_STOCK_PROPERTIES, + NULL, + NULL, + N_("Change the properties of this folder"), + G_CALLBACK (action_mail_folder_properties_cb) }, + + { "mail-folder-refresh", + GTK_STOCK_REFRESH, + NULL, + "F5", + N_("Refresh the folder"), + G_CALLBACK (action_mail_folder_refresh_cb) }, + + { "mail-folder-rename", + NULL, + N_("_Rename..."), + "F2", + N_("Change the name of this folder"), + G_CALLBACK (action_mail_folder_rename_cb) }, + + { "mail-folder-select-all", + NULL, + N_("Select _All Messages"), + "<Control>a", + N_("Select all visible messages"), + G_CALLBACK (action_mail_folder_select_all_cb) }, + + { "mail-folder-select-thread", + NULL, + N_("Select Message _Thread"), + "<Control>h", + N_("Select all messages in the same thread as the selected message"), + G_CALLBACK (action_mail_folder_select_thread_cb) }, + + { "mail-folder-select-subthread", + NULL, + N_("Select Message S_ubthread"), + "<Shift><Control>h", + N_("Select all replies to the currently selected message"), + G_CALLBACK (action_mail_folder_select_subthread_cb) }, + + { "mail-label-new", + NULL, + N_("_New Label"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_mail_label_new_cb) }, + + { "mail-label-none", + NULL, + N_("N_one"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_mail_label_none_cb) }, + + { "mail-hide-read", + NULL, + N_("Hide _Read Messages"), + NULL, + N_("Temporarily hide all messages that have already been read"), + G_CALLBACK (action_mail_hide_read_cb) }, + + { "mail-hide-selected", + NULL, + N_("Hide S_elected Messages"), + NULL, + N_("Temporarily hide the selected messages"), + G_CALLBACK (action_mail_hide_selected_cb) }, + + { "mail-show-hidden", + NULL, + N_("Show Hidde_n Messages"), + NULL, + N_("Show messages that have been temporarily hidden"), + G_CALLBACK (action_mail_show_hidden_cb) }, + + { "mail-smart-backward", + NULL, + NULL, /* No menu item; key press only */ + NULL, + NULL, + G_CALLBACK (action_mail_smart_backward_cb) }, + + { "mail-smart-forward", + NULL, + NULL, /* No menu item; key press only */ + NULL, + NULL, + G_CALLBACK (action_mail_smart_forward_cb) }, + + { "mail-stop", + GTK_STOCK_STOP, + N_("Cancel"), + NULL, + N_("Cancel the current mail operation"), + G_CALLBACK (action_mail_stop_cb) }, + + { "mail-threads-collapse-all", + NULL, + N_("Collapse All _Threads"), + "<Shift><Control>b", + N_("Collapse all message threads"), + G_CALLBACK (action_mail_threads_collapse_all_cb) }, + + { "mail-threads-expand-all", + NULL, + N_("E_xpand All Threads"), + NULL, + N_("Expand all message threads"), + G_CALLBACK (action_mail_threads_expand_all_cb) }, + + { "mail-tools-filters", + NULL, + N_("_Message Filters"), + NULL, + N_("Create or edit rules for filtering new mail"), + G_CALLBACK (action_mail_tools_filters_cb) }, + + { "mail-tools-search-folders", + NULL, + N_("Search F_olders"), + NULL, + N_("Create or edit search folder definitions"), + G_CALLBACK (action_mail_tools_search_folders_cb) }, + + { "mail-tools-subscriptions", + NULL, + N_("_Subscriptions..."), + NULL, + N_("Subscribe or unsubscribe to folders on remote servers"), + G_CALLBACK (action_mail_tools_subscriptions_cb) }, + + /*** Menus ***/ + + { "mail-folder-menu", + NULL, + N_("F_older"), + NULL, + NULL, + NULL }, + + { "mail-label-menu", + NULL, + N_("_Label"), + NULL, + NULL, + NULL }, + + { "mail-preview-menu", + NULL, + N_("_Preview"), + NULL, + NULL, + NULL } +}; + +static EPopupActionEntry mail_popup_entries[] = { + + { "mail-popup-account-disable", + NULL, + "mail-account-disable" }, + + { "mail-popup-empty-trash", + NULL, + "mail-empty-trash" }, + + { "mail-popup-flush-outbox", + NULL, + "mail-flush-outbox" }, + + { "mail-popup-folder-copy", + NULL, + "mail-folder-copy" }, + + { "mail-popup-folder-delete", + NULL, + "mail-folder-delete" }, + + { "mail-popup-folder-move", + NULL, + "mail-folder-move" }, + + { "mail-popup-folder-new", + N_("_New Folder..."), + "mail-folder-new" }, + + { "mail-popup-folder-properties", + NULL, + "mail-folder-properties" }, + + { "mail-popup-folder-refresh", + NULL, + "mail-folder-refresh" }, + + { "mail-popup-folder-rename", + NULL, + "mail-folder-rename" } +}; + +static GtkToggleActionEntry mail_toggle_entries[] = { + + { "mail-hide-deleted", + NULL, + N_("Hide _Deleted Messages"), + NULL, + N_("Hide deleted messages rather than displaying " + "them with a line through them"), + G_CALLBACK (action_mail_hide_deleted_cb), + TRUE }, + + { "mail-preview", + NULL, + N_("Show Message _Preview"), + "<Control>m", + N_("Show message preview pane"), + G_CALLBACK (action_mail_preview_cb), + TRUE }, + + { "mail-threads-group-by", + NULL, + N_("_Group By Threads"), + "<Control>t", + N_("Threaded message list"), + G_CALLBACK (action_mail_threads_group_by_cb), + FALSE } +}; + +static GtkRadioActionEntry mail_view_entries[] = { + + /* This action represents the initial active mail view. + * It should not be visible in the UI, nor should it be + * possible to switch to it from another shell view. */ + { "mail-view-internal", + NULL, + NULL, + NULL, + NULL, + -1 }, + + { "mail-view-classic", + NULL, + N_("_Classic View"), + NULL, + N_("Show message preview below the message list"), + 0 }, + + { "mail-view-vertical", + NULL, + N_("_Vertical View"), + NULL, + N_("Show message preview alongside the message list"), + 1 } +}; + +static GtkRadioActionEntry mail_filter_entries[] = { + + { "mail-filter-all-messages", + NULL, + N_("All Messages"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_FILTER_ALL_MESSAGES }, + + { "mail-filter-important-messages", + "emblem-important", + N_("Important Messages"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_FILTER_IMPORTANT_MESSAGES }, + + { "mail-filter-last-5-days-messages", + NULL, + N_("Last 5 Days' Messages"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_FILTER_LAST_5_DAYS_MESSAGES }, + + { "mail-filter-messages-not-junk", + "mail-mark-notjunk", + N_("Messages Not Junk"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_FILTER_MESSAGES_NOT_JUNK }, + + { "mail-filter-messages-with-attachments", + "mail-attachment", + N_("Messages with Attachments"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_FILTER_MESSAGES_WITH_ATTACHMENTS }, + + { "mail-filter-no-label", + NULL, + N_("No Label"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_FILTER_NO_LABEL }, + + { "mail-filter-read-messages", + "mail-read", + N_("Read Messages"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_FILTER_READ_MESSAGES }, + + { "mail-filter-recent-messages", + NULL, + N_("Recent Messages"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_FILTER_RECENT_MESSAGES }, + + { "mail-filter-unread-messages", + "mail-unread", + N_("Unread Messages"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_FILTER_UNREAD_MESSAGES } +}; + +static GtkRadioActionEntry mail_search_entries[] = { + + { "mail-search-body-contains", + NULL, + N_("Body contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_SEARCH_BODY_CONTAINS }, + + { "mail-search-message-contains", + NULL, + N_("Message contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_SEARCH_MESSAGE_CONTAINS }, + + { "mail-search-recipients-contain", + NULL, + N_("Recipients contain"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_SEARCH_RECIPIENTS_CONTAIN }, + + { "mail-search-sender-contains", + NULL, + N_("Sender contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_SEARCH_SENDER_CONTAINS }, + + { "mail-search-subject-contains", + NULL, + N_("Subject contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_SEARCH_SUBJECT_CONTAINS }, + + { "mail-search-subject-or-recipients-contains", + NULL, + N_("Subject or Recipients contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_SEARCH_SUBJECT_OR_RECIPIENTS_CONTAINS }, + + { "mail-search-subject-or-sender-contains", + NULL, + N_("Subject or Sender contains"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_SEARCH_SUBJECT_OR_SENDER_CONTAINS } +}; + +static GtkRadioActionEntry mail_scope_entries[] = { + + { "mail-scope-all-accounts", + NULL, + N_("All Accounts"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_SCOPE_ALL_ACCOUNTS }, + + { "mail-scope-current-account", + NULL, + N_("Current Account"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_SCOPE_CURRENT_ACCOUNT }, + + { "mail-scope-current-folder", + NULL, + N_("Current Folder"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_SCOPE_CURRENT_FOLDER }, + + { "mail-scope-current-message", + NULL, + N_("Current Message"), + NULL, + NULL, /* XXX Add a tooltip! */ + MAIL_SCOPE_CURRENT_MESSAGE } +}; + +void +e_mail_shell_view_actions_init (EMailShellView *mail_shell_view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EShellContent *shell_content; + GtkActionGroup *action_group; + GtkRadioAction *radio_action; + GConfBridge *bridge; + GObject *object; + GObject *src_object; + GObject *dst_object; + const gchar *key; + + g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + + /* Mail Actions */ + action_group = ACTION_GROUP (MAIL); + gtk_action_group_add_actions ( + action_group, mail_entries, + G_N_ELEMENTS (mail_entries), mail_shell_view); + e_action_group_add_popup_actions ( + action_group, mail_popup_entries, + G_N_ELEMENTS (mail_popup_entries)); + gtk_action_group_add_toggle_actions ( + action_group, mail_toggle_entries, + G_N_ELEMENTS (mail_toggle_entries), mail_shell_view); + gtk_action_group_add_radio_actions ( + action_group, mail_view_entries, + G_N_ELEMENTS (mail_view_entries), -1, + G_CALLBACK (action_mail_view_cb), mail_shell_view); + gtk_action_group_add_radio_actions ( + action_group, mail_search_entries, + G_N_ELEMENTS (mail_search_entries), + MAIL_SEARCH_SUBJECT_OR_SENDER_CONTAINS, + NULL, NULL); + gtk_action_group_add_radio_actions ( + action_group, mail_scope_entries, + G_N_ELEMENTS (mail_scope_entries), + MAIL_SCOPE_CURRENT_FOLDER, + G_CALLBACK (action_search_scope_cb), mail_shell_view); + + radio_action = GTK_RADIO_ACTION (ACTION (MAIL_SCOPE_ALL_ACCOUNTS)); + e_shell_content_set_scope_action (shell_content, radio_action); + e_shell_content_set_scope_visible (shell_content, TRUE); + + /* Bind GObject properties for GConf keys. */ + + bridge = gconf_bridge_get (); + + object = G_OBJECT (ACTION (MAIL_PREVIEW)); + key = "/apps/evolution/mail/display/show_preview"; + gconf_bridge_bind_property (bridge, key, object, "active"); + + object = G_OBJECT (ACTION (MAIL_THREADS_GROUP_BY)); + key = "/apps/evolution/mail/display/thread_list"; + gconf_bridge_bind_property (bridge, key, object, "active"); + + object = G_OBJECT (ACTION (MAIL_VIEW_VERTICAL)); + key = "/apps/evolution/mail/display/layout"; + gconf_bridge_bind_property (bridge, key, object, "current-value"); + + /* Fine tuning. */ + + src_object = G_OBJECT (ACTION (MAIL_THREADS_GROUP_BY)); + + dst_object = G_OBJECT (ACTION (MAIL_FOLDER_SELECT_THREAD)); + e_binding_new (src_object, "active", dst_object, "sensitive"); + + dst_object = G_OBJECT (ACTION (MAIL_FOLDER_SELECT_SUBTHREAD)); + e_binding_new (src_object, "active", dst_object, "sensitive"); + + dst_object = G_OBJECT (ACTION (MAIL_THREADS_COLLAPSE_ALL)); + e_binding_new (src_object, "active", dst_object, "sensitive"); + + dst_object = G_OBJECT (ACTION (MAIL_THREADS_EXPAND_ALL)); + e_binding_new (src_object, "active", dst_object, "sensitive"); + + /* XXX The boolean sense of the GConf key is the inverse of + * the menu item, so we have to maintain two properties. */ + e_mutual_binding_new_with_negation ( + G_OBJECT (shell_content), "show-deleted", + G_OBJECT (ACTION (MAIL_HIDE_DELETED)), "active"); + + g_signal_connect ( + ACTION (GAL_SAVE_CUSTOM_VIEW), "activate", + G_CALLBACK (action_gal_save_custom_view_cb), mail_shell_view); + + g_signal_connect ( + ACTION (SEARCH_EXECUTE), "activate", + G_CALLBACK (action_search_execute_cb), mail_shell_view); +} + +/* Helper for e_mail_shell_view_update_popup_labels() */ +static void +mail_shell_view_update_label_action (GtkToggleAction *action, + MessageList *message_list, + GPtrArray *uids, + const gchar *label_tag) +{ + CamelFolder *folder; + gboolean exists = FALSE; + gboolean not_exists = FALSE; + gboolean sensitive; + guint ii; + + folder = message_list->folder; + + /* Figure out the proper label action state for the selected + * messages. If all the selected messages have the given label, + * make the toggle action active. If all the selected message + * DO NOT have the given label, make the toggle action inactive. + * If some do and some don't, make the action insensitive. */ + + for (ii = 0; ii < uids->len && (!exists || !not_exists); ii++) { + const gchar *old_label; + gchar *new_label; + + /* Check for new-style labels. */ + if (camel_folder_get_message_user_flag ( + folder, uids->pdata[ii], label_tag)) { + exists = TRUE; + continue; + } + + /* Check for old-style labels. */ + old_label = camel_folder_get_message_user_tag ( + folder, uids->pdata[ii], "label"); + if (old_label == NULL) { + not_exists = TRUE; + continue; + } + + /* Convert old-style labels ("<name>") to "$Label<name>". */ + new_label = g_alloca (strlen (old_label) + 10); + g_stpcpy (g_stpcpy (new_label, "$Label"), old_label); + + if (strcmp (new_label, label_tag) == 0) + exists = TRUE; + else + not_exists = TRUE; + } + + sensitive = !(exists && not_exists); + gtk_toggle_action_set_active (action, exists); + gtk_action_set_sensitive (GTK_ACTION (action), sensitive); +} + +void +e_mail_shell_view_update_popup_labels (EMailShellView *mail_shell_view) +{ + EShell *shell; + EShellSettings *shell_settings; + EShellWindow *shell_window; + EShellView *shell_view; + EMailReader *reader; + MessageList *message_list; + GtkUIManager *ui_manager; + GtkActionGroup *action_group; + GtkTreeModel *tree_model; + GtkTreeIter iter; + GPtrArray *uids; + const gchar *path; + gboolean valid; + guint merge_id; + gint ii = 0; + + g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + ui_manager = e_shell_window_get_ui_manager (shell_window); + + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + tree_model = e_shell_settings_get_object ( + shell_settings, "mail-label-list-store"); + + action_group = ACTION_GROUP (MAIL_LABEL); + merge_id = mail_shell_view->priv->label_merge_id; + path = "/mail-message-popup/mail-label-menu/mail-label-actions"; + + /* Unmerge the previous menu items. */ + gtk_ui_manager_remove_ui (ui_manager, merge_id); + e_action_group_remove_all_actions (action_group); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + uids = message_list_get_selected (message_list); + + valid = gtk_tree_model_get_iter_first (tree_model, &iter); + + while (valid) { + GtkToggleAction *toggle_action; + GtkAction *action; + gchar *action_name; + gchar *stock_id; + gchar *label; + gchar *tag; + + label = e_mail_label_list_store_get_name ( + E_MAIL_LABEL_LIST_STORE (tree_model), &iter); + stock_id = e_mail_label_list_store_get_stock_id ( + E_MAIL_LABEL_LIST_STORE (tree_model), &iter); + tag = e_mail_label_list_store_get_tag ( + E_MAIL_LABEL_LIST_STORE (tree_model), &iter); + action_name = g_strdup_printf ("mail-label-%d", ii); + + /* XXX Add a tooltip! */ + toggle_action = gtk_toggle_action_new ( + action_name, label, NULL, stock_id); + + g_object_set_data_full ( + G_OBJECT (toggle_action), "tag", + tag, (GDestroyNotify) g_free); + + /* Configure the action before we connect to signals. */ + mail_shell_view_update_label_action ( + toggle_action, message_list, uids, tag); + + g_signal_connect ( + toggle_action, "toggled", + G_CALLBACK (action_mail_label_cb), mail_shell_view); + + /* The action group takes ownership of the action. */ + action = GTK_ACTION (toggle_action); + gtk_action_group_add_action (action_group, action); + g_object_unref (toggle_action); + + gtk_ui_manager_add_ui ( + ui_manager, merge_id, path, action_name, + action_name, GTK_UI_MANAGER_AUTO, FALSE); + + g_free (label); + g_free (stock_id); + g_free (action_name); + + valid = gtk_tree_model_iter_next (tree_model, &iter); + ii++; + } + + message_list_free_uids (message_list, uids); + + g_object_unref (tree_model); +} + +void +e_mail_shell_view_update_search_filter (EMailShellView *mail_shell_view) +{ + EShell *shell; + EShellContent *shell_content; + EShellSettings *shell_settings; + EShellWindow *shell_window; + EShellView *shell_view; + GtkActionGroup *action_group; + GtkRadioAction *radio_action; + GtkTreeModel *tree_model; + GtkTreeIter iter; + GList *list; + GSList *group; + gboolean valid; + gint ii = 0; + + g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + tree_model = e_shell_settings_get_object ( + shell_settings, "mail-label-list-store"); + + action_group = ACTION_GROUP (MAIL_FILTER); + e_action_group_remove_all_actions (action_group); + + /* Add the standard filter actions. */ + gtk_action_group_add_radio_actions ( + action_group, mail_filter_entries, + G_N_ELEMENTS (mail_filter_entries), + MAIL_FILTER_ALL_MESSAGES, + G_CALLBACK (action_search_filter_cb), + mail_shell_view); + + /* Retrieve the radio group from an action we just added. */ + list = gtk_action_group_list_actions (action_group); + radio_action = GTK_RADIO_ACTION (list->data); + group = gtk_radio_action_get_group (radio_action); + g_list_free (list); + + valid = gtk_tree_model_get_iter_first (tree_model, &iter); + + while (valid) { + GtkAction *action; + gchar *action_name; + gchar *stock_id; + gchar *label; + + label = e_mail_label_list_store_get_name ( + E_MAIL_LABEL_LIST_STORE (tree_model), &iter); + stock_id = e_mail_label_list_store_get_stock_id ( + E_MAIL_LABEL_LIST_STORE (tree_model), &iter); + + action_name = g_strdup_printf ("mail-filter-label-%d", ii); + radio_action = gtk_radio_action_new ( + action_name, label, NULL, stock_id, ii); + g_free (action_name); + + gtk_radio_action_set_group (radio_action, group); + group = gtk_radio_action_get_group (radio_action); + + /* The action group takes ownership of the action. */ + action = GTK_ACTION (radio_action); + gtk_action_group_add_action (action_group, action); + g_object_unref (radio_action); + + g_free (label); + g_free (stock_id); + + valid = gtk_tree_model_iter_next (tree_model, &iter); + ii++; + } + + /* Use any action in the group; doesn't matter which. */ + e_shell_content_set_filter_action (shell_content, radio_action); + + ii = MAIL_FILTER_UNREAD_MESSAGES; + e_shell_content_add_filter_separator_after (shell_content, ii); + + ii = MAIL_FILTER_READ_MESSAGES; + e_shell_content_add_filter_separator_before (shell_content, ii); + + g_object_unref (tree_model); +} diff --git a/mail/e-mail-shell-view-actions.h b/mail/e-mail-shell-view-actions.h new file mode 100644 index 0000000000..c6c1fa3c91 --- /dev/null +++ b/mail/e-mail-shell-view-actions.h @@ -0,0 +1,261 @@ +/* + * e-mail-shell-view-actions.h + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MAIL_SHELL_VIEW_ACTIONS_H +#define E_MAIL_SHELL_VIEW_ACTIONS_H + +#include <shell/e-shell-window-actions.h> + +/* Mail Actions */ +#define E_SHELL_WINDOW_ACTION_MAIL_ACCOUNT_DISABLE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-account-disable") +#define E_SHELL_WINDOW_ACTION_MAIL_ADD_SENDER(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-add-sender") +#define E_SHELL_WINDOW_ACTION_MAIL_CARET_MODE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-caret-mode") +#define E_SHELL_WINDOW_ACTION_MAIL_CHECK_FOR_JUNK(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-check-for-junk") +#define E_SHELL_WINDOW_ACTION_MAIL_CLIPBOARD_COPY(window) \ + E_SHELL_WINDOw_ACTION ((window), "mail-clipboard-copy") +#define E_SHELL_WINDOW_ACTION_MAIL_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-copy") +#define E_SHELL_WINDOW_ACTION_MAIL_CREATE_SEARCH_FOLDER(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-create-search-folder") +#define E_SHELL_WINDOW_ACTION_MAIL_DELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-delete") +#define E_SHELL_WINDOW_ACTION_MAIL_DOWNLOAD(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-download") +#define E_SHELL_WINDOW_ACTION_MAIL_EMPTY_TRASH(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-empty-trash") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_ON_MAILING_LIST(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-on-mailing-list") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_ON_RECIPIENTS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-on-recipients") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_ON_SENDER(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-on-sender") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_ON_SUBJECT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-on-subject") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTERS_APPLY(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filters-apply") +#define E_SHELL_WINDOW_ACTION_MAIL_FIND(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-find") +#define E_SHELL_WINDOW_ACTION_MAIL_FLAG_CLEAR(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-flag-clear") +#define E_SHELL_WINDOW_ACTION_MAIL_FLAG_COMPLETED(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-flag-completed") +#define E_SHELL_WINDOW_ACTION_MAIL_FLAG_FOR_FOLLOWUP(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-flag-for-followup") +#define E_SHELL_WINDOW_ACTION_MAIL_FLUSH_OUTBOX(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-flush-outbox") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_COPY(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-copy") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_DELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-delete") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_EXPUNGE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-expunge") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_MARK_ALL_READ(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-mark-all-read") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_MOVE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-move") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_NEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-new") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_PROPERTIES(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-properties") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_REFRESH(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-refresh") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_RENAME(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-rename") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_SELECT_ALL(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-select-all") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_SELECT_THREAD(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-select-thread") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_SELECT_SUBTHREAD(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-select-subthread") +#define E_SHELL_WINDOW_ACTION_MAIL_FORWARD(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-forward") +#define E_SHELL_WINDOW_ACTION_MAIL_FORWARD_ATTACHED(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-forward-attached") +#define E_SHELL_WINDOW_ACTION_MAIL_FORWARD_INLINE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-forward-inline") +#define E_SHELL_WINDOW_ACTION_MAIL_FORWARD_QUOTED(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-forward-quoted") +#define E_SHELL_WINDOW_ACTION_MAIL_HIDE_DELETED(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-hide-deleted") +#define E_SHELL_WINDOW_ACTION_MAIL_HIDE_READ(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-hide-read") +#define E_SHELL_WINDOW_ACTION_MAIL_HIDE_SELECTED(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-hide-selected") +#define E_SHELL_WINDOW_ACTION_MAIL_LABEL_NEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-label-new") +#define E_SHELL_WINDOW_ACTION_MAIL_LABEL_NONE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-label-none") +#define E_SHELL_WINDOW_ACTION_MAIL_LOAD_IMAGES(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-load-images") +#define E_SHELL_WINDOW_ACTION_MAIL_MARK_IMPORTANT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-mark-important") +#define E_SHELL_WINDOW_ACTION_MAIL_MARK_JUNK(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-mark-junk") +#define E_SHELL_WINDOW_ACTION_MAIL_MARK_NOTJUNK(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-mark-notjunk") +#define E_SHELL_WINDOW_ACTION_MAIL_MARK_READ(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-mark-read") +#define E_SHELL_WINDOW_ACTION_MAIL_MARK_UNIMPORTANT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-mark-unimportant") +#define E_SHELL_WINDOW_ACTION_MAIL_MARK_UNREAD(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-mark-unread") +#define E_SHELL_WINDOW_ACTION_MAIL_MESSAGE_EDIT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-message-edit") +#define E_SHELL_WINDOW_ACTION_MAIL_MESSAGE_NEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-message-new") +#define E_SHELL_WINDOW_ACTION_MAIL_MESSAGE_OPEN(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-message-open") +#define E_SHELL_WINDOW_ACTION_MAIL_MESSAGE_POST(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-message-post") +#define E_SHELL_WINDOW_ACTION_MAIL_MOVE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-move") +#define E_SHELL_WINDOW_ACTION_MAIL_NEXT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-next") +#define E_SHELL_WINDOW_ACTION_MAIL_NEXT_IMPORTANT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-next-important") +#define E_SHELL_WINDOW_ACTION_MAIL_NEXT_THREAD(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-next-thread") +#define E_SHELL_WINDOW_ACTION_MAIL_NEXT_UNREAD(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-next-unread") +#define E_SHELL_WINDOW_ACTION_MAIL_PREVIEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-preview") +#define E_SHELL_WINDOW_ACTION_MAIL_PREVIOUS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-previous") +#define E_SHELL_WINDOW_ACTION_MAIL_PREVIOUS_IMPORTANT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-previous-important") +#define E_SHELL_WINDOW_ACTION_MAIL_PREVIOUS_UNREAD(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-previous-unread") +#define E_SHELL_WINDOW_ACTION_MAIL_PRINT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-print") +#define E_SHELL_WINDOW_ACTION_MAIL_PRINT_PREVIEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-print-preview") +#define E_SHELL_WINDOW_ACTION_MAIL_REDIRECT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-redirect") +#define E_SHELL_WINDOW_ACTION_MAIL_REPLY_ALL(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-reply-all") +#define E_SHELL_WINDOW_ACTION_MAIL_REPLY_LIST(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-reply-list") +#define E_SHELL_WINDOW_ACTION_MAIL_REPLY_POST(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-reply-post") +#define E_SHELL_WINDOW_ACTION_MAIL_REPLY_SENDER(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-reply-sender") +#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_FOLDER_FROM_MAILING_LIST(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-search-folder-from-mailing-list") +#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_FOLDER_FROM_RECIPIENTS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-search-folder-from-recipients") +#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_FOLDER_FROM_SENDER(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-search-folder-from-sender") +#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_FOLDER_FROM_SUBJECT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-search-folder-from-subject") +#define E_SHELL_WINDOW_ACTION_MAIL_SELECT_ALL(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-select-all") +#define E_SHELL_WINDOW_ACTION_MAIL_SHOW_ALL_HEADERS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-show-all-headers") +#define E_SHELL_WINDOW_ACTION_MAIL_SHOW_HIDDEN(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-show-hidden") +#define E_SHELL_WINDOW_ACTION_MAIL_SHOW_SOURCE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-show-source") +#define E_SHELL_WINDOW_ACTION_MAIL_SMART_BACKWARD(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-smart-backward") +#define E_SHELL_WINDOW_ACTION_MAIL_SMART_FORWARD(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-smart-forward") +#define E_SHELL_WINDOW_ACTION_MAIL_STOP(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-stop") +#define E_SHELL_WINDOW_ACTION_MAIL_THREADS_COLLAPSE_ALL(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-threads-collapse-all") +#define E_SHELL_WINDOW_ACTION_MAIL_THREADS_EXPAND_ALL(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-threads-expand-all") +#define E_SHELL_WINDOW_ACTION_MAIL_THREADS_GROUP_BY(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-threads-group-by") +#define E_SHELL_WINDOW_ACTION_MAIL_TOOLS_FILTERS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-tools-filters") +#define E_SHELL_WINDOW_ACTION_MAIL_TOOLS_SEARCH_FOLDERS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-tools-search-folders") +#define E_SHELL_WINDOW_ACTION_MAIL_TOOLS_SUBSCRIPTIONS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-tools-subscriptions") +#define E_SHELL_WINDOW_ACTION_MAIL_UNDELETE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-undelete") +#define E_SHELL_WINDOW_ACTION_MAIL_VIEW_CLASSIC(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-view-classic") +#define E_SHELL_WINDOW_ACTION_MAIL_VIEW_VERTICAL(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-view-vertical") +#define E_SHELL_WINDOW_ACTION_MAIL_ZOOM_100(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-zoom-100") +#define E_SHELL_WINDOW_ACTION_MAIL_ZOOM_IN(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-zoom-in") +#define E_SHELL_WINDOW_ACTION_MAIL_ZOOM_OUT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-zoom-out") + +/* Mail Query Actions */ +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_ALL_MESSAGES(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-all-messages") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_IMPORTANT_MESSAGES(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-important-messages") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_LAST_5_DAYS_MESSAGES(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-last-5-days-messages") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_MESSAGES_NOT_JUNK(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-messages-not-junk") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_MESSAGES_WITH_ATTACHMENTS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-messages-with-attachments") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_NO_LABEL(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-no-label") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_READ_MESSAGES(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-read-messages") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_RECENT_MESSAGES(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-recent-messages") +#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_UNREAD_MESSAGES(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-filter-unread-messages") +#define E_SHELL_WINDOW_ACTION_MAIL_SCOPE_ALL_ACCOUNTS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-scope-all-accounts") +#define E_SHELL_WINDOW_ACTION_MAIL_SCOPE_CURRENT_ACCOUNT(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-scope-current-account") +#define E_SHELL_WINDOW_ACTION_MAIL_SCOPE_CURRENT_FOLDER(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-scope-current-folder") +#define E_SHELL_WINDOW_ACTION_MAIL_SCOPE_CURRENT_MESSAGE(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-scope-current-message") +#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_BODY_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-search-body-contains") +#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_MESSAGE_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-search-message-contains") +#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_RECIPIENTS_CONTAIN(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-search-recipients-contain") +#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_SENDER_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-search-sender-contains") +#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_SUBJECT_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-search-subject-contains") +#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_SUBJECT_OR_RECIPIENTS_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-search-subject-or-recipients-contains") +#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_SUBJECT_OR_SENDER_CONTAINS(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-search-subject-or-sender-contains") + +/* Action Groups */ +#define E_SHELL_WINDOW_ACTION_GROUP_MAIL(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "mail") +#define E_SHELL_WINDOW_ACTION_GROUP_MAIL_FILTER(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "mail-filter") +#define E_SHELL_WINDOW_ACTION_GROUP_MAIL_LABEL(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "mail-label") + +#endif /* E_MAIL_SHELL_VIEW_ACTIONS_H */ diff --git a/mail/e-mail-shell-view-private.c b/mail/e-mail-shell-view-private.c new file mode 100644 index 0000000000..5974cc7386 --- /dev/null +++ b/mail/e-mail-shell-view-private.c @@ -0,0 +1,890 @@ +/* + * e-mail-shell-view-private.c + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-shell-view-private.h" + +#include <widgets/menus/gal-view-factory-etable.h> + +static void +mail_shell_view_folder_tree_selected_cb (EMailShellView *mail_shell_view, + const gchar *full_name, + const gchar *uri, + guint32 flags, + EMFolderTree *folder_tree) +{ + EMailReader *reader; + gboolean folder_selected; + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + + folder_selected = + !(flags & CAMEL_FOLDER_NOSELECT) && + full_name != NULL; + + if (folder_selected) { + EMFolderTreeModel *model; + + model = em_folder_tree_get_model (folder_tree); + em_folder_tree_model_set_selected (model, uri); + em_folder_tree_model_save_state (model); + + e_mail_reader_set_folder_uri (reader, uri); + } else + e_mail_reader_set_folder (reader, NULL, NULL); + + e_shell_view_update_actions (E_SHELL_VIEW (mail_shell_view)); +} + +static void +mail_shell_view_folder_tree_popup_event_cb (EShellView *shell_view, + GdkEventButton *event) +{ + const gchar *widget_path; + + widget_path = "/mail-folder-popup"; + e_shell_view_show_popup_menu (shell_view, widget_path, event); +} + +static gboolean +mail_shell_view_key_press_event_cb (EMailShellView *mail_shell_view, + GdkEventKey *event) +{ + EShellView *shell_view; + EShellWindow *shell_window; + GtkAction *action; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + + if ((event->state & GDK_CONTROL_MASK) != 0) + return FALSE; + + switch (event->keyval) { + case GDK_space: + action = ACTION (MAIL_SMART_FORWARD); + break; + + case GDK_BackSpace: + action = ACTION (MAIL_SMART_BACKWARD); + break; + + default: + return FALSE; + } + + gtk_action_activate (action); + + return TRUE; +} + +static gint +mail_shell_view_message_list_key_press_cb (EMailShellView *mail_shell_view, + gint row, + ETreePath path, + gint col, + GdkEvent *event) +{ + return mail_shell_view_key_press_event_cb ( + mail_shell_view, &event->key); +} + +static gboolean +mail_shell_view_message_list_right_click_cb (EShellView *shell_view, + gint row, + ETreePath path, + gint col, + GdkEventButton *event) +{ + const gchar *widget_path; + + widget_path = "/mail-message-popup"; + e_shell_view_show_popup_menu (shell_view, widget_path, event); + + return TRUE; +} + +static void +mail_shell_view_reader_changed_cb (EMailShellView *mail_shell_view) +{ + EMailShellContent *mail_shell_content; + + mail_shell_content = mail_shell_view->priv->mail_shell_content; + e_mail_shell_content_update_view_instance (mail_shell_content); + e_mail_shell_view_update_sidebar (mail_shell_view); +} + +static void +mail_shell_view_reader_status_message_cb (EMailShellView *mail_shell_view, + const gchar *status_message) +{ + EShellView *shell_view; + EShellTaskbar *shell_taskbar; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_taskbar = e_shell_view_get_shell_taskbar (shell_view); + + e_shell_taskbar_set_message (shell_taskbar, status_message); +} + +static void +mail_shell_view_load_view_collection (EShellViewClass *shell_view_class) +{ + GalViewCollection *collection; + GalViewFactory *factory; + ETableSpecification *spec; + const gchar *base_dir; + gchar *filename; + + collection = shell_view_class->view_collection; + + base_dir = EVOLUTION_ETSPECDIR; + spec = e_table_specification_new (); + filename = g_build_filename (base_dir, ETSPEC_FILENAME, NULL); + if (!e_table_specification_load_from_file (spec, filename)) + g_critical ("Unable to load ETable specification file " + "for mail"); + g_free (filename); + + factory = gal_view_factory_etable_new (spec); + gal_view_collection_add_factory (collection, factory); + g_object_unref (factory); + g_object_unref (spec); + + gal_view_collection_load (collection); +} + +static void +mail_shell_view_notify_view_id_cb (EMailShellView *mail_shell_view) +{ + EMailShellContent *mail_shell_content; + GalViewInstance *view_instance; + const gchar *view_id; + + mail_shell_content = mail_shell_view->priv->mail_shell_content; + view_instance = NULL; /* FIXME */ + view_id = e_shell_view_get_view_id (E_SHELL_VIEW (mail_shell_view)); + + /* A NULL view ID implies we're in a custom view. But you can + * only get to a custom view via the "Define Views" dialog, which + * would have already modified the view instance appropriately. + * Furthermore, there's no way to refer to a custom view by ID + * anyway, since custom views have no IDs. */ + if (view_id == NULL) + return; + + gal_view_instance_set_current_view_id (view_instance, view_id); +} + +void +e_mail_shell_view_private_init (EMailShellView *mail_shell_view, + EShellViewClass *shell_view_class) +{ + if (!gal_view_collection_loaded (shell_view_class->view_collection)) + mail_shell_view_load_view_collection (shell_view_class); + + g_signal_connect ( + mail_shell_view, "notify::view-id", + G_CALLBACK (mail_shell_view_notify_view_id_cb), NULL); +} + +void +e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view) +{ + EMailShellViewPrivate *priv = mail_shell_view->priv; + EMailShellSidebar *mail_shell_sidebar; + EShell *shell; + EShellView *shell_view; + EShellContent *shell_content; + EShellSettings *shell_settings; + EShellSidebar *shell_sidebar; + EShellWindow *shell_window; + EMFormatHTMLDisplay *html_display; + EMFolderTreeModel *folder_tree_model; + EMFolderTree *folder_tree; + RuleContext *context; + FilterRule *rule = NULL; + GtkTreeModel *tree_model; + GtkUIManager *ui_manager; + MessageList *message_list; + EMailReader *reader; + GtkHTML *html; + const gchar *source; + guint merge_id; + gchar *uri; + gint ii = 0; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + ui_manager = e_shell_window_get_ui_manager (shell_window); + + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + tree_model = e_shell_settings_get_object ( + shell_settings, "mail-label-list-store"); + + e_shell_window_add_action_group (shell_window, "mail"); + e_shell_window_add_action_group (shell_window, "mail-filter"); + e_shell_window_add_action_group (shell_window, "mail-label"); + + merge_id = gtk_ui_manager_new_merge_id (ui_manager); + priv->label_merge_id = merge_id; + + /* Cache these to avoid lots of awkward casting. */ + priv->mail_shell_content = g_object_ref (shell_content); + priv->mail_shell_sidebar = g_object_ref (shell_sidebar); + + reader = E_MAIL_READER (shell_content); + html_display = e_mail_reader_get_html_display (reader); + message_list = e_mail_reader_get_message_list (reader); + + mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar); + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + + html = EM_FORMAT_HTML (html_display)->html; + + g_signal_connect_swapped ( + folder_tree, "folder-selected", + G_CALLBACK (mail_shell_view_folder_tree_selected_cb), + mail_shell_view); + + g_signal_connect_swapped ( + folder_tree, "popup-event", + G_CALLBACK (mail_shell_view_folder_tree_popup_event_cb), + mail_shell_view); + + g_signal_connect_swapped ( + message_list->tree, "key-press", + G_CALLBACK (mail_shell_view_message_list_key_press_cb), + mail_shell_view); + + g_signal_connect_swapped ( + message_list->tree, "right-click", + G_CALLBACK (mail_shell_view_message_list_right_click_cb), + mail_shell_view); + + g_signal_connect_swapped ( + reader, "changed", + G_CALLBACK (mail_shell_view_reader_changed_cb), + mail_shell_view); + + /* Use the same callback as "changed". */ + g_signal_connect_swapped ( + reader, "folder-loaded", + G_CALLBACK (mail_shell_view_reader_changed_cb), + mail_shell_view); + + g_signal_connect_swapped ( + tree_model, "row-changed", + G_CALLBACK (e_mail_shell_view_update_search_filter), + mail_shell_view); + + g_signal_connect_swapped ( + tree_model, "row-deleted", + G_CALLBACK (e_mail_shell_view_update_search_filter), + mail_shell_view); + + g_signal_connect_swapped ( + tree_model, "row-inserted", + G_CALLBACK (e_mail_shell_view_update_search_filter), + mail_shell_view); + + g_signal_connect_swapped ( + html, "key-press-event", + G_CALLBACK (mail_shell_view_key_press_event_cb), + mail_shell_view); + + g_signal_connect_swapped ( + html, "status-message", + G_CALLBACK (mail_shell_view_reader_status_message_cb), + mail_shell_view); + + e_mail_shell_view_actions_init (mail_shell_view); + e_mail_shell_view_update_search_filter (mail_shell_view); + e_mail_reader_init (reader); + + /* Populate built-in rules for search entry popup menu. + * Keep the assertions, please. If the conditions aren't + * met we're going to crash anyway, just more mysteriously. */ + context = e_shell_content_get_search_context (shell_content); + source = FILTER_SOURCE_DEMAND; + while ((rule = rule_context_next_rule (context, rule, source))) { + g_assert (ii < MAIL_NUM_SEARCH_RULES); + priv->search_rules[ii++] = g_object_ref (rule); + } + g_assert (ii == MAIL_NUM_SEARCH_RULES); + + /* Restore the previously selected folder. */ + folder_tree_model = em_folder_tree_get_model (folder_tree); + uri = em_folder_tree_model_get_selected (folder_tree_model); + if (uri != NULL) { + gboolean expanded; + + expanded = em_folder_tree_model_get_expanded_uri ( + folder_tree_model, uri); + em_folder_tree_set_selected (folder_tree, uri, FALSE); + e_mail_reader_set_folder_uri (reader, uri); + + if (!expanded) + em_folder_tree_model_set_expanded_uri ( + folder_tree_model, uri, expanded); + + g_free (uri); + } +} + +void +e_mail_shell_view_private_dispose (EMailShellView *mail_shell_view) +{ + EMailShellViewPrivate *priv = mail_shell_view->priv; + gint ii; + + DISPOSE (priv->mail_shell_content); + DISPOSE (priv->mail_shell_sidebar); + + for (ii = 0; ii < MAIL_NUM_SEARCH_RULES; ii++) + DISPOSE (priv->search_rules[ii]); +} + +void +e_mail_shell_view_private_finalize (EMailShellView *mail_shell_view) +{ + /* XXX Nothing to do? */ +} + +void +e_mail_shell_view_execute_search (EMailShellView *mail_shell_view) +{ + EShell *shell; + EShellView *shell_view; + EShellWindow *shell_window; + EShellContent *shell_content; + EShellSettings *shell_settings; + EMFormatHTMLDisplay *html_display; + EMailShellContent *mail_shell_content; + MessageList *message_list; + FilterRule *rule; + EMailReader *reader; + CamelFolder *folder; + GtkAction *action; + GtkTreeModel *model; + GtkTreePath *path; + GtkTreeIter tree_iter; + GString *string; + GList *iter; + GSList *search_strings = NULL; + const gchar *folder_uri; + const gchar *text; + gboolean valid; + gchar *query; + gchar *temp; + gchar *tag; + gint value; + + g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + mail_shell_content = mail_shell_view->priv->mail_shell_content; + + reader = E_MAIL_READER (shell_content); + html_display = e_mail_reader_get_html_display (reader); + message_list = e_mail_reader_get_message_list (reader); + + folder_uri = message_list->folder_uri; + folder = message_list->folder; + + /* This returns a new object reference. */ + model = e_shell_settings_get_object ( + shell_settings, "mail-label-list-store"); + + text = e_shell_content_get_search_text (shell_content); + if (text == NULL || *text == '\0') { + query = g_strdup (""); + goto filter; + } + + /* Replace variables in the selected rule with the + * current search text and extract a query string. */ + + action = ACTION (MAIL_SEARCH_SUBJECT_OR_SENDER_CONTAINS); + value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + g_return_if_fail (value >= 0 && value < MAIL_NUM_SEARCH_RULES); + rule = mail_shell_view->priv->search_rules[value]; + + for (iter = rule->parts; iter != NULL; iter = iter->next) { + FilterPart *part = iter->data; + FilterElement *element = NULL; + + if (strcmp (part->name, "subject") == 0) + element = filter_part_find_element (part, "subject"); + else if (strcmp (part->name, "body") == 0) + element = filter_part_find_element (part, "word"); + else if (strcmp (part->name, "sender") == 0) + element = filter_part_find_element (part, "sender"); + else if (strcmp (part->name, "to") == 0) + element = filter_part_find_element (part, "recipient"); + + if (strcmp (part->name, "body") == 0) { + struct _camel_search_words *words; + gint ii; + + words = camel_search_words_split ((guchar *) text); + for (ii = 0; ii < words->len; ii++) + search_strings = g_slist_prepend ( + search_strings, g_strdup ( + words->words[ii]->word)); + camel_search_words_free (words); + } + + if (element != NULL) { + FilterInput *input = FILTER_INPUT (element); + filter_input_set_value (input, text); + } + } + + string = g_string_sized_new (1024); + filter_rule_build_code (rule, string); + query = g_string_free (string, FALSE); + +filter: + + /* Apply selected filter. */ + + value = e_shell_content_get_filter_value (shell_content); + switch (value) { + case MAIL_FILTER_ALL_MESSAGES: + break; + + case MAIL_FILTER_UNREAD_MESSAGES: + temp = g_strdup_printf ( + "(and %s (match-all (not " + "(system-flag \"Seen\"))))", query); + g_free (query); + query = temp; + break; + + case MAIL_FILTER_NO_LABEL: + string = g_string_sized_new (1024); + g_string_append_printf ( + string, "(and %s (and ", query); + valid = gtk_tree_model_get_iter_first ( + model, &tree_iter); + while (valid) { + tag = e_mail_label_list_store_get_tag ( + E_MAIL_LABEL_LIST_STORE (model), + &tree_iter); + g_string_append_printf ( + string, " (match-all (not (or " + "(= (user-tag \"label\") \"%s\") " + "(user-flag \"$Label%s\") " + "(user-flag \"%s\"))))", + tag, tag, tag); + g_free (tag); + + valid = gtk_tree_model_iter_next ( + model, &tree_iter); + } + g_string_append_len (string, "))", 2); + g_free (query); + query = g_string_free (string, FALSE); + break; + + case MAIL_FILTER_READ_MESSAGES: + temp = g_strdup_printf ( + "(and %s (match-all " + "(system-flag \"Seen\")))", query); + g_free (query); + query = temp; + break; + + case MAIL_FILTER_RECENT_MESSAGES: + if (em_utils_folder_is_sent (folder, folder_uri)) + temp = g_strdup_printf ( + "(and %s (match-all " + "(> (get-sent-date) " + "(- (get-current-date) 86400))))", + query); + else + temp = g_strdup_printf ( + "(and %s (match-all " + "(> (get-received-date) " + "(- (get_current_date) 86400))))", + query); + g_free (query); + query = temp; + break; + + case MAIL_FILTER_LAST_5_DAYS_MESSAGES: + if (em_utils_folder_is_sent (folder, folder_uri)) + temp = g_strdup_printf ( + "(and %s (match-all " + "(> (get-sent-date) " + "(- (get-current-date) 432000))))", + query); + else + temp = g_strdup_printf ( + "(and %s (match-all " + "(> (get-received-date) " + "(- (get_current_date) 432000))))", + query); + g_free (query); + query = temp; + break; + + case MAIL_FILTER_MESSAGES_WITH_ATTACHMENTS: + temp = g_strdup_printf ( + "(and %s (match-all " + "(system-flag \"Attachments\")))", query); + g_free (query); + query = temp; + break; + + case MAIL_FILTER_IMPORTANT_MESSAGES: + temp = g_strdup_printf ( + "(and %s (match-all " + "(system-flag \"Flagged\")))", query); + g_free (query); + query = temp; + break; + + case MAIL_FILTER_MESSAGES_NOT_JUNK: + temp = g_strdup_printf ( + "(and %s (match-all (not " + "(system-flag \"junk\"))))", query); + g_free (query); + query = temp; + break; + + default: + /* The action value also serves as a path for + * the label list store. That's why we number + * the label actions from zero. */ + path = gtk_tree_path_new_from_indices (value, -1); + gtk_tree_model_get_iter (model, &tree_iter, path); + gtk_tree_path_free (path); + + tag = e_mail_label_list_store_get_tag ( + E_MAIL_LABEL_LIST_STORE (model), &tree_iter); + temp = g_strdup_printf ( + "(and %s (match-all (or " + "(= (user-tag \"label\") \"%s\") " + "(user-flag \"$Label%s\") " + "(user-flag \"%s\"))))", + query, tag, tag, tag); + g_free (tag); + + g_free (query); + query = temp; + break; + } + + message_list_set_search (message_list, query); + + e_mail_shell_content_set_search_strings ( + mail_shell_content, search_strings); + + g_slist_foreach (search_strings, (GFunc) g_free, NULL); + g_slist_free (search_strings); + + g_object_unref (model); + g_free (query); +} + +/* Helper for e_mail_shell_view_create_filter_from_selected() */ +static void +mail_shell_view_create_filter_cb (CamelFolder *folder, + const gchar *uid, + CamelMimeMessage *message, + gpointer user_data) +{ + struct { + const gchar *source; + gint type; + } *filter_data = user_data; + + if (message != NULL) + filter_gui_add_from_message ( + message, filter_data->source, filter_data->type); + + g_free (filter_data); +} + +void +e_mail_shell_view_create_filter_from_selected (EMailShellView *mail_shell_view, + gint filter_type) +{ + EMailReader *reader; + MessageList *message_list; + CamelFolder *folder; + const gchar *filter_source; + const gchar *folder_uri; + GPtrArray *uids; + + struct { + const gchar *source; + gint type; + } *filter_data; + + g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + folder_uri = message_list->folder_uri; + folder = message_list->folder; + + if (em_utils_folder_is_sent (folder, folder_uri)) + filter_source = FILTER_SOURCE_OUTGOING; + else if (em_utils_folder_is_outbox (folder, folder_uri)) + filter_source = FILTER_SOURCE_OUTGOING; + else + filter_source = FILTER_SOURCE_INCOMING; + + uids = message_list_get_selected (message_list); + + if (uids->len == 1) { + filter_data = g_malloc (sizeof (*filter_data)); + filter_data->source = filter_source; + filter_data->type = filter_type; + + mail_get_message ( + folder, uids->pdata[0], + mail_shell_view_create_filter_cb, + filter_data, mail_msg_unordered_push); + } + + em_utils_uids_free (uids); +} + +/* Helper for e_mail_shell_view_create_vfolder_from_selected() */ +static void +mail_shell_view_create_vfolder_cb (CamelFolder *folder, + const gchar *uid, + CamelMimeMessage *message, + gpointer user_data) +{ + struct { + gchar *uri; + gint type; + } *vfolder_data = user_data; + + if (message != NULL) + vfolder_gui_add_from_message ( + message, vfolder_data->type, vfolder_data->uri); + + g_free (vfolder_data->uri); + g_free (vfolder_data); +} + +void +e_mail_shell_view_create_vfolder_from_selected (EMailShellView *mail_shell_view, + gint vfolder_type) +{ + EMailReader *reader; + MessageList *message_list; + CamelFolder *folder; + const gchar *folder_uri; + GPtrArray *uids; + + struct { + gchar *uri; + gint type; + } *vfolder_data; + + g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + folder_uri = message_list->folder_uri; + folder = message_list->folder; + + uids = message_list_get_selected (message_list); + + if (uids->len == 1) { + vfolder_data = g_malloc (sizeof (*vfolder_data)); + vfolder_data->uri = g_strdup (folder_uri); + vfolder_data->type = vfolder_type; + + mail_get_message ( + folder, uids->pdata[0], + mail_shell_view_create_vfolder_cb, + vfolder_data, mail_msg_unordered_push); + } + + em_utils_uids_free (uids); +} + +void +e_mail_shell_view_update_sidebar (EMailShellView *mail_shell_view) +{ + EShellSidebar *shell_sidebar; + EShellModule *shell_module; + EShellView *shell_view; + EMailReader *reader; + MessageList *message_list; + CamelStore *local_store; + CamelFolder *folder; + GPtrArray *selected; + GString *buffer; + const gchar *display_name; + const gchar *folder_uri; + gchar *folder_name; + gchar *title; + guint32 num_deleted; + guint32 num_junked; + guint32 num_junked_not_deleted; + guint32 num_unread; + guint32 num_visible; + + g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_module = e_shell_view_get_shell_module (shell_view); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + local_store = e_mail_shell_module_get_local_store (shell_module); + + reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content); + message_list = e_mail_reader_get_message_list (reader); + folder_uri = message_list->folder_uri; + folder = message_list->folder; + + /* If no folder is selected, reset the sidebar banners + * to their default values and stop. */ + if (folder == NULL) { + GtkAction *action; + gchar *label; + + action = e_shell_view_get_action (shell_view); + + g_object_get (action, "label", &label, NULL); + e_shell_sidebar_set_secondary_text (shell_sidebar, NULL); + e_shell_view_set_title (shell_view, label); + g_free (label); + + return; + } + + camel_object_get ( + folder, NULL, + CAMEL_FOLDER_NAME, &folder_name, + CAMEL_FOLDER_DELETED, &num_deleted, + CAMEL_FOLDER_JUNKED, &num_junked, + CAMEL_FOLDER_JUNKED_NOT_DELETED, &num_junked_not_deleted, + CAMEL_FOLDER_UNREAD, &num_unread, + CAMEL_FOLDER_VISIBLE, &num_visible, + NULL); + + buffer = g_string_sized_new (256); + selected = message_list_get_selected (message_list); + + if (selected->len > 1) + g_string_append_printf ( + buffer, ngettext ("%d selected, ", "%d selected, ", + selected->len), selected->len); + + if (CAMEL_IS_VTRASH_FOLDER (folder)) { + CamelVTrashFolder *trash_folder; + + trash_folder = (CamelVTrashFolder *) folder; + + /* "Trash" folder */ + if (trash_folder->type == CAMEL_VTRASH_FOLDER_TRASH) + g_string_append_printf ( + buffer, ngettext ("%d deleted", + "%d deleted", num_deleted), num_deleted); + + /* "Junk" folder (hide deleted messages) */ + else if (e_mail_reader_get_hide_deleted (reader)) + g_string_append_printf ( + buffer, ngettext ("%d junk", + "%d junk", num_junked_not_deleted), + num_junked_not_deleted); + + /* "Junk" folder (show deleted messages) */ + else + g_string_append_printf ( + buffer, ngettext ("%d junk", "%d junk", + num_junked), num_junked); + + /* "Drafts" folder */ + } else if (em_utils_folder_is_drafts (folder, folder_uri)) { + g_string_append_printf ( + buffer, ngettext ("%d draft", "%d drafts", + num_visible), num_visible); + + /* "Outbox" folder */ + } else if (em_utils_folder_is_outbox (folder, folder_uri)) { + g_string_append_printf ( + buffer, ngettext ("%d unsent", "%d unsent", + num_visible), num_visible); + + /* "Sent" folder */ + } else if (em_utils_folder_is_sent (folder, folder_uri)) { + g_string_append_printf ( + buffer, ngettext ("%d sent", "%d sent", + num_visible), num_visible); + + /* Normal folder */ + } else { + if (!e_mail_reader_get_hide_deleted (reader)) + num_visible += + num_deleted - num_junked + + num_junked_not_deleted; + + if (num_unread > 0 && selected->len <= 1) + g_string_append_printf ( + buffer, ngettext ("%d unread, ", + "%d unread, ", num_unread), num_unread); + g_string_append_printf ( + buffer, ngettext ("%d total", "%d total", + num_visible), num_visible); + } + + message_list_free_uids (message_list, selected); + + /* Choose a suitable folder name for displaying. */ + if (folder->parent_store == local_store && ( + strcmp (folder_name, "Drafts") == 0 || + strcmp (folder_name, "Inbox") == 0 || + strcmp (folder_name, "Outbox") == 0 || + strcmp (folder_name, "Sent") == 0 || + strcmp (folder_name, "Templates") == 0)) + display_name = _(folder_name); + else if (strcmp (folder_name, "INBOX") == 0) + display_name = _("Inbox"); + else + display_name = folder_name; + + title = g_strdup_printf ("%s (%s)", display_name, buffer->str); + e_shell_sidebar_set_secondary_text (shell_sidebar, buffer->str); + e_shell_view_set_title (shell_view, title); + g_free (title); + + camel_object_free (folder, CAMEL_FOLDER_NAME, folder_name); + g_string_free (buffer, TRUE); +} diff --git a/mail/e-mail-shell-view-private.h b/mail/e-mail-shell-view-private.h new file mode 100644 index 0000000000..97bb638b3b --- /dev/null +++ b/mail/e-mail-shell-view-private.h @@ -0,0 +1,169 @@ +/* + * e-mail-shell-view-private.h + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MAIL_SHELL_VIEW_PRIVATE_H +#define E_MAIL_SHELL_VIEW_PRIVATE_H + +#include "e-mail-shell-view.h" + +#include <glib/gi18n.h> +#include <gtkhtml/gtkhtml.h> +#include <camel/camel-disco-store.h> +#include <camel/camel-offline-store.h> +#include <camel/camel-vtrash-folder.h> +#include <camel/camel-search-private.h> /* for camel_search_word */ + +#include "e-util/e-util.h" +#include "e-util/e-binding.h" +#include "e-util/gconf-bridge.h" +#include "e-util/e-account-utils.h" +#include "filter/filter-part.h" +#include "widgets/misc/e-popup-action.h" +#include "widgets/menus/gal-view-instance.h" + +#include "e-mail-label-dialog.h" +#include "e-mail-label-list-store.h" +#include "e-mail-reader.h" +#include "em-composer-utils.h" +#include "em-folder-properties.h" +#include "em-folder-selector.h" +#include "em-folder-utils.h" +#include "em-subscribe-editor.h" +#include "em-utils.h" +#include "mail-autofilter.h" +#include "mail-config.h" +#include "mail-ops.h" +#include "mail-send-recv.h" +#include "mail-vfolder.h" + +#include "e-mail-shell-content.h" +#include "e-mail-shell-module.h" +#include "e-mail-shell-sidebar.h" +#include "e-mail-shell-view-actions.h" + +#define E_MAIL_SHELL_VIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_SHELL_VIEW, EMailShellViewPrivate)) + +/* Shorthand, requires a variable named "shell_window". */ +#define ACTION(name) \ + (E_SHELL_WINDOW_ACTION_##name (shell_window)) +#define ACTION_GROUP(name) \ + (E_SHELL_WINDOW_ACTION_GROUP_##name (shell_window)) + +/* For use in dispose() methods. */ +#define DISPOSE(obj) \ + G_STMT_START { \ + if ((obj) != NULL) { g_object_unref (obj); (obj) = NULL; } \ + } G_STMT_END + +/* ETable Specifications */ +#define ETSPEC_FILENAME "message-list.etspec" + +G_BEGIN_DECLS + +/* Filter items are displayed in ascending order. + * Labels are numbered from zero, so subsequent items must have + * sufficiently large values. Unfortunately this introduces an + * arbitrary upper bound on labels. */ +enum { + MAIL_FILTER_ALL_MESSAGES = -3, + MAIL_FILTER_UNREAD_MESSAGES = -2, + MAIL_FILTER_NO_LABEL = -1, + /* Labels go here */ + MAIL_FILTER_READ_MESSAGES = 5000, + MAIL_FILTER_RECENT_MESSAGES = 5001, + MAIL_FILTER_LAST_5_DAYS_MESSAGES = 5002, + MAIL_FILTER_MESSAGES_WITH_ATTACHMENTS = 5003, + MAIL_FILTER_IMPORTANT_MESSAGES = 5004, + MAIL_FILTER_MESSAGES_NOT_JUNK = 5005 +}; + +/* Search items are displayed in ascending order. */ +enum { + MAIL_SEARCH_SUBJECT_OR_SENDER_CONTAINS, + MAIL_SEARCH_SUBJECT_OR_RECIPIENTS_CONTAINS, + MAIL_SEARCH_RECIPIENTS_CONTAIN, + MAIL_SEARCH_MESSAGE_CONTAINS, + MAIL_SEARCH_SUBJECT_CONTAINS, + MAIL_SEARCH_SENDER_CONTAINS, + MAIL_SEARCH_BODY_CONTAINS, + MAIL_NUM_SEARCH_RULES +}; + +/* Scope items are displayed in ascending order. */ +enum { + MAIL_SCOPE_CURRENT_FOLDER, + MAIL_SCOPE_CURRENT_ACCOUNT, + MAIL_SCOPE_ALL_ACCOUNTS, + MAIL_SCOPE_CURRENT_MESSAGE +}; + +struct _EMailShellViewPrivate { + + /*** Other Stuff ***/ + + /* These are just for convenience. */ + EMailShellContent *mail_shell_content; + EMailShellSidebar *mail_shell_sidebar; + + /* For UI merging and unmerging. */ + guint merge_id; + guint label_merge_id; + + /* Filter rules correspond to the search entry menu. */ + FilterRule *search_rules[MAIL_NUM_SEARCH_RULES]; + + guint show_deleted : 1; +}; + +void e_mail_shell_view_private_init + (EMailShellView *mail_shell_view, + EShellViewClass *shell_view_class); +void e_mail_shell_view_private_constructed + (EMailShellView *mail_shell_view); +void e_mail_shell_view_private_dispose + (EMailShellView *mail_shell_view); +void e_mail_shell_view_private_finalize + (EMailShellView *mail_shell_view); + +/* Private Utilities */ + +void e_mail_shell_view_actions_init + (EMailShellView *mail_shell_view); +void e_mail_shell_view_execute_search + (EMailShellView *mail_shell_view); +void e_mail_shell_view_create_filter_from_selected + (EMailShellView *mail_shell_view, + gint filter_type); +void e_mail_shell_view_create_vfolder_from_selected + (EMailShellView *mail_shell_view, + gint vfolder_type); +void e_mail_shell_view_update_popup_labels + (EMailShellView *mail_shell_view); +void e_mail_shell_view_update_search_filter + (EMailShellView *mail_shell_view); +void e_mail_shell_view_update_sidebar + (EMailShellView *mail_shell_view); + +G_END_DECLS + +#endif /* E_MAIL_SHELL_VIEW_PRIVATE_H */ diff --git a/mail/e-mail-shell-view.c b/mail/e-mail-shell-view.c new file mode 100644 index 0000000000..ab0e7d92d5 --- /dev/null +++ b/mail/e-mail-shell-view.c @@ -0,0 +1,260 @@ +/* + * e-mail-shell-view.c + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-shell-view-private.h" + +GType e_mail_shell_view_type = 0; +static gpointer parent_class; + +static void +mail_shell_view_dispose (GObject *object) +{ + e_mail_shell_view_private_dispose (E_MAIL_SHELL_VIEW (object)); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +mail_shell_view_finalize (GObject *object) +{ + e_mail_shell_view_private_finalize (E_MAIL_SHELL_VIEW (object)); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +mail_shell_view_constructed (GObject *object) +{ + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + e_mail_shell_view_private_constructed (E_MAIL_SHELL_VIEW (object)); +} + +static void +mail_shell_view_toggled (EShellView *shell_view) +{ + EMailShellViewPrivate *priv; + EShellWindow *shell_window; + GtkUIManager *ui_manager; + const gchar *basename; + gboolean view_is_active; + + /* Chain up to parent's toggled() method. */ + E_SHELL_VIEW_CLASS (parent_class)->toggled (shell_view); + + priv = E_MAIL_SHELL_VIEW_GET_PRIVATE (shell_view); + + shell_window = e_shell_view_get_shell_window (shell_view); + ui_manager = e_shell_window_get_ui_manager (shell_window); + view_is_active = e_shell_view_is_active (shell_view); + basename = E_MAIL_READER_UI_DEFINITION; + + if (view_is_active && priv->merge_id == 0) { + priv->merge_id = e_load_ui_definition (ui_manager, basename); + e_mail_reader_create_charset_menu ( + E_MAIL_READER (priv->mail_shell_content), + ui_manager, priv->merge_id); + } else if (!view_is_active && priv->merge_id != 0) { + gtk_ui_manager_remove_ui (ui_manager, priv->merge_id); + priv->merge_id = 0; + } + + gtk_ui_manager_ensure_update (ui_manager); +} + +static void +mail_shell_view_update_actions (EShellView *shell_view) +{ + EMailShellView *mail_shell_view; + EMailShellSidebar *mail_shell_sidebar; + EShellContent *shell_content; + EShellSidebar *shell_sidebar; + EShellWindow *shell_window; + EMFolderTree *folder_tree; + EAccount *account = NULL; + GtkAction *action; + const gchar *label; + gchar *uri; + gboolean sensitive; + guint32 state; + + /* Be descriptive. */ + gboolean account_is_groupwise; + gboolean folder_allows_children; + gboolean folder_can_be_deleted; + gboolean folder_is_junk; + gboolean folder_is_outbox; + gboolean folder_is_store; + gboolean folder_is_trash; + + mail_shell_view = E_MAIL_SHELL_VIEW (shell_view); + + shell_window = e_shell_view_get_shell_window (shell_view); + + shell_content = e_shell_view_get_shell_content (shell_view); + e_mail_reader_update_actions (E_MAIL_READER (shell_content)); + + mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar; + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + state = e_shell_sidebar_check_state (shell_sidebar); + + folder_allows_children = + (state & E_MAIL_SHELL_SIDEBAR_FOLDER_ALLOWS_CHILDREN); + folder_can_be_deleted = + (state & E_MAIL_SHELL_SIDEBAR_FOLDER_CAN_DELETE); + folder_is_junk = + (state & E_MAIL_SHELL_SIDEBAR_FOLDER_IS_JUNK); + folder_is_outbox = + (state & E_MAIL_SHELL_SIDEBAR_FOLDER_IS_OUTBOX); + folder_is_store = + (state & E_MAIL_SHELL_SIDEBAR_FOLDER_IS_STORE); + folder_is_trash = + (state & E_MAIL_SHELL_SIDEBAR_FOLDER_IS_TRASH); + + uri = em_folder_tree_get_selected_uri (folder_tree); + if (uri != NULL) { + account = mail_config_get_account_by_source_url (uri); + + /* FIXME This belongs in a GroupWise plugin. */ + account_is_groupwise = + (g_strrstr (uri, "groupwise://") != NULL) && + account != NULL && account->parent_uid != NULL; + + g_free (uri); + } + + action = ACTION (MAIL_ACCOUNT_DISABLE); + sensitive = (account != NULL) && folder_is_store; + if (account_is_groupwise) + label = _("Proxy _Logout"); + else + label = _("_Disable Account"); + gtk_action_set_sensitive (action, sensitive); + g_object_set (action, "label", label, NULL); + + action = ACTION (MAIL_EMPTY_TRASH); + sensitive = folder_is_trash; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MAIL_FLUSH_OUTBOX); + sensitive = folder_is_outbox; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MAIL_FOLDER_COPY); + sensitive = !folder_is_store; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MAIL_FOLDER_DELETE); + sensitive = !folder_is_store && folder_can_be_deleted; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MAIL_FOLDER_MOVE); + sensitive = !folder_is_store && folder_can_be_deleted; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MAIL_FOLDER_NEW); + sensitive = folder_allows_children; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MAIL_FOLDER_PROPERTIES); + sensitive = !folder_is_store; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MAIL_FOLDER_REFRESH); + sensitive = !folder_is_store; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (MAIL_FOLDER_RENAME); + sensitive = !folder_is_store && folder_can_be_deleted; + gtk_action_set_sensitive (action, sensitive); + + e_mail_shell_view_update_popup_labels (mail_shell_view); +} + +static void +mail_shell_view_class_init (EMailShellViewClass *class, + GTypeModule *type_module) +{ + GObjectClass *object_class; + EShellViewClass *shell_view_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMailShellViewPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->dispose = mail_shell_view_dispose; + object_class->finalize = mail_shell_view_finalize; + object_class->constructed = mail_shell_view_constructed; + + shell_view_class = E_SHELL_VIEW_CLASS (class); + shell_view_class->label = _("Mail"); + shell_view_class->icon_name = "evolution-mail"; + shell_view_class->ui_definition = "evolution-mail.ui"; + shell_view_class->ui_manager_id = "org.gnome.evolution.mail"; + shell_view_class->search_options = "/mail-search-options"; + shell_view_class->search_rules = "searchtypes.xml"; + shell_view_class->type_module = type_module; + shell_view_class->new_shell_content = e_mail_shell_content_new; + shell_view_class->new_shell_sidebar = e_mail_shell_sidebar_new; + shell_view_class->toggled = mail_shell_view_toggled; + shell_view_class->update_actions = mail_shell_view_update_actions; +} + +static void +mail_shell_view_init (EMailShellView *mail_shell_view, + EShellViewClass *shell_view_class) +{ + mail_shell_view->priv = + E_MAIL_SHELL_VIEW_GET_PRIVATE (mail_shell_view); + + e_mail_shell_view_private_init (mail_shell_view, shell_view_class); +} + +GType +e_mail_shell_view_get_type (GTypeModule *type_module) +{ + if (e_mail_shell_view_type == 0) { + const GTypeInfo type_info = { + sizeof (EMailShellViewClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) mail_shell_view_class_init, + (GClassFinalizeFunc) NULL, + type_module, + sizeof (EMailShellView), + 0, /* n_preallocs */ + (GInstanceInitFunc) mail_shell_view_init, + NULL /* value_table */ + }; + + e_mail_shell_view_type = + g_type_module_register_type ( + type_module, E_TYPE_SHELL_VIEW, + "EMailShellView", &type_info, 0); + } + + return e_mail_shell_view_type; +} diff --git a/mail/e-mail-shell-view.h b/mail/e-mail-shell-view.h new file mode 100644 index 0000000000..2c5a3642ab --- /dev/null +++ b/mail/e-mail-shell-view.h @@ -0,0 +1,76 @@ +/* + * e-mail-shell-view.h + * + * 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/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_MAIL_SHELL_VIEW_H +#define E_MAIL_SHELL_VIEW_H + +#include <shell/e-shell-view.h> + +#include <e-mail-shell-content.h> +#include <e-mail-shell-sidebar.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_SHELL_VIEW \ + (e_mail_shell_view_type) +#define E_MAIL_SHELL_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_SHELL_VIEW, EMailShellView)) +#define E_MAIL_SHELL_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_SHELL_VIEW, EMailShellViewClass)) +#define E_IS_MAIL_SHELL_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_SHELL_VIEW)) +#define E_IS_MAIL_SHELL_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_SHELL_VIEW)) +#define E_MAIL_SHELL_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_SHELL_VIEW, EMailShellViewClass)) + +G_BEGIN_DECLS + +extern GType e_mail_shell_view_type; + +typedef struct _EMailShellView EMailShellView; +typedef struct _EMailShellViewClass EMailShellViewClass; +typedef struct _EMailShellViewPrivate EMailShellViewPrivate; + +struct _EMailShellView { + EShellView parent; + EMailShellViewPrivate *priv; +}; + +struct _EMailShellViewClass { + EShellViewClass parent_class; +}; + +GType e_mail_shell_view_get_type + (GTypeModule *type_module); +gboolean e_mail_shell_view_get_show_deleted + (EMailShellView *mail_shell_view); +void e_mail_shell_view_set_show_deleted + (EMailShellView *mail_shell_view, + gboolean show_deleted); + +G_END_DECLS + +#endif /* E_MAIL_SHELL_VIEW_H */ diff --git a/mail/e-searching-tokenizer.c b/mail/e-searching-tokenizer.c index 9704ebb96d..129aa0539b 100644 --- a/mail/e-searching-tokenizer.c +++ b/mail/e-searching-tokenizer.c @@ -38,77 +38,17 @@ #define d(x) +#define E_SEARCHING_TOKENIZER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_SEARCHING_TOKENIZER, ESearchingTokenizerPrivate)) + enum { MATCH_SIGNAL, LAST_SIGNAL }; -static guint signals[LAST_SIGNAL] = { 0, }; - -static void e_searching_tokenizer_begin (HTMLTokenizer *, const char *); -static void e_searching_tokenizer_end (HTMLTokenizer *); -static char *e_searching_tokenizer_peek_token (HTMLTokenizer *); -static char *e_searching_tokenizer_next_token (HTMLTokenizer *); -static gboolean e_searching_tokenizer_has_more (HTMLTokenizer *); - -static HTMLTokenizer *e_searching_tokenizer_clone (HTMLTokenizer *); - -/* - static const gchar *space_tags[] = { "br", NULL };*/ - -static HTMLTokenizerClass *parent_class = NULL; - -/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ - -/* ??? -typedef struct _SharedState SharedState; -struct _SharedState { - gint refs; - gchar *str_primary; - gchar *str_secondary; - gboolean case_sensitive_primary; - gboolean case_sensitive_secondary; -}; -*/ - -/* ********************************************************************** */ - - -#if 0 -static SharedState * -shared_state_new (void) -{ - SharedState *shared = g_new0 (SharedState, 1); - shared->refs = 1; - return shared; -} - -static void -shared_state_ref (SharedState *shared) -{ - g_return_if_fail (shared != NULL); - g_return_if_fail (shared->refs > 0); - ++shared->refs; -} - -static void -shared_state_unref (SharedState *shared) -{ - if (shared) { - g_return_if_fail (shared->refs > 0); - --shared->refs; - if (shared->refs == 0) { - g_free (shared->str_primary); - g_free (shared->str_secondary); - g_free (shared); - } - } -} -#endif - -/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ - -/* ********************************************************************** */ +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; /* Utility functions */ @@ -184,7 +124,7 @@ ignore_tag (const char *tag) *out = 0; for (i=0;i<sizeof(ignored_tags)/sizeof(ignored_tags[0]);i++) { - if (strcmp(t, ignored_tags[i]) == 0) + if (strcmp (t, ignored_tags[i]) == 0) return 1; } @@ -222,7 +162,7 @@ struct _trie { /* will be enabled only if debug is enabled */ #if d(1) -1 != -1 static void -dump_trie(struct _state *s, int d) +dump_trie (struct _state *s, int d) { char *p = alloca(d*2+1); struct _match *m; @@ -235,7 +175,7 @@ dump_trie(struct _state *s, int d) while (m) { printf(" %s'%c' -> %p\n", p, m->ch, m->match); if (m->match) - dump_trie(m->match, d+1); + dump_trie (m->match, d+1); m = m->next; } } @@ -247,7 +187,7 @@ dump_trie(struct _state *s, int d) for a neat demo */ static inline struct _match * -g(struct _state *q, guint32 c) +g (struct _state *q, guint32 c) { struct _match *m = q->matches; @@ -258,7 +198,7 @@ g(struct _state *q, guint32 c) } static struct _trie * -build_trie(int nocase, int len, unsigned char **words) +build_trie (int nocase, int len, unsigned char **words) { struct _state *q, *qt, *r; const unsigned char *word; @@ -275,8 +215,8 @@ build_trie(int nocase, int len, unsigned char **words) trie->root.fail = NULL; trie->root.next = NULL; - trie->state_chunks = e_memchunk_new(8, sizeof(struct _state)); - trie->match_chunks = e_memchunk_new(8, sizeof(struct _match)); + trie->state_chunks = e_memchunk_new (8, sizeof(struct _state)); + trie->match_chunks = e_memchunk_new (8, sizeof(struct _match)); /* This will correspond to the length of the longest pattern */ state_depth_size = 0; @@ -294,8 +234,8 @@ build_trie(int nocase, int len, unsigned char **words) depth = 0; while ((c = camel_utf8_getc (&word))) { if (nocase) - c = g_unichar_tolower(c); - m = g(q, c); + c = g_unichar_tolower (c); + m = g (q, c); if (m == NULL) { m = e_memchunk_alloc(trie->match_chunks); m->ch = c; @@ -324,7 +264,7 @@ build_trie(int nocase, int len, unsigned char **words) } d(printf("Dumping trie:\n")); - d(dump_trie(&trie->root, 0)); + d(dump_trie (&trie->root, 0)); /* Step 2: Build failure graph */ @@ -340,14 +280,14 @@ build_trie(int nocase, int len, unsigned char **words) c = m->ch; qt = m->match; r = q->fail; - while (r && (n = g(r, c)) == NULL) + while (r && (n = g (r, c)) == NULL) r = r->fail; if (r != NULL) { qt->fail = n->match; if (qt->fail->final > qt->final) qt->final = qt->fail->final; } else { - if ((n = g(&trie->root, c))) + if ((n = g (&trie->root, c))) qt->fail = n->match; else qt->fail = &trie->root; @@ -358,10 +298,10 @@ build_trie(int nocase, int len, unsigned char **words) } } - d(printf("After failure analysis\n")); - d(dump_trie(&trie->root, 0)); + d (printf("After failure analysis\n")); + d (dump_trie (&trie->root, 0)); - g_free(state_depth); + g_free (state_depth); trie->max_depth = state_depth_size; @@ -369,12 +309,12 @@ build_trie(int nocase, int len, unsigned char **words) } static void -free_trie(struct _trie *t) +free_trie (struct _trie *t) { e_memchunk_destroy(t->match_chunks); e_memchunk_destroy(t->state_chunks); - g_free(t); + g_free (t); } /* ********************************************************************** */ @@ -444,10 +384,10 @@ searcher_new (int flags, int argc, unsigned char **argv, const char *tags, const s = g_malloc(sizeof(*s)); - s->t = build_trie((flags&SEARCH_CASE) == 0, argc, argv); + s->t = build_trie ((flags&SEARCH_CASE) == 0, argc, argv); s->words = argc; - s->tags = g_strdup(tags); - s->tage = g_strdup(tage); + s->tags = g_strdup (tags); + s->tage = g_strdup (tage); s->flags = flags; s->state = &s->t->root; s->matchcount = 0; @@ -476,20 +416,20 @@ searcher_new (int flags, int argc, unsigned char **argv, const char *tags, const } static void -searcher_free(struct _searcher *s) +searcher_free (struct _searcher *s) { struct _token *t; - while ((t = (struct _token *)e_dlist_remhead(&s->input))) - g_free(t); - while ((t = (struct _token *)e_dlist_remhead(&s->output))) - g_free(t); - g_free(s->tags); - g_free(s->tage); - g_free(s->last); - g_free(s->submatches); - free_trie(s->t); - g_free(s); + while ((t = (struct _token *)e_dlist_remhead (&s->input))) + g_free (t); + while ((t = (struct _token *)e_dlist_remhead (&s->output))) + g_free (t); + g_free (s->tags); + g_free (s->tage); + g_free (s->last); + g_free (s->submatches); + free_trie (s->t); + g_free (s); } static struct _token * append_token(EDList *list, const char *tok, int len) @@ -507,7 +447,7 @@ append_token(EDList *list, const char *tok, int len) return token; } -#define free_token(x) (g_free(x)) +#define free_token(x) (g_free (x)) static void output_token(struct _searcher *s, struct _token *token) @@ -517,10 +457,10 @@ output_token(struct _searcher *s, struct _token *token) if (token->tok[0] == TAG_ESCAPE) { if (token->offset >= s->offout) { - d(printf("moving tag token '%s' from input to output\n", token->tok[0]==TAG_ESCAPE?token->tok+1:token->tok)); + d (printf("moving tag token '%s' from input to output\n", token->tok[0]==TAG_ESCAPE?token->tok+1:token->tok)); e_dlist_addtail(&s->output, (EDListNode *)token); } else { - d(printf("discarding tag token '%s' from input\n", token->tok[0]==TAG_ESCAPE?token->tok+1:token->tok)); + d (printf("discarding tag token '%s' from input\n", token->tok[0]==TAG_ESCAPE?token->tok+1:token->tok)); free_token(token); } } else { @@ -529,12 +469,12 @@ output_token(struct _searcher *s, struct _token *token) if (left > 0) { pre = s->offout - token->offset; if (pre>0) - memmove(token->tok, token->tok+pre, left+1); - d(printf("adding partial remaining/failed '%s'\n", token->tok[0]==TAG_ESCAPE?token->tok+1:token->tok)); + memmove (token->tok, token->tok+pre, left+1); + d (printf("adding partial remaining/failed '%s'\n", token->tok[0]==TAG_ESCAPE?token->tok+1:token->tok)); s->offout = offend; e_dlist_addtail(&s->output, (EDListNode *)token); } else { - d(printf("discarding whole token '%s'\n", token->tok[0]==TAG_ESCAPE?token->tok+1:token->tok)); + d (printf("discarding whole token '%s'\n", token->tok[0]==TAG_ESCAPE?token->tok+1:token->tok)); free_token(token); } } @@ -563,30 +503,30 @@ output_match(struct _searcher *s, unsigned int start, unsigned int end) struct _token *starttoken, *endtoken; char b[8]; - d(printf("output match: %d-%d at %d\n", start, end, s->offout)); + d (printf("output match: %d-%d at %d\n", start, end, s->offout)); starttoken = find_token(s, start); endtoken = find_token(s, end); if (starttoken == NULL || endtoken == NULL) { - d(printf("Cannot find match history for match %d-%d\n", start, end)); + d (printf("Cannot find match history for match %d-%d\n", start, end)); return; } - d(printf("start in token '%s'\n", starttoken->tok[0]==TAG_ESCAPE?starttoken->tok+1:starttoken->tok)); - d(printf("end in token '%s'\n", endtoken->tok[0]==TAG_ESCAPE?endtoken->tok+1:endtoken->tok)); + d (printf("start in token '%s'\n", starttoken->tok[0]==TAG_ESCAPE?starttoken->tok+1:starttoken->tok)); + d (printf("end in token '%s'\n", endtoken->tok[0]==TAG_ESCAPE?endtoken->tok+1:endtoken->tok)); /* output pending stuff that didn't match afterall */ while ((struct _token *)s->input.head != starttoken) { - token = (struct _token *)e_dlist_remhead(&s->input); - d(printf("appending failed match '%s'\n", token->tok[0]==TAG_ESCAPE?token->tok+1:token->tok)); + token = (struct _token *)e_dlist_remhead (&s->input); + d (printf("appending failed match '%s'\n", token->tok[0]==TAG_ESCAPE?token->tok+1:token->tok)); output_token(s, token); } /* output any pre-match text */ if (s->offout < start) { token = append_token(&s->output, starttoken->tok + (s->offout-starttoken->offset), start-s->offout); - d(printf("adding pre-match text '%s'\n", token->tok[0]==TAG_ESCAPE?token->tok+1:token->tok)); + d (printf("adding pre-match text '%s'\n", token->tok[0]==TAG_ESCAPE?token->tok+1:token->tok)); s->offout = start; } @@ -598,11 +538,11 @@ output_match(struct _searcher *s, unsigned int start, unsigned int end) if (s->tags) append_token(&s->output, s->tags, -1); - /* output match node(s) */ + /* output match node (s) */ if (starttoken != endtoken) { while ((struct _token *)s->input.head != endtoken) { - token = (struct _token *)e_dlist_remhead(&s->input); - d(printf("appending (partial) match node (head) '%s'\n", token->tok[0]==TAG_ESCAPE?token->tok+1:token->tok)); + token = (struct _token *)e_dlist_remhead (&s->input); + d (printf("appending (partial) match node (head) '%s'\n", token->tok[0]==TAG_ESCAPE?token->tok+1:token->tok)); output_token(s, token); } } @@ -610,7 +550,7 @@ output_match(struct _searcher *s, unsigned int start, unsigned int end) /* any remaining partial content */ if (s->offout < end) { token = append_token(&s->output, endtoken->tok+(s->offout-endtoken->offset), end-s->offout); - d(printf("appending (partial) match node (tail) '%s'\n", token->tok[0]==TAG_ESCAPE?token->tok+1:token->tok)); + d (printf("appending (partial) match node (tail) '%s'\n", token->tok[0]==TAG_ESCAPE?token->tok+1:token->tok)); s->offout = end; } @@ -627,7 +567,7 @@ output_match(struct _searcher *s, unsigned int start, unsigned int end) /* output any sub-pending blocks */ static void -output_subpending(struct _searcher *s) +output_subpending (struct _searcher *s) { int i; @@ -638,7 +578,7 @@ output_subpending(struct _searcher *s) /* returns true if a merge took place */ static int -merge_subpending(struct _searcher *s, int offstart, int offend) +merge_subpending (struct _searcher *s, int offstart, int offend) { int i; @@ -663,11 +603,11 @@ merge_subpending(struct _searcher *s, int offstart, int offend) } static void -push_subpending(struct _searcher *s, int offstart, int offend) +push_subpending (struct _searcher *s, int offstart, int offend) { /* This is really an assertion, we just ignore the last pending match instead of crashing though */ if (s->submatchp >= s->words) { - d(printf("ERROR: submatch pending stack overflow\n")); + d (printf("ERROR: submatch pending stack overflow\n")); s->submatchp = s->words-1; } @@ -678,11 +618,11 @@ push_subpending(struct _searcher *s, int offstart, int offend) /* move any (partial) tokens from input to output if they are beyond the current output position */ static void -output_pending(struct _searcher *s) +output_pending (struct _searcher *s) { struct _token *token; - while ( (token = (struct _token *)e_dlist_remhead(&s->input)) ) + while ( (token = (struct _token *)e_dlist_remhead (&s->input)) ) output_token(s, token); } @@ -706,7 +646,7 @@ flush_extra(struct _searcher *s) return; while ((struct _token *)s->input.head != starttoken) { - token = (struct _token *)e_dlist_remhead(&s->input); + token = (struct _token *)e_dlist_remhead (&s->input); output_token(s, token); } } @@ -726,8 +666,8 @@ searcher_next_token(struct _searcher *s) /* get next token */ tok = (unsigned char *)s->next_token(s->next_data); if (tok == NULL) { - output_subpending(s); - output_pending(s); + output_subpending (s); + output_pending (s); break; } @@ -736,14 +676,14 @@ searcher_next_token(struct _searcher *s) token->offset = s->offset; tok = (unsigned char *)token->tok; - d(printf("new token %d '%s'\n", token->offset, token->tok[0]==TAG_ESCAPE?token->tok+1:token->tok)); + d (printf("new token %d '%s'\n", token->offset, token->tok[0]==TAG_ESCAPE?token->tok+1:token->tok)); /* tag test, reset state on unknown tags */ if (tok[0] == TAG_ESCAPE) { if (!ignore_tag ((char *)tok)) { /* force reset */ - output_subpending(s); - output_pending(s); + output_subpending (s); + output_pending (s); q = &t->root; } @@ -754,12 +694,12 @@ searcher_next_token(struct _searcher *s) pre_tok = stok = tok; while ((c = camel_utf8_getc (&tok))) { if ((s->flags & SEARCH_CASE) == 0) - c = g_unichar_tolower(c); - while (q && (m = g(q, c)) == NULL) + c = g_unichar_tolower (c); + while (q && (m = g (q, c)) == NULL) q = q->fail; if (q == NULL) { /* mismatch ... reset state */ - output_subpending(s); + output_subpending (s); q = &t->root; } else if (m != NULL) { /* keep track of previous offsets of utf8 chars, rotating buffer */ @@ -778,21 +718,21 @@ searcher_next_token(struct _searcher *s) if (q->matches == NULL) { if (s->submatchp == 0) { /* nothing pending, always put something in so we can try merge */ - push_subpending(s, offstart, offend); - } else if (!merge_subpending(s, offstart, offend)) { + push_subpending (s, offstart, offend); + } else if (!merge_subpending (s, offstart, offend)) { /* can't merge, output what we have, and start againt */ - output_subpending(s); - push_subpending(s, offstart, offend); + output_subpending (s); + push_subpending (s, offstart, offend); /*output_match(s, offstart, offend);*/ } else if (e_dlist_length(&s->input) > 8) { /* we're continuing to match and merge, but we have a lot of stuff waiting, so flush it out now since this is a safe point to do it */ - output_subpending(s); + output_subpending (s); } } else { /* merge/add subpending */ - if (!merge_subpending(s, offstart, offend)) - push_subpending(s, offstart, offend); + if (!merge_subpending (s, offstart, offend)) + push_subpending (s, offstart, offend); } } } @@ -809,7 +749,7 @@ searcher_next_token(struct _searcher *s) if (s->current) free_token(s->current); - s->current = token = (struct _token *)e_dlist_remhead(&s->output); + s->current = token = (struct _token *)e_dlist_remhead (&s->output); return token ? g_strdup (token->tok) : NULL; } @@ -823,7 +763,7 @@ searcher_peek_token(struct _searcher *s) tok = searcher_next_token(s); if (tok) { /* need to clear this so we dont free it while its still active */ - e_dlist_addhead(&s->output, (EDListNode *)s->current); + e_dlist_addhead (&s->output, (EDListNode *)s->current); s->current = NULL; } @@ -831,7 +771,7 @@ searcher_peek_token(struct _searcher *s) } static int -searcher_pending(struct _searcher *s) +searcher_pending (struct _searcher *s) { return !(e_dlist_empty(&s->input) && e_dlist_empty(&s->output)); } @@ -840,7 +780,7 @@ searcher_pending(struct _searcher *s) struct _search_info { GPtrArray *strv; - char *colour; + char *color; unsigned int size:8; unsigned int flags:8; }; @@ -848,12 +788,12 @@ struct _search_info { /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ static struct _search_info * -search_info_new(void) +search_info_new (void) { struct _search_info *s; s = g_malloc0(sizeof(struct _search_info)); - s->strv = g_ptr_array_new(); + s->strv = g_ptr_array_new (); return s; } @@ -865,14 +805,14 @@ search_info_set_flags(struct _search_info *si, unsigned int flags, unsigned int } static void -search_info_set_colour(struct _search_info *si, const char *colour) +search_info_set_color (struct _search_info *si, const char *color) { - g_free(si->colour); - si->colour = g_strdup(colour); + g_free (si->color); + si->color = g_strdup (color); } static void -search_info_add_string(struct _search_info *si, const char *s) +search_info_add_string (struct _search_info *si, const char *s) { const unsigned char *start; guint32 c; @@ -889,44 +829,44 @@ search_info_add_string(struct _search_info *si, const char *s) } /* should probably also strip trailing, but i'm lazy today */ if (start[0]) - g_ptr_array_add(si->strv, g_strdup ((char *)start)); + g_ptr_array_add (si->strv, g_strdup ((char *)start)); } } static void -search_info_clear(struct _search_info *si) +search_info_clear (struct _search_info *si) { int i; for (i=0;i<si->strv->len;i++) - g_free(si->strv->pdata[i]); + g_free (si->strv->pdata[i]); - g_ptr_array_set_size(si->strv, 0); + g_ptr_array_set_size (si->strv, 0); } static void -search_info_free(struct _search_info *si) +search_info_free (struct _search_info *si) { int i; for (i=0;i<si->strv->len;i++) - g_free(si->strv->pdata[i]); + g_free (si->strv->pdata[i]); - g_ptr_array_free(si->strv, TRUE); - g_free(si->colour); - g_free(si); + g_ptr_array_free (si->strv, TRUE); + g_free (si->color); + g_free (si); } static struct _search_info * -search_info_clone(struct _search_info *si) +search_info_clone (struct _search_info *si) { struct _search_info *out; int i; - out = search_info_new(); + out = search_info_new (); for (i=0;i<si->strv->len;i++) - g_ptr_array_add(out->strv, g_strdup(si->strv->pdata[i])); - out->colour = g_strdup(si->colour); + g_ptr_array_add (out->strv, g_strdup (si->strv->pdata[i])); + out->color = g_strdup (si->color); out->flags = si->flags; out->size = si->size; @@ -934,7 +874,7 @@ search_info_clone(struct _search_info *si) } static struct _searcher * -search_info_to_searcher(struct _search_info *si) +search_info_to_searcher (struct _search_info *si) { char *tags, *tage; char *col; @@ -942,10 +882,10 @@ search_info_to_searcher(struct _search_info *si) if (si->strv->len == 0) return NULL; - if (si->colour == NULL) + if (si->color == NULL) col = "red"; else - col = si->colour; + col = si->color; tags = alloca(20+strlen(col)); sprintf(tags, "%c<font color=\"%s\">", TAG_ESCAPE, col); @@ -964,287 +904,289 @@ struct _ESearchingTokenizerPrivate { /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ -static void -e_searching_tokenizer_finalise (GObject *obj) -{ - ESearchingTokenizer *st = E_SEARCHING_TOKENIZER (obj); - struct _ESearchingTokenizerPrivate *p = st->priv; - - search_info_free (p->primary); - search_info_free (p->secondary); - if (p->engine) - searcher_free(p->engine); +/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ - /* again wtf? - shared_state_unref (st->priv->shared); - */ +/* blah blah the htmltokeniser doesn't like being asked + for a token if it doens't hvae any! */ +static char * +get_token (HTMLTokenizer *tokenizer) +{ + HTMLTokenizerClass *class = HTML_TOKENIZER_CLASS (parent_class); - g_free (p); + if (class->has_more (tokenizer)) + return class->next_token (tokenizer); - if (G_OBJECT_CLASS (parent_class)->finalize) - G_OBJECT_CLASS (parent_class)->finalize(obj); + return NULL; } +/* proxy matched event, not sure what its for otherwise */ static void -e_searching_tokenizer_class_init (ESearchingTokenizerClass *klass) +matched (ESearchingTokenizer *tokenizer) { - GObjectClass *obj_class = (GObjectClass *) klass; - HTMLTokenizerClass *tok_class = HTML_TOKENIZER_CLASS (klass); - - parent_class = g_type_class_ref (HTML_TYPE_TOKENIZER); - - signals[MATCH_SIGNAL] = - g_signal_new ("match", - E_TYPE_SEARCHING_TOKENIZER, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ESearchingTokenizerClass, match), - NULL, - NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - obj_class->finalize = e_searching_tokenizer_finalise; - - tok_class->begin = e_searching_tokenizer_begin; - tok_class->end = e_searching_tokenizer_end; - - tok_class->peek_token = e_searching_tokenizer_peek_token; - tok_class->next_token = e_searching_tokenizer_next_token; - tok_class->has_more = e_searching_tokenizer_has_more; - tok_class->clone = e_searching_tokenizer_clone; + /*++tokenizer->priv->match_count;*/ + g_signal_emit (tokenizer, signals[MATCH_SIGNAL], 0); } +/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ + static void -e_searching_tokenizer_init (ESearchingTokenizer *st) +searching_tokenizer_finalize (GObject *object) { - struct _ESearchingTokenizerPrivate *p; - - p = st->priv = g_new0 (struct _ESearchingTokenizerPrivate, 1); + ESearchingTokenizerPrivate *priv; - p->primary = search_info_new(); - search_info_set_flags(p->primary, SEARCH_BOLD, SEARCH_CASE|SEARCH_BOLD); - search_info_set_colour(p->primary, "red"); + priv = E_SEARCHING_TOKENIZER_GET_PRIVATE (object); - p->secondary = search_info_new(); - search_info_set_flags(p->secondary, SEARCH_BOLD, SEARCH_CASE|SEARCH_BOLD); - search_info_set_colour(p->secondary, "purple"); -} + search_info_free (priv->primary); + search_info_free (priv->secondary); -GType -e_searching_tokenizer_get_type (void) -{ - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof (ESearchingTokenizerClass), - NULL, NULL, - (GClassInitFunc) e_searching_tokenizer_class_init, - NULL, NULL, - sizeof (ESearchingTokenizer), - 0, - (GInstanceInitFunc) e_searching_tokenizer_init, - }; - - type = g_type_register_static (HTML_TYPE_TOKENIZER, "ESearchingTokenizer", &info, 0); - } + if (priv->engine != NULL) + searcher_free (priv->engine); - return type; -} - -HTMLTokenizer * -e_searching_tokenizer_new (void) -{ - return (HTMLTokenizer *) g_object_new (E_TYPE_SEARCHING_TOKENIZER, NULL); -} - -/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ - -/* blah blah the htmltokeniser doesn't like being asked - for a token if it doens't hvae any! */ -static char *get_token(HTMLTokenizer *t) -{ - HTMLTokenizerClass *klass = HTML_TOKENIZER_CLASS (parent_class); - - return klass->has_more(t) ? klass->next_token(t) : NULL; + /* Chain up to parent's finalize () method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); } static void -e_searching_tokenizer_begin (HTMLTokenizer *t, const char *content_type) +searching_tokenizer_begin (HTMLTokenizer *tokenizer, + const gchar *content_type) { - ESearchingTokenizer *st = E_SEARCHING_TOKENIZER (t); - struct _ESearchingTokenizerPrivate *p = st->priv; + ESearchingTokenizerPrivate *priv; + + priv = E_SEARCHING_TOKENIZER_GET_PRIVATE (tokenizer); /* reset search */ - if (p->engine) { - searcher_free(p->engine); - p->engine = NULL; + if (priv->engine != NULL) { + searcher_free (priv->engine); + priv->engine = NULL; } - if ((p->engine = search_info_to_searcher(p->primary)) - || (p->engine = search_info_to_searcher(p->secondary))) { - /*HTMLTokenizerClass *klass = HTML_TOKENIZER_CLASS (parent_class);*/ - - /*searcher_set_tokenfunc(p->engine, klass->next_token, st);*/ - searcher_set_tokenfunc(p->engine, get_token, st); + if ((priv->engine = search_info_to_searcher (priv->primary)) + || (priv->engine = search_info_to_searcher (priv->secondary))) { + searcher_set_tokenfunc(priv->engine, get_token, tokenizer); } /* else - no engine, no search active */ - HTML_TOKENIZER_CLASS (parent_class)->begin (t, content_type); + /* Chain up to parent's begin() method. */ + HTML_TOKENIZER_CLASS (parent_class)->begin (tokenizer, content_type); } -static void -e_searching_tokenizer_end (HTMLTokenizer *t) +static gchar * +searching_tokenizer_peek_token (HTMLTokenizer *tokenizer) { - /* so end gets called before any get/next tokens. - I dont get it. */ -#if 0 - ESearchingTokenizer *st = E_SEARCHING_TOKENIZER (t); - struct _ESearchingTokenizerPrivate *p = st->priv; - - /* not sure if we should reset search every time ... *shrug* */ - if (p->engine) { - searcher_free(p->engine); - p->engine = NULL; - } -#endif + ESearchingTokenizerPrivate *priv; - HTML_TOKENIZER_CLASS (parent_class)->end (t); -} + priv = E_SEARCHING_TOKENIZER_GET_PRIVATE (tokenizer); -static char * -e_searching_tokenizer_peek_token (HTMLTokenizer *tok) -{ - ESearchingTokenizer *st = E_SEARCHING_TOKENIZER (tok); + if (priv->engine != NULL) + return searcher_peek_token (priv->engine); - /* If no search is active, just use the default method. */ - if (st->priv->engine == NULL) - return HTML_TOKENIZER_CLASS (parent_class)->peek_token (tok); - - return searcher_peek_token(st->priv->engine); + /* Chain up to parent's peek_token() method. */ + return HTML_TOKENIZER_CLASS (parent_class)->peek_token (tokenizer); } -static char * -e_searching_tokenizer_next_token (HTMLTokenizer *tok) +static gchar * +searching_tokenizer_next_token (HTMLTokenizer *tokenizer) { - ESearchingTokenizer *st = E_SEARCHING_TOKENIZER (tok); + ESearchingTokenizerPrivate *priv; int oldmatched; char *token; + priv = E_SEARCHING_TOKENIZER_GET_PRIVATE (tokenizer); + /* If no search is active, just use the default method. */ - if (st->priv->engine == NULL) - return HTML_TOKENIZER_CLASS (parent_class)->next_token (tok); + if (priv->engine == NULL) + return HTML_TOKENIZER_CLASS (parent_class)->next_token (tokenizer); - oldmatched = st->priv->engine->matchcount; + oldmatched = priv->engine->matchcount; - token = searcher_next_token(st->priv->engine); + token = searcher_next_token (priv->engine); /* not sure if this has to be accurate or just say we had some matches */ - if (oldmatched != st->priv->engine->matchcount) - g_signal_emit (st, signals[MATCH_SIGNAL], 0); + if (oldmatched != priv->engine->matchcount) + g_signal_emit (tokenizer, signals[MATCH_SIGNAL], 0); return token; } static gboolean -e_searching_tokenizer_has_more (HTMLTokenizer *tok) +searching_tokenizer_has_more (HTMLTokenizer *tokenizer) { - ESearchingTokenizer *st = E_SEARCHING_TOKENIZER (tok); + ESearchingTokenizerPrivate *priv; + + priv = E_SEARCHING_TOKENIZER_GET_PRIVATE (tokenizer); - return (st->priv->engine != NULL && searcher_pending(st->priv->engine)) - || HTML_TOKENIZER_CLASS (parent_class)->has_more (tok); + return (priv->engine != NULL && searcher_pending (priv->engine)) || + HTML_TOKENIZER_CLASS (parent_class)->has_more (tokenizer); } -/* proxy matched event, not sure what its for otherwise */ +static HTMLTokenizer * +searching_tokenizer_clone (HTMLTokenizer *tokenizer) +{ + ESearchingTokenizer *orig_st; + ESearchingTokenizer *new_st; + + orig_st = E_SEARCHING_TOKENIZER (tokenizer); + new_st = e_searching_tokenizer_new (); + + search_info_free (new_st->priv->primary); + search_info_free (new_st->priv->secondary); + + new_st->priv->primary = search_info_clone (orig_st->priv->primary); + new_st->priv->secondary = search_info_clone (orig_st->priv->secondary); + + g_signal_connect_swapped ( + new_st, "match", G_CALLBACK (matched), orig_st); + + return HTML_TOKENIZER (new_st); +} static void -matched (ESearchingTokenizer *st) +searching_tokenizer_class_init (ESearchingTokenizerClass *class) { - /*++st->priv->match_count;*/ - g_signal_emit (st, signals[MATCH_SIGNAL], 0); + GObjectClass *object_class; + HTMLTokenizerClass *tokenizer_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ESearchingTokenizerPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->finalize = searching_tokenizer_finalize; + + tokenizer_class = HTML_TOKENIZER_CLASS (class); + tokenizer_class->begin = searching_tokenizer_begin; + tokenizer_class->peek_token = searching_tokenizer_peek_token; + tokenizer_class->next_token = searching_tokenizer_next_token; + tokenizer_class->has_more = searching_tokenizer_has_more; + tokenizer_class->clone = searching_tokenizer_clone; + + signals[MATCH_SIGNAL] = g_signal_new ( + "match", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ESearchingTokenizerClass, match), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } -static HTMLTokenizer * -e_searching_tokenizer_clone (HTMLTokenizer *tok) +static void +searching_tokenizer_init (ESearchingTokenizer *tokenizer) { - ESearchingTokenizer *orig_st = E_SEARCHING_TOKENIZER (tok); - ESearchingTokenizer *new_st = E_SEARCHING_TOKENIZER (e_searching_tokenizer_new ()); + tokenizer->priv = E_SEARCHING_TOKENIZER_GET_PRIVATE (tokenizer); + + tokenizer->priv->primary = search_info_new (); + search_info_set_flags ( + tokenizer->priv->primary, + SEARCH_BOLD, SEARCH_CASE | SEARCH_BOLD); + search_info_set_color (tokenizer->priv->primary, "red"); + + tokenizer->priv->secondary = search_info_new (); + search_info_set_flags( + tokenizer->priv->secondary, + SEARCH_BOLD, SEARCH_CASE | SEARCH_BOLD); + search_info_set_color (tokenizer->priv->secondary, "purple"); +} - search_info_free(new_st->priv->primary); - search_info_free(new_st->priv->secondary); +GType +e_searching_tokenizer_get_type (void) +{ + static GType type = 0; - new_st->priv->primary = search_info_clone(orig_st->priv->primary); - new_st->priv->secondary = search_info_clone(orig_st->priv->secondary); + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (ESearchingTokenizerClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) searching_tokenizer_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (ESearchingTokenizer), + 0, /* n_preallocs */ + (GInstanceInitFunc) searching_tokenizer_init, + NULL /* value_table */ + }; -#if 0 - shared_state_ref (orig_st->priv->shared); - shared_state_unref (new_st->priv->shared); - new_st->priv->shared = orig_st->priv->shared; -#endif + type = g_type_register_static ( + HTML_TYPE_TOKENIZER, "ESearchingTokenizer", + &type_info, 0); + } - g_signal_connect_swapped (new_st, "match", G_CALLBACK(matched), orig_st); + return type; +} - return HTML_TOKENIZER (new_st); +ESearchingTokenizer * +e_searching_tokenizer_new (void) +{ + return g_object_new (E_TYPE_SEARCHING_TOKENIZER, NULL); } -/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ void -e_searching_tokenizer_set_primary_search_string (ESearchingTokenizer *st, const gchar *search_str) +e_searching_tokenizer_set_primary_search_string (ESearchingTokenizer *tokenizer, + const gchar *primary_string) { - g_return_if_fail (st && E_IS_SEARCHING_TOKENIZER (st)); + g_return_if_fail (E_IS_SEARCHING_TOKENIZER (tokenizer)); - search_info_clear(st->priv->primary); - search_info_add_string(st->priv->primary, search_str); + search_info_clear (tokenizer->priv->primary); + search_info_add_string (tokenizer->priv->primary, primary_string); } void -e_searching_tokenizer_add_primary_search_string (ESearchingTokenizer *st, const gchar *search_str) +e_searching_tokenizer_add_primary_search_string (ESearchingTokenizer *tokenizer, + const gchar *primary_string) { - g_return_if_fail (st && E_IS_SEARCHING_TOKENIZER (st)); + g_return_if_fail (E_IS_SEARCHING_TOKENIZER (tokenizer)); - search_info_add_string(st->priv->primary, search_str); + search_info_add_string (tokenizer->priv->primary, primary_string); } void -e_searching_tokenizer_set_primary_case_sensitivity (ESearchingTokenizer *st, gboolean iscase) +e_searching_tokenizer_set_primary_case_sensitivity (ESearchingTokenizer *tokenizer, + gboolean case_sensitive) { - g_return_if_fail (st && E_IS_SEARCHING_TOKENIZER (st)); + g_return_if_fail (E_IS_SEARCHING_TOKENIZER (tokenizer)); - search_info_set_flags(st->priv->primary, iscase?SEARCH_CASE:0, SEARCH_CASE); + search_info_set_flags ( + tokenizer->priv->primary, + case_sensitive ? SEARCH_CASE : 0, SEARCH_CASE); } void -e_searching_tokenizer_set_secondary_search_string (ESearchingTokenizer *st, const gchar *search_str) +e_searching_tokenizer_set_secondary_search_string (ESearchingTokenizer *tokenizer, + const gchar *secondary_string) { - g_return_if_fail (st && E_IS_SEARCHING_TOKENIZER (st)); + g_return_if_fail (E_IS_SEARCHING_TOKENIZER (tokenizer)); - search_info_clear(st->priv->secondary); - search_info_add_string(st->priv->secondary, search_str); + search_info_clear (tokenizer->priv->secondary); + search_info_add_string (tokenizer->priv->secondary, secondary_string); } void -e_searching_tokenizer_add_secondary_search_string (ESearchingTokenizer *st, const gchar *search_str) +e_searching_tokenizer_add_secondary_search_string (ESearchingTokenizer *tokenizer, + const gchar *secondary_string) { - g_return_if_fail (st && E_IS_SEARCHING_TOKENIZER (st)); + g_return_if_fail (E_IS_SEARCHING_TOKENIZER (tokenizer)); - search_info_add_string(st->priv->secondary, search_str); + search_info_add_string (tokenizer->priv->secondary, secondary_string); } void -e_searching_tokenizer_set_secondary_case_sensitivity (ESearchingTokenizer *st, gboolean iscase) +e_searching_tokenizer_set_secondary_case_sensitivity (ESearchingTokenizer *tokenizer, + gboolean case_sensitive) { - g_return_if_fail (st && E_IS_SEARCHING_TOKENIZER (st)); + g_return_if_fail (E_IS_SEARCHING_TOKENIZER (tokenizer)); - search_info_set_flags(st->priv->secondary, iscase?SEARCH_CASE:0, SEARCH_CASE); + search_info_set_flags ( + tokenizer->priv->secondary, + case_sensitive ? SEARCH_CASE : 0, SEARCH_CASE); } /* Note: only returns the primary search string count */ gint -e_searching_tokenizer_match_count (ESearchingTokenizer *st) +e_searching_tokenizer_match_count (ESearchingTokenizer *tokenizer) { - g_return_val_if_fail (E_IS_SEARCHING_TOKENIZER (st), -1); + g_return_val_if_fail (E_IS_SEARCHING_TOKENIZER (tokenizer), -1); - if (st->priv->engine && st->priv->primary->strv->len) - return st->priv->engine->matchcount; + if (tokenizer->priv->engine && tokenizer->priv->primary->strv->len) + return tokenizer->priv->engine->matchcount; return 0; } diff --git a/mail/e-searching-tokenizer.h b/mail/e-searching-tokenizer.h index ecc914dab7..7bab007a9f 100644 --- a/mail/e-searching-tokenizer.h +++ b/mail/e-searching-tokenizer.h @@ -21,50 +21,72 @@ * */ -#ifndef __E_SEARCHING_TOKENIZER_H__ -#define __E_SEARCHING_TOKENIZER_H__ +#ifndef E_SEARCHING_TOKENIZER_H +#define E_SEARCHING_TOKENIZER_H #include <glib.h> #include <gtkhtml/htmltokenizer.h> -#define E_TYPE_SEARCHING_TOKENIZER (e_searching_tokenizer_get_type ()) -#define E_SEARCHING_TOKENIZER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_SEARCHING_TOKENIZER, ESearchingTokenizer)) -#define E_SEARCHING_TOKENIZER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), E_TYPE_SEARCHING_TOKENIZER, ESearchingTokenizerClass)) -#define E_IS_SEARCHING_TOKENIZER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_SEARCHING_TOKENIZER)) -#define E_IS_SEARCHING_TOKENIZER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), E_TYPE_SEARCHING_TOKENIZER)) +/* Standard GObject macros */ +#define E_TYPE_SEARCHING_TOKENIZER \ + (e_searching_tokenizer_get_type ()) +#define E_SEARCHING_TOKENIZER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_SEARCHING_TOKENIZER, ESearchingTokenizer)) +#define E_SEARCHING_TOKENIZER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_SEARCHING_TOKENIZER, ESearchingTokenizerClass)) +#define E_IS_SEARCHING_TOKENIZER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_SEARCHING_TOKENIZER)) +#define E_IS_SEARCHING_TOKENIZER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_SEARCHING_TOKENIZER)) +#define E_SEARCH_TOKENIZER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_SEARCHING_TOKENIZER, ESearchingTokenizerClass)) + +G_BEGIN_DECLS typedef struct _ESearchingTokenizer ESearchingTokenizer; typedef struct _ESearchingTokenizerClass ESearchingTokenizerClass; - -struct _ESearchingTokenizerPrivate; +typedef struct _ESearchingTokenizerPrivate ESearchingTokenizerPrivate; struct _ESearchingTokenizer { HTMLTokenizer parent; - - struct _ESearchingTokenizerPrivate *priv; + ESearchingTokenizerPrivate *priv; }; struct _ESearchingTokenizerClass { HTMLTokenizerClass parent_class; - void (*match) (ESearchingTokenizer *); + void (*match) (ESearchingTokenizer *tokenizer); }; -GType e_searching_tokenizer_get_type (void); - -HTMLTokenizer *e_searching_tokenizer_new (void); - -/* For now, just a simple API */ - -void e_searching_tokenizer_set_primary_search_string (ESearchingTokenizer *, const char *); -void e_searching_tokenizer_add_primary_search_string (ESearchingTokenizer *, const char *); -void e_searching_tokenizer_set_primary_case_sensitivity (ESearchingTokenizer *, gboolean is_case_sensitive); - -void e_searching_tokenizer_set_secondary_search_string (ESearchingTokenizer *, const char *); -void e_searching_tokenizer_add_secondary_search_string (ESearchingTokenizer *st, const char *search_str); -void e_searching_tokenizer_set_secondary_case_sensitivity (ESearchingTokenizer *, gboolean is_case_sensitive); - - -int e_searching_tokenizer_match_count (ESearchingTokenizer *); - -#endif /* __E_SEARCHING_TOKENIZER_H__ */ +GType e_searching_tokenizer_get_type (void); +ESearchingTokenizer * + e_searching_tokenizer_new (void); +void e_searching_tokenizer_set_primary_search_string + (ESearchingTokenizer *tokenizer, + const gchar *primary_string); +void e_searching_tokenizer_add_primary_search_string + (ESearchingTokenizer *tokenizer, + const gchar *primary_string); +void e_searching_tokenizer_set_primary_case_sensitivity + (ESearchingTokenizer *tokenizer, + gboolean case_sensitive); +void e_searching_tokenizer_set_secondary_search_string + (ESearchingTokenizer *tokenizer, + const gchar *secondary_string); +void e_searching_tokenizer_add_secondary_search_string + (ESearchingTokenizer *tokenizer, + const gchar *secondary_string); +void e_searching_tokenizer_set_secondary_case_sensitivity + (ESearchingTokenizer *tokenizer, + gboolean case_sensitive); +gint e_searching_tokenizer_match_count + (ESearchingTokenizer *tokenizer); + +G_END_DECLS + +#endif /* E_SEARCHING_TOKENIZER_H */ diff --git a/mail/em-account-editor.c b/mail/em-account-editor.c index b9850bd052..a5c5d59fd8 100644 --- a/mail/em-account-editor.c +++ b/mail/em-account-editor.c @@ -51,10 +51,11 @@ #include <libgnomeui/gnome-druid.h> #include <libgnomeui/gnome-druid-page-standard.h> -#include <libedataserver/e-account-list.h> #include <e-util/e-signature-list.h> #include "e-util/e-error.h" +#include "e-util/e-account-utils.h" +#include "e-util/e-signature-utils.h" #include "e-util/e-util-private.h" #include "em-config.h" @@ -62,14 +63,15 @@ #include "em-account-editor.h" #include "mail-session.h" #include "mail-send-recv.h" -#include "mail-signature-editor.h" -#include "mail-component.h" +#include "e-signature-editor.h" #include "em-utils.h" #include "em-composer-prefs.h" #include "mail-config.h" #include "mail-ops.h" #include "mail-mt.h" +#include "e-mail-shell-module.h" + #if defined (HAVE_NSS) #include "smime/gui/e-cert-selector.h" #endif @@ -209,7 +211,7 @@ emae_finalise(GObject *o) EMAccountEditorPrivate *p = emae->priv; if (p->sig_added_id) { - ESignatureList *signatures = mail_config_get_signatures(); + ESignatureList *signatures = e_get_signature_list (); g_signal_handler_disconnect(signatures, p->sig_added_id); g_signal_handler_disconnect(signatures, p->sig_removed_id); @@ -447,11 +449,13 @@ default_folders_clicked (GtkButton *button, gpointer user_data) EMAccountEditor *emae = user_data; const char *uri; - uri = mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_DRAFTS); + uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, E_MAIL_FOLDER_DRAFTS); em_folder_selection_button_set_selection((EMFolderSelectionButton *)emae->priv->drafts_folder_button, uri); emae_account_folder_changed((EMFolderSelectionButton *)emae->priv->drafts_folder_button, emae); - uri = mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_SENT); + uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, E_MAIL_FOLDER_SENT); em_folder_selection_button_set_selection((EMFolderSelectionButton *)emae->priv->sent_folder_button, uri); emae_account_folder_changed((EMFolderSelectionButton *)emae->priv->sent_folder_button, emae); } @@ -462,7 +466,10 @@ GtkWidget *em_account_editor_folder_selector_button_new (char *widget_name, char GtkWidget * em_account_editor_folder_selector_button_new (char *widget_name, char *string1, char *string2, int int1, int int2) { - return (GtkWidget *)em_folder_selection_button_new(string1 ? string1 : _("Select Folder"), NULL); + EMFolderTreeModel *model; + + model = e_mail_shell_module_get_folder_tree_model (mail_shell_module); + return (GtkWidget *)em_folder_selection_button_new(model, string1 ? string1 : _("Select Folder"), NULL); } GtkWidget *em_account_editor_dropdown_new(char *widget_name, char *string1, char *string2, int int1, int int2); @@ -655,10 +662,19 @@ emae_signaturetype_changed(GtkComboBox *dropdown, EMAccountEditor *emae) static void emae_signature_new(GtkWidget *w, EMAccountEditor *emae) { - /* TODO: why is this in composer prefs? apart from it being somewhere to put it? */ - em_composer_prefs_new_signature((GtkWindow *)gtk_widget_get_toplevel(w), - gconf_client_get_bool(mail_config_get_gconf_client(), - "/apps/evolution/mail/composer/send_html", NULL)); + EShell *shell; + EShellSettings *shell_settings; + GtkWidget *parent; + gboolean html_mode; + + shell = e_shell_get_default (); + shell_settings = e_shell_get_shell_settings (shell); + parent = gtk_widget_get_toplevel (w); + + html_mode = e_shell_settings_get_boolean ( + shell_settings, "composer-format-html"); + + em_composer_prefs_new_signature (GTK_WINDOW (parent), html_mode); } static GtkWidget * @@ -683,7 +699,7 @@ emae_setup_signatures(EMAccountEditor *emae, GladeXML *xml) gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, _("None"), 1, NULL, -1); - signatures = mail_config_get_signatures (); + signatures = e_get_signature_list (); if (p->sig_added_id == 0) { p->sig_added_id = g_signal_connect(signatures, "signature-added", G_CALLBACK(emae_signature_added), emae); @@ -889,7 +905,11 @@ emae_account_folder(EMAccountEditor *emae, const char *name, int item, int deffo em_folder_selection_button_set_selection(folder, tmp); g_free(tmp); } else { - em_folder_selection_button_set_selection(folder, mail_component_get_folder_uri(NULL, deffolder)); + const gchar *uri; + + uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, deffolder); + em_folder_selection_button_set_selection(folder, uri); } g_object_set_data((GObject *)folder, "account-item", GINT_TO_POINTER(item)); @@ -1772,8 +1792,8 @@ emae_identity_page(EConfig *ec, EConfigItem *item, struct _GtkWidget *parent, st gui->management_frame = glade_xml_get_widget(xml, "management_frame"); gui->default_account = GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "management_default")); - if (!mail_config_get_default_account () - || (account == mail_config_get_default_account ()) + if (!e_get_default_account () + || (account == e_get_default_account ()) || (GPOINTER_TO_INT(g_object_get_data (G_OBJECT (emae->account), "default_flagged"))) ) gtk_toggle_button_set_active (gui->default_account, TRUE); @@ -2352,8 +2372,8 @@ emae_defaults_page(EConfig *ec, EConfigItem *item, struct _GtkWidget *parent, st g_free (gladefile); /* Special folders */ - gui->drafts_folder_button = (GtkButton *)emae_account_folder(emae, "drafts_button", E_ACCOUNT_DRAFTS_FOLDER_URI, MAIL_COMPONENT_FOLDER_DRAFTS, xml); - gui->sent_folder_button = (GtkButton *)emae_account_folder(emae, "sent_button", E_ACCOUNT_SENT_FOLDER_URI, MAIL_COMPONENT_FOLDER_SENT, xml); + gui->drafts_folder_button = (GtkButton *)emae_account_folder(emae, "drafts_button", E_ACCOUNT_DRAFTS_FOLDER_URI, E_MAIL_FOLDER_DRAFTS, xml); + gui->sent_folder_button = (GtkButton *)emae_account_folder(emae, "sent_button", E_ACCOUNT_SENT_FOLDER_URI, E_MAIL_FOLDER_SENT, xml); /* Special Folders "Reset Defaults" button */ gui->restore_folders_button = (GtkButton *)glade_xml_get_widget (xml, "default_folders_button"); @@ -2710,7 +2730,7 @@ emae_check_complete(EConfig *ec, const char *pageid, void *data) len = strlen(tmp); template = alloca(len + 14); strcpy(template, tmp); - while (mail_config_get_account_by_name(template)) + while (e_get_account_by_name (template)) sprintf(template + len, " (%d)", i++); gtk_entry_set_text(emae->priv->identity_entries[0], template); @@ -2754,7 +2774,7 @@ emae_check_complete(EConfig *ec, const char *pageid, void *data) if (ok && (pageid == NULL || !strcmp(pageid, "40.management"))) { ok = (tmp = e_account_get_string(emae->account, E_ACCOUNT_NAME)) && tmp[0] - && ((ea = mail_config_get_account_by_name(tmp)) == NULL + && ((ea = e_get_account_by_name (tmp)) == NULL || ea == emae->original); if (!ok) d(printf("management page incomplete\n")); @@ -2767,6 +2787,7 @@ emae_check_complete(EConfig *ec, const char *pageid, void *data) static void add_new_store (char *uri, CamelStore *store, void *user_data) { +#if 0 /* KILL-BONOBO: Try to actually fix this? */ MailComponent *component = mail_component_peek (); EAccount *account = user_data; @@ -2774,13 +2795,14 @@ add_new_store (char *uri, CamelStore *store, void *user_data) return; mail_component_add_store (component, store, account->name); +#endif } static void emae_commit(EConfig *ec, GSList *items, void *data) { EMAccountEditor *emae = data; - EAccountList *accounts = mail_config_get_accounts(); + EAccountList *accounts = e_get_account_list (); EAccount *account; /* the mail-config*acconts* api needs a lot of work */ @@ -2840,13 +2862,21 @@ em_account_editor_construct(EMAccountEditor *emae, EAccount *account, em_account emae->do_signature = TRUE; } else { + const gchar *uri; + /* TODO: have a get_default_account thing?? */ emae->account = e_account_new(); emae->account->enabled = TRUE; - e_account_set_string(emae->account, E_ACCOUNT_DRAFTS_FOLDER_URI, - mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_DRAFTS)); - e_account_set_string(emae->account, E_ACCOUNT_SENT_FOLDER_URI, - mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_SENT)); + + uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, E_MAIL_FOLDER_DRAFTS); + e_account_set_string ( + emae->account, E_ACCOUNT_DRAFTS_FOLDER_URI, uri); + + uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, E_MAIL_FOLDER_SENT); + e_account_set_string ( + emae->account, E_ACCOUNT_SENT_FOLDER_URI, uri); } /* sort the providers, remote first */ diff --git a/mail/em-account-prefs.c b/mail/em-account-prefs.c index 56bb4ce1df..2b6e3343f6 100644 --- a/mail/em-account-prefs.c +++ b/mail/em-account-prefs.c @@ -28,18 +28,17 @@ #include <glib/gi18n.h> -#include "mail-component.h" #include "mail-config.h" #include "mail-ops.h" #include "mail-send-recv.h" -#include "libedataserver/e-account-list.h" +#include "e-util/e-account-utils.h" #include "e-util/e-error.h" #include "e-util/e-util-private.h" #include "em-account-prefs.h" - #include "em-account-editor.h" +#include "e-mail-shell-module.h" static void em_account_prefs_class_init (EMAccountPrefsClass *class); static void em_account_prefs_init (EMAccountPrefs *prefs); @@ -175,6 +174,9 @@ static void account_edit_clicked (GtkButton *button, gpointer user_data) { EMAccountPrefs *prefs = (EMAccountPrefs *) user_data; + EAccountList *account_list; + + account_list = e_get_account_list (); if (prefs->editor == NULL) { GtkTreeSelection *selection; @@ -186,7 +188,7 @@ account_edit_clicked (GtkButton *button, gpointer user_data) if (gtk_tree_selection_get_selected (selection, &model, &iter)) gtk_tree_model_get (model, &iter, 3, &account, -1); - if (account && !account->parent_uid && !mail_config_has_proxies (account)) { + if (account && !account->parent_uid && !e_account_list_account_has_proxies (account_list, account)) { EMAccountEditor *emae; /** @HookPoint-EMConfig: Mail Account Editor @@ -223,6 +225,8 @@ account_delete_clicked (GtkButton *button, gpointer user_data) int ans; gboolean has_proxies = FALSE; + accounts = e_get_account_list (); + selection = gtk_tree_view_get_selection (prefs->table); if (gtk_tree_selection_get_selected (selection, &model, &iter)) gtk_tree_model_get (model, &iter, 3, &account, -1); @@ -231,7 +235,7 @@ account_delete_clicked (GtkButton *button, gpointer user_data) if (account == NULL || prefs->editor != NULL) return; - has_proxies = mail_config_has_proxies (account); + has_proxies = e_account_list_account_has_proxies (accounts, account); ans = e_error_run(PREFS_WINDOW(prefs), has_proxies?"mail:ask-delete-account-with-proxies":"mail:ask-delete-account",NULL); if (ans == GTK_RESPONSE_YES) { @@ -239,15 +243,15 @@ account_delete_clicked (GtkButton *button, gpointer user_data) /* remove it from the folder-tree in the shell */ if (account->enabled && account->source && account->source->url) - mail_component_remove_store_by_uri (mail_component_peek (), account->source->url); + e_mail_shell_module_remove_store_by_uri ( + mail_shell_module, account->source->url); /* remove all the proxies account has created*/ if (has_proxies) - mail_config_remove_account_proxies (account); + e_account_list_remove_account_proxies (accounts, account); /* remove it from the config file */ - mail_config_remove_account (account); - accounts = mail_config_get_accounts (); + e_account_list_remove (accounts, account); mail_config_write (); @@ -281,7 +285,7 @@ account_default_clicked (GtkButton *button, gpointer user_data) gtk_tree_model_get (model, &iter, 3, &account, -1); if (account) { - mail_config_set_default_account (account); + e_set_default_account (account); mail_config_write (); @@ -292,17 +296,16 @@ account_default_clicked (GtkButton *button, gpointer user_data) static void account_able_changed(EAccount *account) { - MailComponent *component = mail_component_peek (); - /* FIXME: do this directly by listening to the mail accounts changed events in the relevant components */ if (account->source->url) { if (account->enabled) - mail_component_load_store_by_uri (component, - account->source->url, - account->name); + e_mail_shell_module_load_store_by_uri ( + mail_shell_module, + account->source->url, account->name); else - mail_component_remove_store_by_uri (component, account->source->url); + e_mail_shell_module_remove_store_by_uri ( + mail_shell_module, account->source->url); } mail_config_write (); @@ -313,11 +316,14 @@ account_able_toggled (GtkCellRendererToggle *renderer, char *arg1, gpointer user { EMAccountPrefs *prefs = user_data; GtkTreeSelection *selection; + EAccountList *account_list; EAccount *account = NULL; GtkTreeModel *model; GtkTreePath *path; GtkTreeIter iter; + account_list = e_get_account_list (); + path = gtk_tree_path_new_from_string (arg1); model = gtk_tree_view_get_model (prefs->table); selection = gtk_tree_view_get_selection (prefs->table); @@ -325,7 +331,7 @@ account_able_toggled (GtkCellRendererToggle *renderer, char *arg1, gpointer user if (gtk_tree_model_get_iter (model, &iter, path)) { gtk_tree_model_get (model, &iter, 3, &account, -1); - if (mail_config_has_proxies (account)) { + if (e_account_list_account_has_proxies (account_list, account)) { int ans; ans = e_error_run(PREFS_WINDOW(prefs), "mail:ask-delete-proxy-accounts",NULL); @@ -335,12 +341,12 @@ account_able_toggled (GtkCellRendererToggle *renderer, char *arg1, gpointer user return; } - mail_config_remove_account_proxies (account); + e_account_list_remove_account_proxies (account_list, account); gtk_widget_set_sensitive (GTK_WIDGET (prefs->mail_edit), 1); } account->enabled = !account->enabled; - e_account_list_change(mail_config_get_accounts(), account); + e_account_list_change(e_get_account_list (), account); account_able_changed (account); gtk_list_store_set ((GtkListStore *) model, &iter, 0, account->enabled, -1); @@ -360,13 +366,16 @@ account_double_click (GtkTreeView *treeview, GtkTreePath *path, static void account_cursor_change (GtkTreeSelection *selection, EMAccountPrefs *prefs) { + EAccountList *account_list; EAccount *account = NULL; GtkTreeModel *model; GtkTreeIter iter; const char *url = NULL; int state; EAccount *default_account; - default_account = mail_config_get_default_account (); + + account_list = e_get_account_list (); + default_account = e_get_default_account (); state = gconf_client_key_is_writable(mail_config_get_gconf_client(), "/apps/evolution/mail/accounts", NULL); if (state) { @@ -382,8 +391,12 @@ account_cursor_change (GtkTreeSelection *selection, EMAccountPrefs *prefs) gtk_widget_set_sensitive (GTK_WIDGET (prefs), FALSE); } - if( url != NULL ) - gtk_widget_set_sensitive (GTK_WIDGET (prefs->mail_edit), !mail_config_has_proxies(account)); + if (url != NULL) { + gboolean has_proxies; + + has_proxies = e_account_list_account_has_proxies (account_list, account); + gtk_widget_set_sensitive (GTK_WIDGET (prefs->mail_edit), !has_proxies); + } gtk_widget_set_sensitive (GTK_WIDGET (prefs->mail_delete), state); @@ -408,9 +421,9 @@ mail_accounts_load (EMAccountPrefs *prefs) model = (GtkListStore *) gtk_tree_view_get_model (prefs->table); gtk_list_store_clear (model); - default_account = mail_config_get_default_account (); + default_account = e_get_default_account (); - accounts = mail_config_get_accounts (); + accounts = e_get_account_list (); node = e_list_get_iterator ((EList *) accounts); selection = gtk_tree_view_get_selection(prefs->table); @@ -565,13 +578,12 @@ em_account_prefs_construct (EMAccountPrefs *prefs) } GtkWidget * -em_account_prefs_new (GNOME_Evolution_Shell shell) +em_account_prefs_new (void) { EMAccountPrefs *new; new = (EMAccountPrefs *) g_object_new (em_account_prefs_get_type (), NULL); em_account_prefs_construct (new); - new->shell = shell; return (GtkWidget *) new; } diff --git a/mail/em-account-prefs.h b/mail/em-account-prefs.h index c63b9f562e..c3932aefc9 100644 --- a/mail/em-account-prefs.h +++ b/mail/em-account-prefs.h @@ -21,29 +21,33 @@ * */ -#ifndef __EM_ACCOUNT_PREFS_H__ -#define __EM_ACCOUNT_PREFS_H__ +#ifndef EM_ACCOUNT_PREFS_H +#define EM_ACCOUNT_PREFS_H #include <gtk/gtk.h> #include <glade/glade.h> - #include <table/e-table.h> -#include "evolution-config-control.h" - -#include <shell/Evolution.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - - -#define EM_ACCOUNT_PREFS_TYPE (em_account_prefs_get_type ()) -#define EM_ACCOUNT_PREFS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EM_ACCOUNT_PREFS_TYPE, EMAccountPrefs)) -#define EM_ACCOUNT_PREFS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), EM_ACCOUNT_PREFS_TYPE, EMAccountPrefsClass)) -#define EM_IS_ACCOUNT_PREFS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EM_ACCOUNT_PREFS_TYPE)) -#define EM_IS_ACCOUNT_PREFS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EM_ACCOUNT_PREFS_TYPE)) +/* Standard GObject macros */ +#define EM_TYPE_ACCOUNT_PREFS \ + (em_account_prefs_get_type ()) +#define EM_ACCOUNT_PREFS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), EM_TYPE_ACCOUNT_PREFS, EMAccountPrefs)) +#define EM_ACCOUNT_PREFS_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), EM_TYPE_ACCOUNT_PREFS, EMAccountPrefsClass)) +#define EM_IS_ACCOUNT_PREFS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), EM_TYPE_ACCOUNT_PREFS)) +#define EM_IS_ACCOUNT_PREFS_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), EM_TYPE_ACCOUNT_PREFS)) +#define EM_ACCOUNT_PREFS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), EM_TYPE_ACCOUNT_PREFS, EMAccountPrefsClass)) + +G_BEGIN_DECLS typedef struct _EMAccountPrefs EMAccountPrefs; typedef struct _EMAccountPrefsClass EMAccountPrefsClass; @@ -51,8 +55,6 @@ typedef struct _EMAccountPrefsClass EMAccountPrefsClass; struct _EMAccountPrefs { GtkVBox parent_object; - GNOME_Evolution_Shell shell; - GladeXML *gui; GtkWidget *druid; @@ -71,21 +73,11 @@ struct _EMAccountPrefs { struct _EMAccountPrefsClass { GtkVBoxClass parent_class; - - /* signals */ - }; +GType em_account_prefs_get_type (void); +GtkWidget * em_account_prefs_new (void); -GType em_account_prefs_get_type (void); - -GtkWidget *em_account_prefs_new (GNOME_Evolution_Shell shell); - -/* needed by global config */ -#define EM_ACCOUNT_PREFS_CONTROL_ID "OAFIID:GNOME_Evolution_Mail_AccountPrefs_ConfigControl:" BASE_VERSION - -#ifdef __cplusplus -} -#endif +G_END_DECLS -#endif /* __EM_ACCOUNT_PREFS_H__ */ +#endif /* EM_ACCOUNT_PREFS_H */ diff --git a/mail/em-composer-prefs.c b/mail/em-composer-prefs.c index d9f3718cb0..dbc174340e 100644 --- a/mail/em-composer-prefs.c +++ b/mail/em-composer-prefs.c @@ -30,63 +30,137 @@ #include <unistd.h> #include <fcntl.h> -#include "e-util/e-signature.h" -#include "e-util/e-signature-list.h" +#include "e-util/e-binding.h" +#include "e-util/e-signature-utils.h" #include "e-util/gconf-bridge.h" #include "em-composer-prefs.h" #include "composer/e-msg-composer.h" -#include <bonobo/bonobo-generic-factory.h> - #include <camel/camel-iconv.h> #include <misc/e-gui-utils.h> +#include <glib/gi18n.h> #include <glib/gstdio.h> -#include <gdk/gdkkeysyms.h> #include <gtkhtml/gtkhtml.h> #include <editor/gtkhtml-spell-language.h> #include "misc/e-charset-picker.h" +#include "misc/e-signature-manager.h" +#include "misc/e-signature-preview.h" #include "e-util/e-error.h" #include "e-util/e-util-private.h" #include "mail-config.h" -#include "mail-signature-editor.h" +#include "e-signature-editor.h" #include "em-config.h" static gpointer parent_class; -static void -composer_prefs_dispose (GObject *object) +static gboolean +transform_color_to_string (const GValue *src_value, + GValue *dst_value, + gpointer user_data) { - EMComposerPrefs *prefs = (EMComposerPrefs *) object; - ESignatureList *signature_list; + const GdkColor *color; + gchar *string; - signature_list = mail_config_get_signatures (); + color = g_value_get_boxed (src_value); + string = gdk_color_to_string (color); + g_value_set_string (dst_value, string); + g_free (string); - if (prefs->sig_added_id != 0) { - g_signal_handler_disconnect ( - signature_list, prefs->sig_added_id); - prefs->sig_added_id = 0; + return TRUE; +} + +static gboolean +transform_string_to_color (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + GdkColor color; + const gchar *string; + gboolean success = FALSE; + + string = g_value_get_string (src_value); + if (gdk_color_parse (string, &color)) { + g_value_set_boxed (dst_value, &color); + success = TRUE; } - if (prefs->sig_removed_id != 0) { - g_signal_handler_disconnect ( - signature_list, prefs->sig_removed_id); - prefs->sig_removed_id = 0; + return success; +} + +static gboolean +transform_old_to_new_reply_style (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + gboolean success = TRUE; + + /* XXX This is the kind of legacy crap we wind up + * with when we don't migrate things properly. */ + + switch (g_value_get_int (src_value)) { + case 0: /* Quoted: 0 -> 2 */ + g_value_set_int (dst_value, 2); + break; + + case 1: /* Do Not Quote: 1 -> 3 */ + g_value_set_int (dst_value, 3); + break; + + case 2: /* Attach: 2 -> 0 */ + g_value_set_int (dst_value, 0); + break; + + case 3: /* Outlook: 3 -> 1 */ + g_value_set_int (dst_value, 1); + break; + + default: + success = FALSE; + break; } - if (prefs->sig_changed_id != 0) { - g_signal_handler_disconnect ( - signature_list, prefs->sig_changed_id); - prefs->sig_changed_id = 0; + return success; +} + +static gboolean +transform_new_to_old_reply_style (const GValue *src_value, + GValue *dst_value, + gpointer user_data) +{ + gboolean success = TRUE; + + /* XXX This is the kind of legacy crap we wind up + * with when we don't migrate things properly. */ + + switch (g_value_get_int (src_value)) { + case 0: /* Attach: 0 -> 2 */ + g_value_set_int (dst_value, 2); + break; + + case 1: /* Outlook: 1 -> 3 */ + g_value_set_int (dst_value, 3); + break; + + case 2: /* Quoted: 2 -> 0 */ + g_value_set_int (dst_value, 0); + break; + + case 3: /* Do Not Quote: 3 -> 1 */ + g_value_set_int (dst_value, 1); + break; + + default: + success = FALSE; + break; } - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); + return success; } static void @@ -96,8 +170,6 @@ composer_prefs_finalize (GObject *object) g_object_unref (prefs->gui); - g_hash_table_destroy (prefs->sig_hash); - /* Chain up to parent's finalize() method. */ G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -110,17 +182,12 @@ composer_prefs_class_init (EMComposerPrefsClass *class) parent_class = g_type_class_peek_parent (class); object_class = G_OBJECT_CLASS (class); - object_class->dispose = composer_prefs_dispose; object_class->finalize = composer_prefs_finalize; } static void composer_prefs_init (EMComposerPrefs *prefs) { - prefs->sig_hash = g_hash_table_new_full ( - g_direct_hash, g_direct_equal, - (GDestroyNotify) NULL, - (GDestroyNotify) gtk_tree_row_reference_free); } GType @@ -149,186 +216,6 @@ em_composer_prefs_get_type (void) return type; } -static void -sig_load_preview (EMComposerPrefs *prefs, - ESignature *signature) -{ - GtkHTML *html; - gchar *str; - - html = prefs->sig_preview; - - if (signature == NULL) { - gtk_html_load_from_string (html, " ", 1); - return; - } - - if (signature->script) - str = mail_config_signature_run_script (signature->filename); - else - str = e_msg_composer_get_sig_file_content ( - signature->filename, signature->html); - if (!str || !*str) { - /* make html stream happy and write at least one character */ - g_free (str); - str = g_strdup (" "); - } - - if (signature->html) { - gtk_html_load_from_string (html, str, strlen (str)); - } else { - GtkHTMLStream *stream; - int len; - - len = strlen (str); - stream = gtk_html_begin_content (html, "text/html; charset=utf-8"); - gtk_html_write (html, stream, "<PRE>", 5); - if (len) - gtk_html_write (html, stream, str, len); - gtk_html_write (html, stream, "</PRE>", 6); - gtk_html_end (html, stream, GTK_HTML_STREAM_OK); - } - - g_free (str); -} - -static void -signature_added (ESignatureList *signature_list, - ESignature *signature, - EMComposerPrefs *prefs) -{ - GtkTreeRowReference *row; - GtkTreeModel *model; - GtkTreePath *path; - GtkTreeIter iter; - - /* autogen signature is special */ - if (signature->autogen) - return; - - model = gtk_tree_view_get_model (prefs->sig_list); - gtk_list_store_append (GTK_LIST_STORE (model), &iter); - gtk_list_store_set ( - GTK_LIST_STORE (model), &iter, - 0, signature->name, 1, signature, -1); - - path = gtk_tree_model_get_path (model, &iter); - row = gtk_tree_row_reference_new (model, path); - gtk_tree_path_free (path); - - g_hash_table_insert (prefs->sig_hash, signature, row); -} - -static void -signature_removed (ESignatureList *signature_list, - ESignature *signature, - EMComposerPrefs *prefs) -{ - GtkTreeRowReference *row; - GtkTreeModel *model; - GtkTreePath *path; - GtkTreeIter iter; - - if (!(row = g_hash_table_lookup (prefs->sig_hash, signature))) - return; - - model = gtk_tree_view_get_model (prefs->sig_list); - path = gtk_tree_row_reference_get_path (row); - g_hash_table_remove (prefs->sig_hash, signature); - - if (!gtk_tree_model_get_iter (model, &iter, path)) { - gtk_tree_path_free (path); - return; - } - - gtk_list_store_remove ((GtkListStore *) model, &iter); -} - -static void -signature_changed (ESignatureList *signature_list, - ESignature *signature, - EMComposerPrefs *prefs) -{ - GtkTreeSelection *selection; - GtkTreeRowReference *row; - GtkTreeModel *model; - GtkTreePath *path; - GtkTreeIter iter; - ESignature *cur; - - if (!(row = g_hash_table_lookup (prefs->sig_hash, signature))) - return; - - model = gtk_tree_view_get_model (prefs->sig_list); - path = gtk_tree_row_reference_get_path (row); - - if (!gtk_tree_model_get_iter (model, &iter, path)) { - gtk_tree_path_free (path); - return; - } - - gtk_tree_path_free (path); - - gtk_list_store_set ((GtkListStore *) model, &iter, 0, signature->name, -1); - - selection = gtk_tree_view_get_selection (prefs->sig_list); - if (gtk_tree_selection_get_selected (selection, &model, &iter)) { - gtk_tree_model_get (model, &iter, 1, &cur, -1); - if (cur == signature) - sig_load_preview (prefs, signature); - } -} - -static void -sig_edit_cb (GtkWidget *widget, EMComposerPrefs *prefs) -{ - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkWidget *parent; - GtkTreeIter iter; - ESignature *signature; - - selection = gtk_tree_view_get_selection (prefs->sig_list); - if (!gtk_tree_selection_get_selected (selection, &model, &iter)) - return; - - gtk_tree_model_get (model, &iter, 1, &signature, -1); - - if (!signature->script) { - GtkWidget *editor; - - /* normal signature */ - if (!signature->filename || *signature->filename == '\0') { - g_free (signature->filename); - signature->filename = g_strdup (_("Unnamed")); - } - - editor = e_signature_editor_new (); - e_signature_editor_set_signature ( - E_SIGNATURE_EDITOR (editor), signature); - - parent = gtk_widget_get_toplevel ((GtkWidget *) prefs); - if (GTK_WIDGET_TOPLEVEL (parent)) - gtk_window_set_transient_for ( - GTK_WINDOW (editor), GTK_WINDOW (parent)); - - gtk_widget_show (editor); - } else { - /* signature script */ - GtkWidget *entry; - - entry = glade_xml_get_widget (prefs->sig_script_gui, "filechooserbutton_add_script"); - gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (entry), signature->filename); - - entry = glade_xml_get_widget (prefs->sig_script_gui, "entry_add_script_name"); - gtk_entry_set_text (GTK_ENTRY (entry), signature->name); - - g_object_set_data ((GObject *) entry, "sig", signature); - - gtk_window_present ((GtkWindow *) prefs->sig_script_dialog); - } -} - void em_composer_prefs_new_signature (GtkWindow *parent, gboolean html_mode) @@ -342,222 +229,6 @@ em_composer_prefs_new_signature (GtkWindow *parent, } static void -sig_delete_cb (GtkWidget *widget, EMComposerPrefs *prefs) -{ - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - ESignature *signature; - - selection = gtk_tree_view_get_selection (prefs->sig_list); - - if (gtk_tree_selection_get_selected (selection, &model, &iter)) { - gtk_tree_model_get (model, &iter, 1, &signature, -1); - mail_config_remove_signature (signature); - } - gtk_widget_grab_focus ((GtkWidget *)prefs->sig_list); -} - -static void -sig_add_cb (GtkWidget *widget, EMComposerPrefs *prefs) -{ - gboolean send_html; - GtkWidget *parent; - - send_html = gconf_client_get_bool ( - mail_config_get_gconf_client (), - "/apps/evolution/mail/composer/send_html", NULL); - - parent = gtk_widget_get_toplevel (GTK_WIDGET (prefs)); - parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; - - em_composer_prefs_new_signature (GTK_WINDOW (parent), send_html); - gtk_widget_grab_focus (GTK_WIDGET (prefs->sig_list)); -} - -static void -sig_add_script_response (GtkWidget *widget, int button, EMComposerPrefs *prefs) -{ - gchar *script, **argv = NULL; - GtkWidget *entry; - const gchar *name; - int argc; - - if (button == GTK_RESPONSE_ACCEPT) { - entry = glade_xml_get_widget (prefs->sig_script_gui, "filechooserbutton_add_script"); - script = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (entry)); - - entry = glade_xml_get_widget (prefs->sig_script_gui, "entry_add_script_name"); - name = gtk_entry_get_text (GTK_ENTRY (entry)); - if (script && *script && g_shell_parse_argv (script, &argc, &argv, NULL)) { - struct stat st; - - if (g_stat (argv[0], &st) == 0 && S_ISREG (st.st_mode) && g_access (argv[0], X_OK) == 0) { - ESignature *signature; - - if ((signature = g_object_get_data ((GObject *) entry, "sig"))) { - /* we're just editing an existing signature script */ - g_free (signature->name); - signature->name = g_strdup (name); - g_free(signature->filename); - signature->filename = g_strdup(script); - e_signature_list_change (mail_config_get_signatures (), signature); - } else { - signature = mail_config_signature_new (script, TRUE, TRUE); - signature->name = g_strdup (name); - - e_signature_list_add (mail_config_get_signatures (), signature); - g_object_unref (signature); - } - - mail_config_save_signatures(); - - gtk_widget_hide (prefs->sig_script_dialog); - g_strfreev (argv); - g_free (script); - - return; - } - } - - e_error_run((GtkWindow *)prefs->sig_script_dialog, "mail:signature-notscript", argv ? argv[0] : script, NULL); - g_strfreev (argv); - g_free (script); - return; - } - - gtk_widget_hide (widget); -} - -static void -sig_add_script_cb (GtkWidget *widget, EMComposerPrefs *prefs) -{ - GtkWidget *entry; - - entry = glade_xml_get_widget (prefs->sig_script_gui, "entry_add_script_name"); - gtk_entry_set_text (GTK_ENTRY (entry), _("Unnamed")); - - g_object_set_data ((GObject *) entry, "sig", NULL); - - gtk_window_present ((GtkWindow *) prefs->sig_script_dialog); -} - -static void -sig_selection_changed (GtkTreeSelection *selection, - EMComposerPrefs *prefs) -{ - ESignature *signature; - GtkTreeModel *model; - GtkTreeIter iter; - gboolean valid; - - valid = gtk_tree_selection_get_selected (selection, &model, &iter); - - if (valid) { - gtk_tree_model_get (model, &iter, 1, &signature, -1); - sig_load_preview (prefs, signature); - } else - sig_load_preview (prefs, NULL); - - gtk_widget_set_sensitive (GTK_WIDGET (prefs->sig_delete), valid); - gtk_widget_set_sensitive (GTK_WIDGET (prefs->sig_edit), valid); -} - -static void -sig_fill_list (EMComposerPrefs *prefs) -{ - ESignatureList *signature_list; - GtkTreeModel *model; - EIterator *iterator; - - model = gtk_tree_view_get_model (prefs->sig_list); - gtk_list_store_clear (GTK_LIST_STORE (model)); - - signature_list = mail_config_get_signatures (); - iterator = e_list_get_iterator ((EList *) signature_list); - - while (e_iterator_is_valid (iterator)) { - ESignature *signature; - - signature = (ESignature *) e_iterator_get (iterator); - signature_added (signature_list, signature, prefs); - - e_iterator_next (iterator); - } - - g_object_unref (iterator); - - gtk_widget_set_sensitive (GTK_WIDGET (prefs->sig_edit), FALSE); - gtk_widget_set_sensitive (GTK_WIDGET (prefs->sig_delete), FALSE); - - prefs->sig_added_id = g_signal_connect ( - signature_list, "signature-added", - G_CALLBACK (signature_added), prefs); - - prefs->sig_removed_id = g_signal_connect ( - signature_list, "signature-removed", - G_CALLBACK (signature_removed), prefs); - - prefs->sig_changed_id = g_signal_connect ( - signature_list, "signature-changed", - G_CALLBACK (signature_changed), prefs); -} - -static void -url_requested (GtkHTML *html, - const gchar *url, - GtkHTMLStream *handle) -{ - GtkHTMLStreamStatus status; - gchar buf[128]; - gssize size; - gint fd; - gchar *filename; - - if (strncmp (url, "file:", 5) == 0) - filename = g_filename_from_uri (url, NULL, NULL); - else - filename = g_strdup (url); - fd = g_open (filename, O_RDONLY | O_BINARY, 0); - g_free (filename); - - status = GTK_HTML_STREAM_OK; - if (fd != -1) { - while ((size = read (fd, buf, sizeof (buf)))) { - if (size == -1) { - status = GTK_HTML_STREAM_ERROR; - break; - } else - gtk_html_write (html, handle, buf, size); - } - } else - status = GTK_HTML_STREAM_ERROR; - - gtk_html_end (html, handle, status); - if (fd > 0) - close (fd); -} - -static void -spell_color_set (GtkColorButton *color_button, - EMComposerPrefs *prefs) -{ - GConfClient *client; - const gchar *key; - GdkColor color; - gchar *string; - - gtk_color_button_get_color (color_button, &color); - string = gdk_color_to_string (&color); - - client = mail_config_get_gconf_client (); - key = "/apps/evolution/mail/composer/spell_color"; - gconf_client_set_string (client, key, string, NULL); - - g_free (string); -} - -static void spell_language_toggled_cb (GtkCellRendererToggle *renderer, const gchar *path_string, EMComposerPrefs *prefs) @@ -619,13 +290,8 @@ spell_setup (EMComposerPrefs *prefs) { const GList *available_languages; GList *active_languages; - GConfClient *client; GtkListStore *store; - GdkColor color; - const gchar *key; - gchar *string; - client = mail_config_get_gconf_client (); store = GTK_LIST_STORE (prefs->language_model); available_languages = gtkhtml_spell_language_get_available (); @@ -652,52 +318,6 @@ spell_setup (EMComposerPrefs *prefs) } g_list_free (active_languages); - - key = "/apps/evolution/mail/composer/spell_color"; - string = gconf_client_get_string (client, key, NULL); - if (string == NULL || !gdk_color_parse (string, &color)) - gdk_color_parse ("Red", &color); - gtk_color_button_set_color (GTK_COLOR_BUTTON (prefs->color), &color); - - g_signal_connect ( - prefs->color, "color_set", - G_CALLBACK (spell_color_set), prefs); -} - -static gint -reply_style_new_order (gint style_id, - gboolean from_enum_to_option_id) -{ - gint values[] = { - MAIL_CONFIG_REPLY_ATTACH, 0, - MAIL_CONFIG_REPLY_OUTLOOK, 1, - MAIL_CONFIG_REPLY_QUOTED, 2, - MAIL_CONFIG_REPLY_DO_NOT_QUOTE, 3, - -1, -1}; - gint ii; - - for (ii = from_enum_to_option_id ? 0 : 1; values[ii] != -1; ii += 2) { - if (values[ii] == style_id) - return values [from_enum_to_option_id ? ii + 1 : ii - 1]; - } - - return style_id; -} - -static void -style_changed (GtkComboBox *combobox, const gchar *key) -{ - GConfClient *client; - gint style; - - client = mail_config_get_gconf_client (); - style = gtk_combo_box_get_active (combobox); - g_return_if_fail (style >= 0); - - if (g_str_has_suffix (key, "/reply_style")) - style = reply_style_new_order (style, FALSE); - - gconf_client_set_int (client, key, style, NULL); } static void @@ -781,38 +401,15 @@ emcp_free (EConfig *ec, GSList *items, gpointer data) g_slist_free (items); } -static gboolean -signature_key_press_cb (GtkTreeView *tree_view, - GdkEventKey *event, - EMComposerPrefs *prefs) -{ - /* No need to care about anything other than DEL key */ - if (event->keyval == GDK_Delete) { - sig_delete_cb (GTK_WIDGET (tree_view), prefs); - return TRUE; - } - - return FALSE; -} - -static gboolean -sig_tree_event_cb (GtkTreeView *tree_view, - GdkEvent *event, - EMComposerPrefs *prefs) -{ - if (event->type == GDK_2BUTTON_PRESS) { - sig_edit_cb (GTK_WIDGET (tree_view), prefs); - return TRUE; - } - - return FALSE; -} - static void -em_composer_prefs_construct (EMComposerPrefs *prefs) +em_composer_prefs_construct (EMComposerPrefs *prefs, + EShell *shell) { GtkWidget *toplevel, *widget, *menu, *info_pixmap; - GtkDialog *dialog; + GtkWidget *container; + EShellSettings *shell_settings; + ESignatureList *signature_list; + ESignatureTreeView *signature_tree_view; GladeXML *gui; GtkTreeView *view; GtkListStore *store; @@ -820,25 +417,22 @@ em_composer_prefs_construct (EMComposerPrefs *prefs) GtkCellRenderer *renderer; GConfBridge *bridge; GConfClient *client; - const gchar *key; - int style; gchar *buf; EMConfig *ec; EMConfigTargetPrefs *target; GSList *l; int i; gchar *gladefile; - gboolean sensitive; bridge = gconf_bridge_get (); client = mail_config_get_gconf_client (); + shell_settings = e_shell_get_shell_settings (shell); gladefile = g_build_filename (EVOLUTION_GLADEDIR, "mail-config.glade", NULL); gui = glade_xml_new (gladefile, "composer_toplevel", NULL); prefs->gui = gui; - prefs->sig_script_gui = glade_xml_new (gladefile, "vbox_add_script_signature", NULL); g_free (gladefile); /** @HookPoint-EMConfig: Mail Composer Preferences @@ -858,57 +452,50 @@ em_composer_prefs_construct (EMComposerPrefs *prefs) /* General tab */ /* Default Behavior */ - key = "/apps/evolution/mail/composer/send_html"; widget = glade_xml_get_widget (gui, "chkSendHTML"); - if (!gconf_client_key_is_writable (client, key, NULL)) - gtk_widget_set_sensitive (widget, FALSE); - gconf_bridge_bind_property (bridge, key, G_OBJECT (widget), "active"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "composer-format-html", + G_OBJECT (widget), "active"); - key = "/apps/evolution/mail/prompts/empty_subject"; widget = glade_xml_get_widget (gui, "chkPromptEmptySubject"); - if (!gconf_client_key_is_writable (client, key, NULL)) - gtk_widget_set_sensitive (widget, FALSE); - gconf_bridge_bind_property (bridge, key, G_OBJECT (widget), "active"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "composer-prompt-empty-subject", + G_OBJECT (widget), "active"); - key = "/apps/evolution/mail/prompts/only_bcc"; widget = glade_xml_get_widget (gui, "chkPromptBccOnly"); - if (!gconf_client_key_is_writable (client, key, NULL)) - gtk_widget_set_sensitive (widget, FALSE); - gconf_bridge_bind_property (bridge, key, G_OBJECT (widget), "active"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "composer-prompt-only-bcc", + G_OBJECT (widget), "active"); - key = "/apps/evolution/mail/composer/magic_smileys"; widget = glade_xml_get_widget (gui, "chkAutoSmileys"); - if (!gconf_client_key_is_writable (client, key, NULL)) - gtk_widget_set_sensitive (widget, FALSE); - gconf_bridge_bind_property (bridge, key, G_OBJECT (widget), "active"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "composer-magic-smileys", + G_OBJECT (widget), "active"); - key = "/apps/evolution/mail/composer/request_receipt"; widget = glade_xml_get_widget (gui, "chkRequestReceipt"); - if (!gconf_client_key_is_writable (client, key, NULL)) - gtk_widget_set_sensitive (widget, FALSE); - gconf_bridge_bind_property (bridge, key, G_OBJECT (widget), "active"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "composer-request-receipt", + G_OBJECT (widget), "active"); - key = "/apps/evolution/mail/composer/reply_start_bottom"; widget = glade_xml_get_widget (gui, "chkReplyStartBottom"); - if (!gconf_client_key_is_writable (client, key, NULL)) - gtk_widget_set_sensitive (widget, FALSE); - gconf_bridge_bind_property (bridge, key, G_OBJECT (widget), "active"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "composer-reply-start-bottom", + G_OBJECT (widget), "active"); - key = "/apps/evolution/mail/composer/outlook_filenames"; widget = glade_xml_get_widget (gui, "chkOutlookFilenames"); - if (!gconf_client_key_is_writable (client, key, NULL)) - gtk_widget_set_sensitive (widget, FALSE); - gconf_bridge_bind_property (bridge, key, G_OBJECT (widget), "active"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "composer-outlook-filenames", + G_OBJECT (widget), "active"); - key = "/apps/evolution/mail/composer/top_signature"; widget = glade_xml_get_widget (gui, "chkTopSignature"); - if (!gconf_client_key_is_writable (client, key, NULL)) - gtk_widget_set_sensitive (widget, FALSE); - gconf_bridge_bind_property (bridge, key, G_OBJECT (widget), "active"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "composer-top-signature", + G_OBJECT (widget), "active"); - key = "/apps/evolution/mail/composer/inline_spelling"; widget = glade_xml_get_widget (gui, "chkEnableSpellChecking"); - gconf_bridge_bind_property (bridge, key, G_OBJECT (widget), "active"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "composer-inline-spelling", + G_OBJECT (widget), "active"); prefs->charset = GTK_OPTION_MENU ( glade_xml_get_widget (gui, "omenuCharset1")); @@ -924,8 +511,6 @@ em_composer_prefs_construct (EMComposerPrefs *prefs) g_free (buf); /* Spell Checking */ - widget = glade_xml_get_widget (gui, "colorButtonSpellCheckColor"); - prefs->color = GTK_COLOR_BUTTON (widget); widget = glade_xml_get_widget (gui, "listSpellCheckLanguage"); view = GTK_TREE_VIEW (widget); store = gtk_list_store_new ( @@ -945,7 +530,7 @@ em_composer_prefs_construct (EMComposerPrefs *prefs) gtk_tree_view_insert_column_with_attributes ( view, -1, _("Language(s)"), - gtk_cell_renderer_text_new (), + gtk_cell_renderer_text_new (), "text", 1, NULL); selection = gtk_tree_view_get_selection (view); gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE); @@ -953,114 +538,84 @@ em_composer_prefs_construct (EMComposerPrefs *prefs) gtk_image_set_from_stock ( GTK_IMAGE (info_pixmap), GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_BUTTON); + + widget = glade_xml_get_widget (gui, "colorButtonSpellCheckColor"); + e_mutual_binding_new_full ( + G_OBJECT (shell_settings), "composer-spell-color", + G_OBJECT (widget), "color", + transform_string_to_color, + transform_color_to_string, + NULL, NULL); + spell_setup (prefs); /* Forwards and Replies */ - prefs->forward_style = GTK_COMBO_BOX (glade_xml_get_widget (gui, "comboboxForwardStyle")); - style = gconf_client_get_int (client, "/apps/evolution/mail/format/forward_style", NULL); - gtk_combo_box_set_active (prefs->forward_style, style); - g_signal_connect (prefs->forward_style, "changed", G_CALLBACK (style_changed), "/apps/evolution/mail/format/forward_style"); - - prefs->reply_style = GTK_COMBO_BOX (glade_xml_get_widget (gui, "comboboxReplyStyle")); - style = gconf_client_get_int (client, "/apps/evolution/mail/format/reply_style", NULL); - gtk_combo_box_set_active (prefs->reply_style, reply_style_new_order (style, TRUE)); - g_signal_connect (prefs->reply_style, "changed", G_CALLBACK (style_changed), "/apps/evolution/mail/format/reply_style"); + widget = glade_xml_get_widget (gui, "comboboxForwardStyle"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-forward-style", + G_OBJECT (widget), "active"); + + widget = glade_xml_get_widget (gui, "comboboxReplyStyle"); + e_mutual_binding_new_full ( + G_OBJECT (shell_settings), "mail-reply-style", + G_OBJECT (widget), "active", + transform_old_to_new_reply_style, + transform_new_to_old_reply_style, + NULL, NULL); /* Signatures */ - dialog = (GtkDialog *) gtk_dialog_new (); - - gtk_widget_realize ((GtkWidget *) dialog); - gtk_container_set_border_width ((GtkContainer *)dialog->action_area, 12); - gtk_container_set_border_width ((GtkContainer *)dialog->vbox, 0); - - prefs->sig_script_dialog = (GtkWidget *) dialog; - gtk_dialog_add_buttons (dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, - GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); - gtk_dialog_set_has_separator (dialog, FALSE); - gtk_window_set_title ((GtkWindow *) dialog, _("Add signature script")); - g_signal_connect (dialog, "response", G_CALLBACK (sig_add_script_response), prefs); - widget = glade_xml_get_widget (prefs->sig_script_gui, "vbox_add_script_signature"); - gtk_box_pack_start ((GtkBox *) dialog->vbox, widget, TRUE, TRUE, 0); - - key = "/apps/evolution/mail/signatures"; - sensitive = gconf_client_key_is_writable (client, key, NULL); - - widget = glade_xml_get_widget (gui, "cmdSignatureAdd"); - gtk_widget_set_sensitive (widget, sensitive); - g_signal_connect ( - widget, "clicked", - G_CALLBACK (sig_add_cb), prefs); - prefs->sig_add = GTK_BUTTON (widget); + signature_list = e_get_signature_list (); + container = glade_xml_get_widget (gui, "alignSignatures"); + widget = e_signature_manager_new (signature_list); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); + + /* The mail shell module responds to the "window-created" signal + * that this triggers and configures it with composer preferences. */ + g_signal_connect_swapped ( + widget, "editor-created", + G_CALLBACK (e_shell_watch_window), shell); - widget = glade_xml_get_widget (gui, "cmdSignatureAddScript"); - gtk_widget_set_sensitive (widget, sensitive && !mail_config_scripts_disabled ()); - g_signal_connect ( - widget, "clicked", - G_CALLBACK (sig_add_script_cb), prefs); - prefs->sig_add_script = GTK_BUTTON (widget); + e_binding_new ( + G_OBJECT (shell_settings), "composer-format-html", + G_OBJECT (widget), "prefer-html"); - widget = glade_xml_get_widget (gui, "cmdSignatureEdit"); - gtk_widget_set_sensitive (widget, sensitive); - g_signal_connect ( - widget, "clicked", - G_CALLBACK (sig_edit_cb), prefs); - prefs->sig_edit = GTK_BUTTON (widget); + e_binding_new_with_negation ( + G_OBJECT (shell_settings), "disable-command-line", + G_OBJECT (widget), "allow-scripts"); - widget = glade_xml_get_widget (gui, "cmdSignatureDelete"); - gtk_widget_set_sensitive (widget, sensitive); - g_signal_connect ( - widget, "clicked", - G_CALLBACK (sig_delete_cb), prefs); - prefs->sig_delete = GTK_BUTTON (widget); - - widget = glade_xml_get_widget (gui, "listSignatures"); - gtk_widget_set_sensitive (widget, sensitive); - prefs->sig_list = GTK_TREE_VIEW (widget); - store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_POINTER); - gtk_tree_view_set_model (prefs->sig_list, GTK_TREE_MODEL (store)); - gtk_tree_view_insert_column_with_attributes ( - prefs->sig_list, -1, _("Signature(s)"), - gtk_cell_renderer_text_new (), "text", 0, NULL); - selection = gtk_tree_view_get_selection (prefs->sig_list); - gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); - g_signal_connect ( - selection, "changed", - G_CALLBACK (sig_selection_changed), prefs); - g_signal_connect ( - prefs->sig_list, "event", - G_CALLBACK (sig_tree_event_cb), prefs); + signature_tree_view = e_signature_manager_get_tree_view ( + E_SIGNATURE_MANAGER (widget)); - sig_fill_list (prefs); + container = glade_xml_get_widget (gui, "scrolled-sig"); + widget = e_signature_preview_new (); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); - /* preview GtkHTML widget */ - widget = glade_xml_get_widget (gui, "scrolled-sig"); - prefs->sig_preview = (GtkHTML *) gtk_html_new (); - g_signal_connect ( - prefs->sig_preview, "url_requested", - G_CALLBACK (url_requested), NULL); - gtk_widget_show (GTK_WIDGET (prefs->sig_preview)); - gtk_container_add ( - GTK_CONTAINER (widget), - GTK_WIDGET (prefs->sig_preview)); + e_binding_new_with_negation ( + G_OBJECT (shell_settings), "disable-command-line", + G_OBJECT (widget), "allow-scripts"); + + e_binding_new ( + G_OBJECT (signature_tree_view), "selected", + G_OBJECT (widget), "signature"); /* get our toplevel widget */ target = em_config_target_new_prefs (ec, client); e_config_set_target ((EConfig *)ec, (EConfigTarget *)target); toplevel = e_config_create_widget ((EConfig *)ec); gtk_container_add (GTK_CONTAINER (prefs), toplevel); - - g_signal_connect ( - prefs->sig_list, "key-press-event", - G_CALLBACK (signature_key_press_cb), prefs); } GtkWidget * -em_composer_prefs_new (void) +em_composer_prefs_new (EShell *shell) { EMComposerPrefs *prefs; + g_return_val_if_fail (E_IS_SHELL (shell), NULL); + prefs = g_object_new (EM_TYPE_COMPOSER_PREFS, NULL); - em_composer_prefs_construct (prefs); + em_composer_prefs_construct (prefs, shell); return GTK_WIDGET (prefs); } diff --git a/mail/em-composer-prefs.h b/mail/em-composer-prefs.h index 82c6ece51e..19d753e121 100644 --- a/mail/em-composer-prefs.h +++ b/mail/em-composer-prefs.h @@ -20,10 +20,12 @@ * */ -#ifndef __EM_COMPOSER_PREFS_H__ -#define __EM_COMPOSER_PREFS_H__ +#ifndef EM_COMPOSER_PREFS_H +#define EM_COMPOSER_PREFS_H #include <gtk/gtk.h> +#include <glade/glade.h> +#include <shell/e-shell.h> /* Standard GObject macros */ #define EM_TYPE_COMPOSER_PREFS \ @@ -50,19 +52,17 @@ typedef struct _EMComposerPrefs EMComposerPrefs; typedef struct _EMComposerPrefsClass EMComposerPrefsClass; struct _ESignature; -struct _GladeXML; struct _EMComposerPrefs { GtkVBox parent; - struct _GladeXML *gui; + GladeXML *gui; /* General tab */ /* Default Behavior */ GtkOptionMenu *charset; - GtkColorButton *color; GtkTreeModel *language_model; /* Forwards and Replies */ @@ -70,20 +70,7 @@ struct _EMComposerPrefs { GtkComboBox *reply_style; /* Signatures */ - GtkTreeView *sig_list; - GHashTable *sig_hash; - GtkButton *sig_add; - GtkButton *sig_add_script; - GtkButton *sig_edit; - GtkButton *sig_delete; struct _GtkHTML *sig_preview; - - struct _GladeXML *sig_script_gui; - GtkWidget *sig_script_dialog; - - guint sig_added_id; - guint sig_removed_id; - guint sig_changed_id; }; struct _EMComposerPrefsClass { @@ -91,7 +78,7 @@ struct _EMComposerPrefsClass { }; GType em_composer_prefs_get_type (void); -GtkWidget * em_composer_prefs_new (void); +GtkWidget * em_composer_prefs_new (EShell *shell); void em_composer_prefs_new_signature (GtkWindow *parent, gboolean html_mode); @@ -101,4 +88,4 @@ void em_composer_prefs_new_signature (GtkWindow *parent, G_END_DECLS -#endif /* __EM_COMPOSER_PREFS_H__ */ +#endif /* EM_COMPOSER_PREFS_H */ diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c index 88225669c8..381e7fbfc5 100644 --- a/mail/em-composer-utils.c +++ b/mail/em-composer-utils.c @@ -37,20 +37,22 @@ #include "mail-config.h" #include "mail-session.h" #include "mail-send-recv.h" -#include "mail-component.h" #include "e-util/e-error.h" +#include "e-util/e-account-utils.h" #include "em-utils.h" #include "em-composer-utils.h" #include "composer/e-msg-composer.h" #include "composer/e-composer-autosave.h" +#include "composer/e-composer-post-header.h" +#include "em-folder-selector.h" +#include "em-folder-tree.h" #include "em-format-html.h" +#include "em-format-html-print.h" #include "em-format-quote.h" #include "em-event.h" -#include "libedataserver/e-account-list.h" - #include <camel/camel-folder.h> #include <camel/camel-multipart.h> #include <camel/camel-string-utils.h> @@ -58,6 +60,8 @@ #include <camel/camel-nntp-address.h> #include <camel/camel-vee-folder.h> +#include "e-mail-shell-module.h" + #ifdef G_OS_WIN32 /* Undef the similar macro from pthread.h, it doesn't check if * gmtime() returns NULL. @@ -72,6 +76,9 @@ static EAccount * guess_account (CamelMimeMessage *message, CamelFolder *folder); +static void em_utils_composer_send_cb (EMsgComposer *composer); +static void em_utils_composer_save_draft_cb (EMsgComposer *composer); + struct emcs_t { unsigned int ref_count; @@ -88,28 +95,67 @@ emcs_new (void) { struct emcs_t *emcs; - emcs = g_new (struct emcs_t, 1); + emcs = g_new0 (struct emcs_t, 1); emcs->ref_count = 1; - emcs->drafts_folder = NULL; - emcs->drafts_uid = NULL; - emcs->folder = NULL; - emcs->flags = 0; - emcs->set = 0; - emcs->uid = NULL; return emcs; } static void +emcs_set_drafts_info (struct emcs_t *emcs, + CamelFolder *drafts_folder, + const gchar *drafts_uid) +{ + g_return_if_fail (emcs != NULL); + g_return_if_fail (drafts_folder != NULL); + g_return_if_fail (drafts_uid != NULL); + + if (emcs->drafts_folder != NULL) + camel_object_unref (emcs->drafts_folder); + g_free (emcs->drafts_uid); + + camel_object_ref (drafts_folder); + emcs->drafts_folder = drafts_folder; + emcs->drafts_uid = g_strdup (drafts_uid); + + g_debug ("%s", G_STRFUNC); +} + +static void +emcs_set_folder_info (struct emcs_t *emcs, + CamelFolder *folder, + const gchar *uid, + guint32 flags, + guint32 set) +{ + g_return_if_fail (emcs != NULL); + g_return_if_fail (folder != NULL); + g_return_if_fail (uid != NULL); + + if (emcs->folder != NULL) + camel_object_unref (emcs->folder); + g_free (emcs->uid); + + camel_object_ref (folder); + emcs->folder = folder; + emcs->uid = g_strdup (uid); + emcs->flags = flags; + emcs->set = set; + + g_debug ("%s", G_STRFUNC); +} + +static void free_emcs (struct emcs_t *emcs) { - if (emcs->drafts_folder) + if (emcs->drafts_folder != NULL) camel_object_unref (emcs->drafts_folder); g_free (emcs->drafts_uid); - if (emcs->folder) + if (emcs->folder != NULL) camel_object_unref (emcs->folder); g_free (emcs->uid); + g_free (emcs); } @@ -127,12 +173,6 @@ emcs_unref (struct emcs_t *emcs) free_emcs (emcs); } -static void -composer_destroy_cb (gpointer user_data, GObject *deadbeef) -{ - emcs_unref (user_data); -} - static gboolean ask_confirm_for_unwanted_html_mail (EMsgComposer *composer, EDestination **recipients) { @@ -226,17 +266,6 @@ composer_send_queued_cb (CamelFolder *folder, CamelMimeMessage *msg, CamelMessag mail_send (); } } else { - if (!emcs) { - /* disconnect the previous signal handlers */ - g_signal_handlers_disconnect_matched (send->composer, G_SIGNAL_MATCH_FUNC, 0, - 0, NULL, em_utils_composer_send_cb, NULL); - g_signal_handlers_disconnect_matched (send->composer, G_SIGNAL_MATCH_FUNC, 0, - 0, NULL, em_utils_composer_save_draft_cb, NULL); - - /* reconnect to the signals using a non-NULL emcs for the callback data */ - em_composer_utils_setup_default_callbacks (send->composer); - } - e_msg_composer_set_enable_autosave (send->composer, TRUE); gtk_widget_show (GTK_WIDGET (send->composer)); } @@ -416,8 +445,8 @@ composer_get_message (EMsgComposer *composer, gboolean save_html_object_data) return message; } -void -em_utils_composer_send_cb (EMsgComposer *composer, gpointer user_data) +static void +em_utils_composer_send_cb (EMsgComposer *composer) { EComposerHeaderTable *table; CamelMimeMessage *message; @@ -429,32 +458,36 @@ em_utils_composer_send_cb (EMsgComposer *composer, gpointer user_data) table = e_msg_composer_get_header_table (composer); account = e_composer_header_table_get_account (table); if (!account || !account->enabled) { - e_error_run((GtkWindow *)composer, "mail:send-no-account-enabled", NULL); + e_error_run ( + GTK_WINDOW (composer), + "mail:send-no-account-enabled", NULL); return; } - if (!(message = composer_get_message (composer, FALSE))) + if ((message = composer_get_message (composer, FALSE)) == NULL) return; - mail_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX); + mail_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_OUTBOX); camel_object_ref (mail_folder); /* mail the message */ - info = camel_message_info_new(NULL); - camel_message_info_set_flags(info, CAMEL_MESSAGE_SEEN, ~0); + info = camel_message_info_new (NULL); + camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, ~0); send = g_malloc (sizeof (*send)); - send->emcs = user_data; + send->emcs = g_object_get_data (G_OBJECT (composer), "emcs"); if (send->emcs) emcs_ref (send->emcs); send->send = TRUE; - send->composer = composer; - g_object_ref (composer); + send->composer = g_object_ref (composer); gtk_widget_hide (GTK_WIDGET (composer)); e_msg_composer_set_enable_autosave (composer, FALSE); - mail_append_mail (mail_folder, message, info, composer_send_queued_cb, send); + mail_append_mail ( + mail_folder, message, info, composer_send_queued_cb, send); + camel_object_unref (mail_folder); camel_object_unref (message); } @@ -493,17 +526,9 @@ save_draft_done (CamelFolder *folder, CamelMimeMessage *msg, CamelMessageInfo *i composer_set_no_change (sdi->composer, FALSE); - if ((emcs = sdi->emcs) == NULL) { + if ((emcs = sdi->emcs) == NULL) emcs = emcs_new (); - /* disconnect the previous signal handlers */ - g_signal_handlers_disconnect_by_func (sdi->composer, G_CALLBACK (em_utils_composer_send_cb), NULL); - g_signal_handlers_disconnect_by_func (sdi->composer, G_CALLBACK (em_utils_composer_save_draft_cb), NULL); - - /* reconnect to the signals using a non-NULL emcs for the callback data */ - em_composer_utils_setup_default_callbacks (sdi->composer); - } - if (emcs->drafts_folder) { /* delete the original draft message */ camel_folder_set_message_flags (emcs->drafts_folder, emcs->drafts_uid, @@ -555,13 +580,13 @@ save_draft_folder (char *uri, CamelFolder *folder, gpointer data) } } -void -em_utils_composer_save_draft_cb (EMsgComposer *composer, gpointer user_data) +static void +em_utils_composer_save_draft_cb (EMsgComposer *composer) { - const char *default_drafts_folder_uri = mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_DRAFTS); - CamelFolder *drafts_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_DRAFTS); + CamelFolder *local_drafts_folder; EComposerHeaderTable *table; struct _save_draft_info *sdi; + const gchar *local_drafts_folder_uri; CamelFolder *folder = NULL; CamelMimeMessage *msg; CamelMessageInfo *info; @@ -571,19 +596,25 @@ em_utils_composer_save_draft_cb (EMsgComposer *composer, gpointer user_data) * get destroyed while we're in mail_msg_wait() a little lower * down, waiting for the folder to open */ - g_object_ref(composer); + local_drafts_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_DRAFTS); + + local_drafts_folder_uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, E_MAIL_FOLDER_DRAFTS); + + g_object_ref (composer); msg = e_msg_composer_get_message_draft (composer); table = e_msg_composer_get_header_table (composer); account = e_composer_header_table_get_account (table); - sdi = g_malloc(sizeof(struct _save_draft_info)); + sdi = g_malloc (sizeof(struct _save_draft_info)); sdi->composer = composer; - sdi->emcs = user_data; + sdi->emcs = g_object_get_data (G_OBJECT (composer), "emcs"); if (sdi->emcs) - emcs_ref(sdi->emcs); + emcs_ref (sdi->emcs); if (account && account->drafts_folder_uri && - strcmp (account->drafts_folder_uri, default_drafts_folder_uri) != 0) { + strcmp (account->drafts_folder_uri, local_drafts_folder_uri) != 0) { int id; id = mail_get_folder (account->drafts_folder_uri, 0, save_draft_folder, &folder, mail_msg_unordered_push); @@ -599,11 +630,11 @@ em_utils_composer_save_draft_cb (EMsgComposer *composer, gpointer user_data) return; } - folder = drafts_folder; - camel_object_ref (drafts_folder); + folder = local_drafts_folder; + camel_object_ref (local_drafts_folder); } } else { - folder = drafts_folder; + folder = local_drafts_folder; camel_object_ref (folder); } @@ -615,43 +646,24 @@ em_utils_composer_save_draft_cb (EMsgComposer *composer, gpointer user_data) camel_object_unref (msg); } -void -em_composer_utils_setup_callbacks (EMsgComposer *composer, - CamelFolder *folder, - const char *uid, - guint32 flags, - guint32 set, - CamelFolder *drafts, - const char *drafts_uid) +static void +em_utils_composer_print_cb (EMsgComposer *composer, + GtkPrintOperationAction action) { - struct emcs_t *emcs; - - emcs = emcs_new (); - - if (folder && uid) { - camel_object_ref (folder); - emcs->folder = folder; - emcs->uid = g_strdup (uid); - emcs->flags = flags; - emcs->set = set; - } - - if (drafts && drafts_uid) { - camel_object_ref (drafts); - emcs->drafts_folder = drafts; - emcs->drafts_uid = g_strdup (drafts_uid); - } + CamelMimeMessage *message; + EMFormatHTMLPrint *efhp; - g_signal_connect (composer, "send", G_CALLBACK (em_utils_composer_send_cb), emcs); - g_signal_connect (composer, "save-draft", G_CALLBACK (em_utils_composer_save_draft_cb), emcs); + message = e_msg_composer_get_message_print (composer, 1); - g_object_weak_ref ((GObject *) composer, (GWeakNotify) composer_destroy_cb, emcs); + efhp = em_format_html_print_new (NULL, action); + em_format_html_print_raw_message (efhp, message); + g_object_unref (efhp); } /* Composing messages... */ static EMsgComposer * -create_new_composer (const char *subject, const char *fromuri, gboolean use_default_callbacks) +create_new_composer (const char *subject, const char *fromuri) { EMsgComposer *composer; EComposerHeaderTable *table; @@ -662,15 +674,12 @@ create_new_composer (const char *subject, const char *fromuri, gboolean use_defa return NULL; if (fromuri) - account = mail_config_get_account_by_source_url(fromuri); + account = mail_config_get_account_by_source_url (fromuri); table = e_msg_composer_get_header_table (composer); e_composer_header_table_set_account (table, account); e_composer_header_table_set_subject (table, subject); - if (use_default_callbacks) - em_composer_utils_setup_default_callbacks (composer); - return composer; } @@ -685,7 +694,7 @@ em_utils_compose_new_message (const char *fromuri) { GtkWidget *composer; - composer = (GtkWidget *) create_new_composer ("", fromuri, TRUE); + composer = (GtkWidget *) create_new_composer ("", fromuri); if (composer == NULL) return; @@ -715,7 +724,6 @@ em_utils_compose_new_message_with_mailto (const char *url, const char *fromuri) composer = e_msg_composer_new (); table = e_msg_composer_get_header_table (composer); - em_composer_utils_setup_default_callbacks (composer); if (fromuri && (account = mail_config_get_account_by_source_url(fromuri))) @@ -763,8 +771,6 @@ em_utils_post_to_folder (CamelFolder *folder) table, account->name); } - em_composer_utils_setup_default_callbacks (composer); - composer_set_no_change (composer, TRUE); gtk_widget_show ((GtkWidget *) composer); @@ -796,8 +802,6 @@ em_utils_post_to_url (const char *url) g_list_free (list); } - em_composer_utils_setup_default_callbacks (composer); - composer_set_no_change (composer, TRUE); gtk_widget_show ((GtkWidget *) composer); @@ -945,10 +949,12 @@ edit_message (CamelMimeMessage *message, CamelFolder *drafts, const char *uid) composer = e_msg_composer_new_with_message (message); - if (em_utils_folder_is_templates(drafts, NULL) == TRUE) - em_composer_utils_setup_callbacks (composer, NULL, NULL, 0, 0, NULL, NULL); - else - em_composer_utils_setup_callbacks (composer, NULL, NULL, 0, 0, drafts, uid); + if (em_utils_folder_is_drafts (drafts, NULL)) { + struct emcs_t *emcs; + + emcs = g_object_get_data (G_OBJECT (composer), "emcs"); + emcs_set_drafts_info (emcs, drafts, uid); + } composer_set_no_change (composer, TRUE); @@ -1071,7 +1077,7 @@ forward_attached (CamelFolder *folder, GPtrArray *uids, GPtrArray *messages, Cam { EMsgComposer *composer; - composer = create_new_composer (subject, fromuri, TRUE); + composer = create_new_composer (subject, fromuri); if (composer == NULL) return; @@ -1150,7 +1156,7 @@ forward_non_attached (CamelFolder *folder, GPtrArray *uids, GPtrArray *messages, text = em_utils_message_to_html (message, _("-------- Forwarded Message --------"), flags, &len, NULL, NULL); if (text) { - composer = create_new_composer (subject, fromuri, !uids || !uids->pdata [i]); + composer = create_new_composer (subject, fromuri); if (composer) { if (CAMEL_IS_MULTIPART(camel_medium_get_content_object((CamelMedium *)message))) @@ -1158,8 +1164,12 @@ forward_non_attached (CamelFolder *folder, GPtrArray *uids, GPtrArray *messages, e_msg_composer_set_body_text (composer, text, len); - if (uids && uids->pdata[i]) - em_composer_utils_setup_callbacks (composer, folder, uids->pdata[i], CAMEL_MESSAGE_FORWARDED, CAMEL_MESSAGE_FORWARDED, NULL, NULL); + if (uids && uids->pdata[i]) { + struct emcs_t *emcs; + + emcs = g_object_get_data (G_OBJECT (composer), "emcs"); + emcs_set_folder_info (emcs, folder, uids->pdata[i], CAMEL_MESSAGE_FORWARDED, CAMEL_MESSAGE_FORWARDED); + } composer_set_no_change (composer, TRUE); @@ -1315,8 +1325,6 @@ redirect_get_composer (CamelMimeMessage *message) composer = e_msg_composer_new_redirect (message, account ? account->name : NULL); - em_composer_utils_setup_default_callbacks (composer); - return composer; } @@ -1559,7 +1567,8 @@ em_utils_send_receipt (CamelFolder *folder, CamelMimeMessage *message) } /* Send the receipt */ - out_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX); + out_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_OUTBOX); info = camel_message_info_new (NULL); camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN); mail_append_mail (out_folder, receipt, info, em_utils_receipt_done, NULL); @@ -1655,7 +1664,7 @@ em_utils_forward_message_raw (CamelFolder *folder, CamelMimeMessage *message, co g_free (subject); /* and send it */ - out_folder = mail_component_get_folder (NULL, MAIL_COMPONENT_FOLDER_OUTBOX); + out_folder = e_mail_shell_module_get_folder (mail_shell_module, E_MAIL_FOLDER_OUTBOX); info = camel_message_info_new (NULL); camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN); mail_append_mail (out_folder, forward, info, emu_forward_raw_done, NULL); @@ -1671,10 +1680,10 @@ generate_account_hash (void) EAccountList *accounts; EIterator *iter; - accounts = mail_config_get_accounts (); + accounts = e_get_account_list (); account_hash = g_hash_table_new (camel_strcase_hash, camel_strcase_equal); - def = mail_config_get_default_account (); + def = e_get_default_account (); iter = e_list_get_iterator ((EList *) accounts); while (e_iterator_is_valid (iter)) { @@ -2323,6 +2332,7 @@ em_utils_reply_to_message(CamelFolder *folder, const char *uid, CamelMimeMessage guint32 flags; EMEvent *eme; EMEventTargetMessage *target; + struct emcs_t *emcs; if (folder && uid && message == NULL) { struct _reply_data *rd = g_malloc0(sizeof(*rd)); @@ -2387,7 +2397,8 @@ em_utils_reply_to_message(CamelFolder *folder, const char *uid, CamelMimeMessage composer_set_body (composer, message, source); - em_composer_utils_setup_callbacks (composer, folder, uid, flags, flags, NULL, NULL); + emcs = g_object_get_data (G_OBJECT (composer), "emcs"); + emcs_set_folder_info (emcs, folder, uid, flags, flags); composer_set_no_change (composer, TRUE); @@ -2411,6 +2422,7 @@ post_reply_to_message (CamelFolder *folder, const char *uid, CamelMimeMessage *m char *real_uid; guint32 flags; GList *list = NULL; + struct emcs_t *emcs; if (message == NULL) return; @@ -2486,7 +2498,8 @@ post_reply_to_message (CamelFolder *folder, const char *uid, CamelMimeMessage *m composer_set_body (composer, message, NULL); - em_composer_utils_setup_callbacks (composer, real_folder, real_uid, flags, flags, NULL, NULL); + emcs = g_object_get_data (G_OBJECT (composer), "emcs"); + emcs_set_folder_info (emcs, real_folder, real_uid, flags, flags); composer_set_no_change (composer, TRUE); @@ -2514,3 +2527,106 @@ em_utils_post_reply_to_message_by_uid (CamelFolder *folder, const char *uid) mail_get_message (folder, uid, post_reply_to_message, NULL, mail_msg_unordered_push); } + +static void +post_header_clicked_cb (EComposerPostHeader *header, + EShellModule *shell_module) +{ + EMFolderTreeModel *model; + GtkWidget *folder_tree; + GtkWidget *dialog; + GList *list; + + model = e_mail_shell_module_get_folder_tree_model (shell_module); + folder_tree = em_folder_tree_new_with_model (model); + + em_folder_tree_set_multiselect ( + EM_FOLDER_TREE (folder_tree), TRUE); + em_folder_tree_set_excluded ( + EM_FOLDER_TREE (folder_tree), + EMFT_EXCLUDE_NOSELECT | + EMFT_EXCLUDE_VIRTUAL | + EMFT_EXCLUDE_VTRASH); + + dialog = em_folder_selector_new ( + EM_FOLDER_TREE (folder_tree), + EM_FOLDER_SELECTOR_CAN_CREATE, + _("Posting destination"), + _("Choose folders to post the message to."), + NULL); + + list = e_composer_post_header_get_folders (header); + em_folder_selector_set_selected_list ( + EM_FOLDER_SELECTOR (dialog), list); + g_list_foreach (list, (GFunc) g_free, NULL); + g_list_free (list); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) { + /* Prevent the header's "custom" flag from being reset, + * which is what the default method will do next. */ + g_signal_stop_emission_by_name (header, "clicked"); + goto exit; + } + + list = em_folder_selector_get_selected_uris ( + EM_FOLDER_SELECTOR (dialog)); + e_composer_post_header_set_folders (header, list); + g_list_foreach (list, (GFunc) g_free, NULL); + g_list_free (list); + +exit: + gtk_widget_destroy (dialog); +} + +/** + * em_configure_new_composer: + * @composer: a newly created #EMsgComposer + * + * Integrates a newly created #EMsgComposer into the mail module. The + * composer can't link directly to the mail module without introducing + * circular library dependencies, so this function finishes configuring + * things the #EMsgComposer instance can't do itself. + **/ +void +em_configure_new_composer (EMsgComposer *composer) +{ + EComposerHeaderTable *table; + EComposerHeaderType header_type; + EComposerHeader *header; + struct emcs_t *emcs; + + g_return_if_fail (E_IS_MSG_COMPOSER (composer)); + + header_type = E_COMPOSER_HEADER_POST_TO; + table = e_msg_composer_get_header_table (composer); + header = e_composer_header_table_get_header (table, header_type); + + emcs = emcs_new (); + + g_object_set_data_full ( + G_OBJECT (composer), "emcs", emcs, + (GDestroyNotify) emcs_unref); + + g_signal_connect ( + composer, "send", + G_CALLBACK (em_utils_composer_send_cb), NULL); + + g_signal_connect ( + composer, "save-draft", + G_CALLBACK (em_utils_composer_save_draft_cb), NULL); + + g_signal_connect ( + composer, "print", + G_CALLBACK (em_utils_composer_print_cb), NULL); + + /* Handle "Post To:" button clicks, which displays a folder tree + * widget. The composer doesn't know about folder tree widgets, + * so it can't handle this itself. + * + * Note: This is a G_SIGNAL_RUN_LAST signal, which allows us to + * stop the signal emission if the user cancels or closes + * the folder selector dialog. See the handler function. */ + g_signal_connect ( + header, "clicked", + G_CALLBACK (post_header_clicked_cb), mail_shell_module); +} diff --git a/mail/em-composer-utils.h b/mail/em-composer-utils.h index d17a98caa3..00e7a10395 100644 --- a/mail/em-composer-utils.h +++ b/mail/em-composer-utils.h @@ -38,14 +38,6 @@ struct _EMsgComposer; struct _EMFormat; struct _EAccount; -void em_composer_utils_setup_callbacks (struct _EMsgComposer *composer, struct _CamelFolder *folder, const char *uid, - guint32 flags, guint32 set, struct _CamelFolder *drafts, const char *drafts_uid); - -#define em_composer_utils_setup_default_callbacks(composer) em_composer_utils_setup_callbacks (composer, NULL, NULL, 0, 0, NULL, NULL) - -void em_utils_composer_send_cb(struct _EMsgComposer *composer, gpointer user_data); -void em_utils_composer_save_draft_cb(struct _EMsgComposer *composer, gpointer user_data); - void em_utils_compose_new_message (const char *fromuri); /* FIXME: mailto? url? should make up its mind what its called. imho use 'uri' */ @@ -81,6 +73,8 @@ void em_utils_reply_to_message (struct _CamelFolder *, const char *uid, struct _ void em_utils_post_reply_to_message_by_uid (struct _CamelFolder *folder, const char *uid); +void em_configure_new_composer (struct _EMsgComposer *composer); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/mail/em-filter-folder-element.c b/mail/em-filter-folder-element.c index a95a4dd88d..b4b098b4b6 100644 --- a/mail/em-filter-folder-element.c +++ b/mail/em-filter-folder-element.c @@ -33,11 +33,12 @@ #include "em-filter-folder-element.h" #include "mail/em-folder-selection-button.h" -#include "mail/mail-component.h" #include "mail/em-utils.h" #include "libedataserver/e-sexp.h" #include "e-util/e-error.h" +#include "e-mail-shell-module.h" + #define d(x) static gboolean validate(FilterElement *fe); @@ -248,6 +249,7 @@ static GtkWidget * get_widget(FilterElement *fe) { EMFilterFolderElement *ff = (EMFilterFolderElement *)fe; + EMFolderTreeModel *model; GtkWidget *button; char *uri; @@ -255,7 +257,8 @@ get_widget(FilterElement *fe) uri = ff->uri; else uri = em_uri_to_camel (ff->uri); - button = em_folder_selection_button_new(_("Select Folder"), NULL); + model = e_mail_shell_module_get_folder_tree_model (mail_shell_module); + button = em_folder_selection_button_new (model, _("Select Folder"), NULL); em_folder_selection_button_set_selection(EM_FOLDER_SELECTION_BUTTON(button), uri); if (!ff->store_camel_uri) diff --git a/mail/em-folder-browser.c b/mail/em-folder-browser.c index 58e42a5834..bfc69f9132 100644 --- a/mail/em-folder-browser.c +++ b/mail/em-folder-browser.c @@ -58,13 +58,6 @@ #include <camel/camel-vee-store.h> #include <camel/camel-operation.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 <bonobo/bonobo-ui-util.h> - /* for efilterbar stuff */ #include <libedataserver/e-sexp.h> #include "mail-vfolder.h" @@ -147,7 +140,6 @@ static void emfb_search_menu_activated(ESearchBar *esb, int id, EMFolderBrowser static void emfb_search_search_activated(ESearchBar *esb, EMFolderBrowser *emfb); static void emfb_search_search_cleared(ESearchBar *esb); -static int emfb_list_key_press(ETree *tree, int row, ETreePath path, int col, GdkEvent *ev, EMFolderBrowser *emfb); static void emfb_list_message_selected (MessageList *ml, const char *uid, EMFolderBrowser *emfb); static void emfb_expand_all_threads(BonoboUIComponent *uid, void *data, const char *path); @@ -213,29 +205,6 @@ enum { /* label IDs are set above this number */ #define VIEW_ITEMS_MASK 63 -/* Options for View */ -static EMFBSearchBarItem emfb_view_items[] = { - {{ N_("All Messages"), VIEW_ALL_MESSAGES, 0 }, NULL}, - {{ N_("Unread Messages"), VIEW_UNREAD_MESSAGES, 0 }, "mail-unread"}, - {{ NULL, 0, 0 }, NULL}, - {{ N_("No Label"),VIEW_NO_LABEL, 0 }, NULL}, - {{ NULL, -1, 0 }, NULL} -}; - -/* TODO: Following options should be customizable */ -static EMFBSearchBarItem temp_view_items[] = { - {{ NULL, 0, 0 }, NULL}, - {{ N_("Read Messages"), VIEW_READ_MESSAGES, 0 }, "mail-read"}, - {{ N_("Recent Messages"), VIEW_RECENT_MESSAGES, 0 }, NULL}, - {{ N_("Last 5 Days' Messages"), VIEW_LAST_FIVE_DAYS, 0 }, NULL}, - {{ N_("Messages with Attachments"), VIEW_WITH_ATTACHMENTS, 0 }, "mail-attachment"}, - {{ N_("Important Messages"), VIEW_MESSAGES_MARKED_AS_IMPORTANT, 0}, "emblem-important"}, - {{ N_("Messages Not Junk"), VIEW_NOT_JUNK, 0 }, "mail-mark-notjunk"}, -/* { NULL, 0, NULL }, */ -/* { N_("Customize"), NOT_IMPLEMENTED, NULL }, */ - {{ NULL, -1, 0 }, NULL} -}; - static ESearchBarItem emfb_search_scope_items[] = { E_FILTERBAR_CURRENT_FOLDER, E_FILTERBAR_CURRENT_ACCOUNT, @@ -246,197 +215,6 @@ static ESearchBarItem emfb_search_scope_items[] = { static EMFolderViewClass *emfb_parent; -/* Needed since the paned wont take the position its given otherwise ... */ -static void -emfb_pane_realised(GtkWidget *w, EMFolderBrowser *emfb) -{ - GConfClient *gconf; - - gconf = mail_config_get_gconf_client (); - - if (emfb->priv->show_wide) - gtk_paned_set_position((GtkPaned *)emfb->vpane, gconf_client_get_int(gconf, "/apps/evolution/mail/display/hpaned_size", NULL)); - else - gtk_paned_set_position((GtkPaned *)emfb->vpane, gconf_client_get_int(gconf, "/apps/evolution/mail/display/paned_size", NULL)); -} - -static gboolean -emfb_pane_button_release_event(GtkWidget *w, GdkEventButton *e, EMFolderBrowser *emfb) -{ - GConfClient *gconf = mail_config_get_gconf_client (); - - if (GTK_WIDGET_REALIZED (w)) { - if (emfb->priv->show_wide) - gconf_client_set_int(gconf, "/apps/evolution/mail/display/hpaned_size", - gtk_paned_get_position(GTK_PANED(w)), NULL); - else - gconf_client_set_int(gconf, "/apps/evolution/mail/display/paned_size", - gtk_paned_get_position(GTK_PANED(w)), NULL); - - } - - return FALSE; -} - -static void -free_one_ui_file (gpointer data, - gpointer user_data) -{ - g_free (data); -} - -static GtkWidget * -generate_viewoption_menu (GtkWidget *emfv) -{ - GtkWidget *menu, *menu_item; - gint i = 0; - GSList *l; - - menu = gtk_menu_new (); - - for (i = 0; emfb_view_items[i].search.id != -1; ++i) { - if (emfb_view_items[i].search.text) { - char *str; - - str = e_str_without_underscores (_(emfb_view_items[i].search.text)); - menu_item = gtk_image_menu_item_new_with_label (str); - if (emfb_view_items[i].image) { - GtkWidget *image; - - image = gtk_image_new_from_icon_name ( - emfb_view_items[i].image, - GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image ( - GTK_IMAGE_MENU_ITEM (menu_item), - image); - } - g_free (str); - } else { - menu_item = gtk_menu_item_new (); - gtk_widget_set_sensitive (menu_item, FALSE); - } - - g_object_set_data (G_OBJECT (menu_item), "EsbItemId", - GINT_TO_POINTER (emfb_view_items[i].search.id)); - - gtk_widget_show (menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - } - - /* Add the labels */ - for (l = mail_config_get_labels (), i = 0; l; l = l->next, i++) { - EUtilLabel *label = l->data; - if (label->name && *(label->name)) { - char *str; - GdkPixmap *pixmap; - GdkColor colour; - GdkGC *gc; - GtkWidget *image; - - gdk_color_parse(label->colour, &colour); - gdk_colormap_alloc_color(gdk_colormap_get_system(), &colour, FALSE, TRUE); - - pixmap = gdk_pixmap_new(((GtkWidget *)emfv)->window, 16, 16, -1); - gc = gdk_gc_new(((GtkWidget *)emfv)->window); - gdk_gc_set_foreground(gc, &colour); - gdk_draw_rectangle(pixmap, gc, TRUE, 0, 0, 16, 16); - g_object_unref(gc); - - image = gtk_image_new_from_pixmap(pixmap, NULL); - str = e_str_without_underscores (label->name); - menu_item = gtk_image_menu_item_new_with_label (str); - g_free (str); - gtk_image_menu_item_set_image ((GtkImageMenuItem *)menu_item, image); - g_object_set_data (G_OBJECT (menu_item), "EsbItemId", - GINT_TO_POINTER (VIEW_LABEL + (VIEW_ITEMS_MASK + 1) * i)); - - g_object_set_data_full (G_OBJECT (menu_item), "LabelTag", - g_strdup (strncmp (label->tag, "$Label", 6) == 0 ? label->tag + 6 : label->tag), - g_free); - } - - gtk_widget_show (menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - } - - for (i = 0; temp_view_items[i].search.id != -1; ++i) { - if (temp_view_items[i].search.text) { - char *str; - str = e_str_without_underscores (_(temp_view_items[i].search.text)); - menu_item = gtk_image_menu_item_new_with_label (str); - if (temp_view_items[i].image) { - GtkWidget *image; - - image = gtk_image_new_from_icon_name ( - temp_view_items[i].image, - GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image ( - GTK_IMAGE_MENU_ITEM (menu_item), - image); - } - g_free (str); - } else { - menu_item = gtk_menu_item_new (); - gtk_widget_set_sensitive (menu_item, FALSE); - } - - g_object_set_data (G_OBJECT (menu_item), "EsbItemId", - GINT_TO_POINTER (temp_view_items[i].search.id)); - - gtk_widget_show (menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - } - - return menu; -} - -#if 0 -static GArray * -viewoption_menu_generator () -{ - GArray *menu = g_array_new (FALSE, FALSE, sizeof (ESearchBarItem)); - gint i = 0; - ESearchBarItem dup_item; - GSList *l; - - for (i = 0; emfb_view_items[i].search.id != -1; i++) - g_array_append_vals (menu, &emfb_view_items[i], 1); - - for (l = mail_config_get_labels (); l; l = l->next) { - ESearchBarItem item; - EUtilLabel *label = l->data; - - item.text = label->name; - item.id = VIEW_LABEL; - - g_array_append_vals (menu, &item, 1); - } - - dup_item.id = -1; - dup_item.text = NULL; - g_array_append_vals (menu, &dup_item, 1); - - return menu; -} -#endif - -static void -emfb_realize (GtkWidget *widget) -{ - GtkWidget *menu; - EMFolderBrowser *emfb = (EMFolderBrowser *)widget; - int id; - - menu = generate_viewoption_menu (widget); - id = e_search_bar_get_viewitem_id (E_SEARCH_BAR (emfb->search)); - - e_search_bar_set_viewoption_menu (E_SEARCH_BAR (emfb->search), menu); - - /* restore last selected ID, if any */ - if (id != -1) - e_search_bar_set_viewitem_id (E_SEARCH_BAR (emfb->search), id); -} - static void html_scroll (GtkHTML *html, GtkOrientation orientation, @@ -457,29 +235,6 @@ html_scroll (GtkHTML *html, } } -static gboolean -labels_changed_idle_cb (gpointer user_data) -{ - EMFolderBrowser *emfb = (EMFolderBrowser*) user_data; - - emfb_realize (GTK_WIDGET (emfb)); - - emfb->priv->labels_change_idle_id = 0; - - return FALSE; -} - -static void -gconf_labels_changed (GConfClient *client, guint cnxn_id, - GConfEntry *entry, gpointer user_data) -{ - EMFolderBrowser *emfb = (EMFolderBrowser*) user_data; - - /* regenerate menu option whenever something changed in labels */ - if (emfb && !emfb->priv->labels_change_idle_id) - emfb->priv->labels_change_idle_id = g_idle_add (labels_changed_idle_cb, emfb); -} - static void emfb_init(GObject *o) { @@ -497,78 +252,78 @@ emfb_init(GObject *o) g_signal_connect_after (((EMFormatHTML *)(emfb->view.preview))->html, "scroll", G_CALLBACK (html_scroll), emfb); - g_slist_foreach (emfb->view.ui_files, free_one_ui_file, NULL); - g_slist_free(emfb->view.ui_files); - - emfb->view.ui_files = g_slist_append(NULL, - g_build_filename (EVOLUTION_UIDIR, - "evolution-mail-global.xml", - NULL)); - emfb->view.ui_files = g_slist_append(emfb->view.ui_files, - g_build_filename (EVOLUTION_UIDIR, - "evolution-mail-list.xml", - NULL)); - emfb->view.ui_files = g_slist_append(emfb->view.ui_files, - g_build_filename (EVOLUTION_UIDIR, - "evolution-mail-message.xml", - NULL)); +// g_slist_foreach (emfb->view.ui_files, free_one_ui_file, NULL); +// g_slist_free(emfb->view.ui_files); + +// emfb->view.ui_files = g_slist_append(NULL, +// g_build_filename (EVOLUTION_UIDIR, +// "evolution-mail-global.xml", +// NULL)); +// emfb->view.ui_files = g_slist_append(emfb->view.ui_files, +// g_build_filename (EVOLUTION_UIDIR, +// "evolution-mail-list.xml", +// NULL)); +// emfb->view.ui_files = g_slist_append(emfb->view.ui_files, +// g_build_filename (EVOLUTION_UIDIR, +// "evolution-mail-message.xml", +// NULL)); emfb->view.enable_map = g_slist_prepend(emfb->view.enable_map, (void *)emfb_enable_map); - if (search_context) { - const char *systemrules = g_object_get_data (G_OBJECT (search_context), "system"); - const char *userrules = g_object_get_data (G_OBJECT (search_context), "user"); - EFilterBar *efb; - GConfClient *gconf; - - emfb->search = e_filter_bar_new(search_context, systemrules, userrules, emfb_search_config_search, emfb); - efb = (EFilterBar *)emfb->search; - efb->account_search_vf = NULL; - efb->all_account_search_vf = NULL; - efb->account_search_cancel = NULL; - e_search_bar_set_menu ((ESearchBar *)emfb->search, emfb_search_items); - e_search_bar_set_scopeoption ((ESearchBar *)emfb->search, emfb_search_scope_items); - e_search_bar_scope_enable ((ESearchBar *)emfb->search, E_FILTERBAR_CURRENT_MESSAGE_ID, FALSE); - emfb->priv->scope_restricted = TRUE; - g_signal_connect(emfb, "realize", G_CALLBACK(emfb_realize), NULL); - gtk_widget_show((GtkWidget *)emfb->search); - - p->search_menu_activated_id = g_signal_connect(emfb->search, "menu_activated", G_CALLBACK(emfb_search_menu_activated), emfb); - p->search_activated_id = g_signal_connect(emfb->search, "search_activated", G_CALLBACK(emfb_search_search_activated), emfb); - g_signal_connect(emfb->search, "search_cleared", G_CALLBACK(emfb_search_search_cleared), NULL); - - gtk_box_pack_start((GtkBox *)emfb, (GtkWidget *)emfb->search, FALSE, TRUE, 0); - - gconf = mail_config_get_gconf_client (); - emfb->priv->labels_change_notify_id = gconf_client_notify_add (gconf, E_UTIL_LABELS_GCONF_KEY, gconf_labels_changed, emfb, NULL, NULL); - } - - emfb->priv->show_wide = gconf_client_get_bool(mail_config_get_gconf_client(), "/apps/evolution/mail/display/show_wide", NULL); - emfb->vpane = emfb->priv->show_wide?gtk_hpaned_new():gtk_vpaned_new(); - - g_signal_connect(emfb->vpane, "realize", G_CALLBACK(emfb_pane_realised), emfb); - emfb->priv->vpane_resize_id = g_signal_connect(emfb->vpane, "button_release_event", G_CALLBACK(emfb_pane_button_release_event), emfb); - - gtk_widget_show(emfb->vpane); - - gtk_box_pack_start((GtkBox *)emfb, emfb->vpane, TRUE, TRUE, 0); - - gtk_paned_pack1 (GTK_PANED (emfb->vpane), GTK_WIDGET (emfb->view.list), FALSE, FALSE); - gtk_widget_show((GtkWidget *)emfb->view.list); - - /* currently: just use a scrolledwindow for preview widget */ - p->scroll = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy((GtkScrolledWindow *)p->scroll, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type((GtkScrolledWindow *)p->scroll, GTK_SHADOW_IN); - gtk_widget_show(p->scroll); - - p->preview = gtk_vbox_new (FALSE, 6); - gtk_container_add((GtkContainer *)p->scroll, (GtkWidget *)emfb->view.preview->formathtml.html); - gtk_widget_show((GtkWidget *)emfb->view.preview->formathtml.html); - gtk_box_pack_start ((GtkBox *)p->preview, p->scroll, TRUE, TRUE, 0); - gtk_box_pack_start ((GtkBox *)p->preview, em_format_html_get_search_dialog (emfb->view.preview), FALSE, FALSE, 0); - gtk_paned_pack2 (GTK_PANED (emfb->vpane), p->preview, TRUE, FALSE); - gtk_widget_show(p->preview); +// if (search_context) { +// const char *systemrules = g_object_get_data (G_OBJECT (search_context), "system"); +// const char *userrules = g_object_get_data (G_OBJECT (search_context), "user"); +// EFilterBar *efb; +// GConfClient *gconf; +// +// emfb->search = e_filter_bar_new(search_context, systemrules, userrules, emfb_search_config_search, emfb); +// efb = (EFilterBar *)emfb->search; +// efb->account_search_vf = NULL; +// efb->all_account_search_vf = NULL; +// efb->account_search_cancel = NULL; +// e_search_bar_set_menu ((ESearchBar *)emfb->search, emfb_search_items); +// e_search_bar_set_scopeoption ((ESearchBar *)emfb->search, emfb_search_scope_items); +// e_search_bar_scope_enable ((ESearchBar *)emfb->search, E_FILTERBAR_CURRENT_MESSAGE_ID, FALSE); +// emfb->priv->scope_restricted = TRUE; +// g_signal_connect(emfb, "realize", G_CALLBACK(emfb_realize), NULL); +// gtk_widget_show((GtkWidget *)emfb->search); +// +// p->search_menu_activated_id = g_signal_connect(emfb->search, "menu_activated", G_CALLBACK(emfb_search_menu_activated), emfb); +// p->search_activated_id = g_signal_connect(emfb->search, "search_activated", G_CALLBACK(emfb_search_search_activated), emfb); +// g_signal_connect(emfb->search, "search_cleared", G_CALLBACK(emfb_search_search_cleared), NULL); +// +// gtk_box_pack_start((GtkBox *)emfb, (GtkWidget *)emfb->search, FALSE, TRUE, 0); +// +// gconf = mail_config_get_gconf_client (); +// emfb->priv->labels_change_notify_id = gconf_client_notify_add (gconf, E_UTIL_LABELS_GCONF_KEY, gconf_labels_changed, emfb, NULL, NULL); +// } +// +// emfb->priv->show_wide = gconf_client_get_bool(mail_config_get_gconf_client(), "/apps/evolution/mail/display/show_wide", NULL); +// emfb->vpane = emfb->priv->show_wide?gtk_hpaned_new():gtk_vpaned_new(); +// +// g_signal_connect(emfb->vpane, "realize", G_CALLBACK(emfb_pane_realised), emfb); +// emfb->priv->vpane_resize_id = g_signal_connect(emfb->vpane, "button_release_event", G_CALLBACK(emfb_pane_button_release_event), emfb); +// +// gtk_widget_show(emfb->vpane); +// +// gtk_box_pack_start_defaults((GtkBox *)emfb, emfb->vpane); +// +// gtk_paned_pack1 (GTK_PANED (emfb->vpane), GTK_WIDGET (emfb->view.list), FALSE, FALSE); +// gtk_widget_show((GtkWidget *)emfb->view.list); +// +// /* currently: just use a scrolledwindow for preview widget */ +// p->scroll = gtk_scrolled_window_new(NULL, NULL); +// gtk_scrolled_window_set_policy((GtkScrolledWindow *)p->scroll, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); +// gtk_scrolled_window_set_shadow_type((GtkScrolledWindow *)p->scroll, GTK_SHADOW_IN); +// gtk_widget_show(p->scroll); +// +// p->preview = gtk_vbox_new (FALSE, 6); +// gtk_container_add((GtkContainer *)p->scroll, (GtkWidget *)emfb->view.preview->formathtml.html); +// gtk_widget_show((GtkWidget *)emfb->view.preview->formathtml.html); +// gtk_box_pack_start ((GtkBox *)p->preview, p->scroll, TRUE, TRUE, 0); +// gtk_box_pack_start ((GtkBox *)p->preview, em_format_html_get_search_dialog (emfb->view.preview), FALSE, FALSE, 0); +// gtk_paned_pack2 (GTK_PANED (emfb->vpane), p->preview, TRUE, FALSE); +// gtk_widget_show(p->preview); /** @HookPoint-EMFolderBrower: Folder Browser * @Id: emfb.created @@ -581,23 +336,11 @@ emfb_init(GObject *o) e_event_emit((EEvent *)eme, "emfb.created", (EEventTarget *)target); - g_signal_connect (((EMFolderView *) emfb)->list->tree, "key_press", G_CALLBACK(emfb_list_key_press), emfb); g_signal_connect (((EMFolderView *) emfb)->list, "message_selected", G_CALLBACK (emfb_list_message_selected), emfb); } static void -emfb_finalise(GObject *o) -{ - EMFolderBrowser *emfb = (EMFolderBrowser *)o; - - g_free (emfb->priv->select_uid); - g_free (emfb->priv); - - ((GObjectClass *)emfb_parent)->finalize(o); -} - -static void emfb_destroy(GtkObject *o) { EMFolderBrowser *emfb = (EMFolderBrowser *)o; @@ -617,8 +360,8 @@ emfb_destroy(GtkObject *o) emfb->priv->idle_scroll_id = 0; } - if (emfb->view.folder && emfb->priv->folder_changed_id) - camel_object_remove_event(emfb->view.folder, emfb->priv->folder_changed_id); +// if (emfb->view.folder && emfb->priv->folder_changed_id) +// camel_object_remove_event(emfb->view.folder, emfb->priv->folder_changed_id); if (emfb->priv->labels_change_notify_id) { GConfClient *gconf = mail_config_get_gconf_client (); @@ -638,75 +381,6 @@ emfb_destroy(GtkObject *o) ((GtkObjectClass *)emfb_parent)->destroy(o); } -static void -emfb_class_init(GObjectClass *klass) -{ - klass->finalize = emfb_finalise; - - folder_browser_signals[ACCOUNT_SEARCH_ACTIVATED] = - g_signal_new ("account_search_activated", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EMFolderBrowserClass, account_search_activated), - NULL, - NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - folder_browser_signals[ACCOUNT_SEARCH_CLEARED] = - g_signal_new ("account_search_cleared", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EMFolderBrowserClass, account_search_cleared), - NULL, - NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - - ((GtkObjectClass *)klass)->destroy = emfb_destroy; - ((EMFolderViewClass *)klass)->set_folder = emfb_set_folder; - ((EMFolderViewClass *)klass)->activate = emfb_activate; -} - -GType -em_folder_browser_get_type(void) -{ - static GType type = 0; - - if (type == 0) { - static const GTypeInfo info = { - sizeof(EMFolderBrowserClass), - NULL, NULL, - (GClassInitFunc)emfb_class_init, - NULL, NULL, - sizeof(EMFolderBrowser), 0, - (GInstanceInitFunc)emfb_init - }; - emfb_parent = g_type_class_ref(em_folder_view_get_type()); - type = g_type_register_static(em_folder_view_get_type(), "EMFolderBrowser", &info, 0); - } - - return type; -} - -GtkWidget *em_folder_browser_new(void) -{ - EMFolderBrowser *emfb = g_object_new(em_folder_browser_get_type(), 0); - - /** @HookPoint-EMMenu: Main Mail Menu - * @Id: org.gnome.evolution.mail.browser - * @Class: org.gnome.evolution.mail.bonobomenu:1.0 - * @Target: EMMenuTargetSelect - * - * The main menu of mail view of the main application window. - * If the folder is NULL (not selected), the target will be empty, not NULL. - */ - ((EMFolderView *)emfb)->menu = em_menu_new("org.gnome.evolution.mail.browser"); - - return (GtkWidget *)emfb; -} - void em_folder_browser_show_preview(EMFolderBrowser *emfb, gboolean state) { if ((emfb->view.preview_active ^ state) == 0 @@ -765,42 +439,6 @@ gboolean em_folder_browser_get_wide (EMFolderBrowser *emfb) return emfb->priv->show_wide; } -void em_folder_browser_show_wide(EMFolderBrowser *emfb, gboolean state) -{ - GtkWidget *w; - int paned_size; - - if ((emfb->priv->show_wide && state) - || emfb->view.list == NULL) { - emfb->priv->show_wide = state; - return; - } - - emfb->priv->show_wide = state; - - w = emfb->priv->show_wide?gtk_hpaned_new():gtk_vpaned_new(); - - g_signal_handler_disconnect(emfb->vpane, emfb->priv->vpane_resize_id); - g_signal_connect(w, "realize", G_CALLBACK(emfb_pane_realised), emfb); - emfb->priv->vpane_resize_id = g_signal_connect(w, "button_release_event", G_CALLBACK(emfb_pane_button_release_event), emfb); - - gtk_box_pack_start((GtkBox *)emfb, w, TRUE, TRUE, 0); - gtk_widget_reparent((GtkWidget *)emfb->view.list, w); - gtk_widget_reparent((GtkWidget *)emfb->priv->preview, w); - gtk_widget_destroy(emfb->vpane); - gtk_container_child_set (GTK_CONTAINER (w), GTK_WIDGET (emfb->view.list), "resize", FALSE, "shrink", FALSE, NULL); - gtk_container_child_set (GTK_CONTAINER (w), GTK_WIDGET (emfb->priv->preview), "resize", TRUE, "shrink", FALSE, NULL); - gtk_container_resize_children ((GtkContainer *)w); - emfb->vpane = w; - gtk_widget_show(w); - - paned_size = gconf_client_get_int(mail_config_get_gconf_client(), emfb->priv->show_wide ? "/apps/evolution/mail/display/hpaned_size":"/apps/evolution/mail/display/paned_size", NULL); - gtk_paned_set_position (GTK_PANED (emfb->vpane), paned_size); - - if (((EMFolderView *)emfb)->folder) - em_folder_view_setup_view_instance ((EMFolderView *) emfb); -} - /* ********************************************************************** */ /* FIXME: Need to separate system rules from user ones */ @@ -838,152 +476,6 @@ emfb_search_menu_activated(ESearchBar *esb, int id, EMFolderBrowser *emfb) } } -static void -emfb_search_config_search(EFilterBar *efb, FilterRule *rule, int id, const char *query, void *data) -{ - EMFolderBrowser *emfb = data; - GList *partl; - struct _camel_search_words *words; - int i; - GSList *strings = NULL; - - /* we scan the parts of a rule, and set all the types we know about to the query string */ - partl = rule->parts; - while (partl) { - FilterPart *part = partl->data; - - if (!strcmp(part->name, "subject")) { - FilterInput *input = (FilterInput *)filter_part_find_element(part, "subject"); - if (input) - filter_input_set_value(input, query); - } else if (!strcmp(part->name, "body")) { - FilterInput *input = (FilterInput *)filter_part_find_element(part, "word"); - if (input) - filter_input_set_value(input, query); - - words = camel_search_words_split((unsigned char *)query); - for (i=0;i<words->len;i++) - strings = g_slist_prepend(strings, g_strdup(words->words[i]->word)); - camel_search_words_free (words); - } else if(!strcmp(part->name, "sender")) { - FilterInput *input = (FilterInput *)filter_part_find_element(part, "sender"); - if (input) - filter_input_set_value(input, query); - } else if(!strcmp(part->name, "to")) { - FilterInput *input = (FilterInput *)filter_part_find_element(part, "recipient"); - if (input) - filter_input_set_value(input, query); - } - - partl = partl->next; - } - - em_format_html_display_set_search(emfb->view.preview, - EM_FORMAT_HTML_DISPLAY_SEARCH_SECONDARY|EM_FORMAT_HTML_DISPLAY_SEARCH_ICASE, - strings); - while (strings) { - GSList *n = strings->next; - g_free(strings->data); - g_slist_free_1(strings); - strings = n; - } -} - -static char * -get_view_query (ESearchBar *esb, CamelFolder *folder, const char *folder_uri) -{ - char *view_sexp = NULL; - gint id; - GtkWidget *menu_item; - char *tag; - gboolean duplicate = TRUE; - - /* Get the current selected view */ - id = e_search_bar_get_viewitem_id (esb); - menu_item = e_search_bar_get_selected_viewitem (esb); - - switch (id & VIEW_ITEMS_MASK) { - case VIEW_ALL_MESSAGES: - /* one space indicates no filtering */ - view_sexp = " "; - break; - - /* README: All the sexp below are not rocket science but it is not straightforward as well. - I believe it is better to document the assumptions and the conventions followed for the sexp, - before I forget so that no one else again needs to read through the code -- Sankar */ - - case VIEW_UNREAD_MESSAGES: - view_sexp = "(match-all (not (system-flag \"Seen\")))"; - break; - case VIEW_READ_MESSAGES: - view_sexp = "(match-all (system-flag \"Seen\" ))"; - break; - case VIEW_RECENT_MESSAGES: - if (!em_utils_folder_is_sent (folder, folder_uri)) - view_sexp = "(match-all (> (get-received-date) (- (get-current-date) 86400)))"; - else - view_sexp = "(match-all (> (get-sent-date) (- (get-current-date) 86400)))"; - break; - case VIEW_LAST_FIVE_DAYS: - if (!em_utils_folder_is_sent (folder, folder_uri)) - view_sexp = " (match-all (> (get-received-date) (- (get-current-date) 432000)))"; - else - view_sexp = " (match-all (> (get-sent-date) (- (get-current-date) 432000)))"; - break; - case VIEW_WITH_ATTACHMENTS: - view_sexp = "(match-all (system-flag \"Attachments\" ))"; - break; - case VIEW_NOT_JUNK: - view_sexp = "(match-all (not (system-flag \"junk\")))"; - break; - case VIEW_NO_LABEL: { - GSList *l; - GString *s = g_string_new ("(and"); - - for (l = mail_config_get_labels (); l; l = l->next) { - EUtilLabel *label = (EUtilLabel *)l->data; - - if (label && label->tag) { - const gchar *tag = label->tag; - - if (strncmp (tag, "$Label", 6) == 0) - tag += 6; - - g_string_append_printf (s, " (match-all (not (or (= (user-tag \"label\") \"%s\") (user-flag \"$Label%s\") (user-flag \"%s\"))))", tag, tag, tag); - /* FIXME: I dont see a way of mapping this kind of sexp into sql atm. I guess this option could be kicked out */ - /* May be we should copy what I did for system flags -- Sankar */ - } - } - - g_string_append (s, ")"); - - duplicate = FALSE; - view_sexp = g_string_free (s, FALSE); - } break; - case VIEW_LABEL: - tag = (char *)g_object_get_data (G_OBJECT (menu_item), "LabelTag"); - view_sexp = g_strdup_printf ("(match-all (or (= (user-tag \"label\") \"%s\") (user-flag \"$Label%s\") (user-flag \"%s\")))", tag, tag, tag); - duplicate = FALSE; - break; - case VIEW_MESSAGES_MARKED_AS_IMPORTANT: - view_sexp = "(match-all (system-flag \"Flagged\" ))"; - break; - case VIEW_ANY_FIELD_CONTAINS: - break; - - case VIEW_CUSTOMIZE: - /* one space indicates no filtering, so here use two */ - view_sexp = " "; - break; - } - - if (duplicate) - view_sexp = g_strdup (view_sexp); - - return view_sexp; -} - - struct _setup_msg { MailMsg base; @@ -1324,60 +816,6 @@ emfb_search_search_cleared(ESearchBar *esb) /* ********************************************************************** */ -static int -emfb_list_key_press(ETree *tree, int row, ETreePath path, int col, GdkEvent *ev, EMFolderBrowser *emfb) -{ - gboolean state, folder_choose = TRUE; - if ((ev->key.state & GDK_CONTROL_MASK) != 0) - return FALSE; - - switch (ev->key.keyval) { - case GDK_space: - if (!emfb->view.preview->caret_mode && mail_config_get_enable_magic_spacebar ()) { - state = gtk_html_command(((EMFormatHTML *)((EMFolderView *) emfb)->preview)->html, "scroll-forward"); - if (!state) { - folder_choose = message_list_select(((EMFolderView *) emfb)->list, MESSAGE_LIST_SELECT_NEXT, 0, CAMEL_MESSAGE_SEEN); - if (!folder_choose) - folder_choose = message_list_select(((EMFolderView *) emfb)->list, - MESSAGE_LIST_SELECT_NEXT | MESSAGE_LIST_SELECT_WRAP, 0, CAMEL_MESSAGE_SEEN); - } - - } else - em_utils_adjustment_page(gtk_scrolled_window_get_vadjustment((GtkScrolledWindow *)emfb->priv->scroll), TRUE); - break; - case GDK_BackSpace: - if (!emfb->view.preview->caret_mode && mail_config_get_enable_magic_spacebar ()) { - state = gtk_html_command(((EMFormatHTML *)((EMFolderView *) emfb)->preview)->html, "scroll-backward"); - if (!state) { - folder_choose = message_list_select(((EMFolderView *) emfb)->list, MESSAGE_LIST_SELECT_PREVIOUS, 0, CAMEL_MESSAGE_SEEN); - if (!folder_choose) - folder_choose = message_list_select(((EMFolderView *) emfb)->list, - MESSAGE_LIST_SELECT_PREVIOUS | MESSAGE_LIST_SELECT_WRAP, 0, CAMEL_MESSAGE_SEEN); - } - - } else - em_utils_adjustment_page(gtk_scrolled_window_get_vadjustment((GtkScrolledWindow *)emfb->priv->scroll), FALSE); - break; - default: - return FALSE; - } - - if (!folder_choose && !emfb->view.preview->caret_mode && mail_config_get_enable_magic_spacebar ()) { - //check for unread messages. if yes .. rewindback to the folder - EMFolderTree *emft = g_object_get_data((GObject*)emfb, "foldertree"); - switch (ev->key.keyval) { - case GDK_space: - em_folder_tree_select_next_path (emft, TRUE); - break; - case GDK_BackSpace: - em_folder_tree_select_prev_path (emft, TRUE); - break; - } - gtk_widget_grab_focus ((GtkWidget *)((EMFolderView *) emfb)->list); - } - return TRUE; -} - static void emfb_list_message_selected (MessageList *ml, const char *uid, EMFolderBrowser *emfb) { @@ -1403,333 +841,6 @@ emfb_list_message_selected (MessageList *ml, const char *uid, EMFolderBrowser *e /* ********************************************************************** */ static void -emfb_edit_cut(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderBrowser *emfb = data; - - /* TODO: pity we can't sucblass this method, ugh, virtualise it? */ - - if (GTK_WIDGET_HAS_FOCUS(((ESearchBar *)emfb->search)->entry)) - gtk_editable_cut_clipboard((GtkEditable *)((ESearchBar *)emfb->search)->entry); - else if (GTK_WIDGET_HAS_FOCUS(emfb->view.preview->formathtml.html)) - em_format_html_display_cut(emfb->view.preview); - else - message_list_copy(emfb->view.list, TRUE); -} - -static void -emfb_edit_copy(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderBrowser *emfb = data; - - if (GTK_WIDGET_HAS_FOCUS(((ESearchBar *)emfb->search)->entry)) - gtk_editable_copy_clipboard((GtkEditable *)((ESearchBar *)emfb->search)->entry); - else if (GTK_WIDGET_HAS_FOCUS(emfb->view.preview->formathtml.html)) - em_format_html_display_copy(emfb->view.preview); - else - message_list_copy(emfb->view.list, FALSE); -} - -static void -emfb_edit_paste(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderBrowser *emfb = data; - - if (GTK_WIDGET_HAS_FOCUS(((ESearchBar *)emfb->search)->entry)) - gtk_editable_paste_clipboard((GtkEditable *)((ESearchBar *)emfb->search)->entry); - else - message_list_paste(emfb->view.list); -} - -static void -emfb_edit_invert_selection(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderView *emfv = data; - - message_list_invert_selection(emfv->list); -} - -static gboolean -emfb_select_all_daemon (MessageList *ml) -{ - message_list_select_all(ml); - gtk_widget_grab_focus ((GtkWidget *)ml); - return FALSE; -} - -static void -emfb_edit_select_all(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderView *emfv = data; - - if (emfv->list->threaded) { - - emfb_expand_all_threads (uid, data, path); - - /* The time out below is added so that the execution thread to - expand all conversations threads would've completed. - - The timeout 505 is just to ensure that the value is a small delta - more than the timeout value in expand_all_threads thread. */ - - g_timeout_add (505, (GSourceFunc) emfb_select_all_daemon, emfv->list); - - } else { - /* If there is no threading, just select-all immediately */ - emfb_select_all_daemon (emfv->list); - } -} - -static void -emfb_edit_select_thread(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderView *emfv = data; - - message_list_select_thread(emfv->list); -} - -static void -emfb_edit_select_subthread(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderView *emfv = data; - - message_list_select_subthread (emfv->list); -} - -static void -emfb_folder_properties(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderBrowser *emfb = data; - - if (emfb->view.folder_uri) - em_folder_properties_show(NULL, emfb->view.folder, emfb->view.folder_uri); -} - -/* VIEWTHREADED*/ -static void -emfb_expand_all_threads(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderView *emfv = data; - - message_list_set_threaded_expand_all(emfv->list); - -} - -static void -emfb_collapse_all_threads(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderView *emfv = data; - - message_list_set_threaded_collapse_all(emfv->list); -} - -static void -emfb_folder_copy(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderBrowser *emfb = data; - CamelFolderInfo *fi = NULL; - CamelException ex; - - /* FIXME: This function MUST become multi-threaded. - FIXME: This interface should NOT use a folderinfo */ - - camel_exception_init (&ex); - - if ((fi = camel_store_get_folder_info (emfb->view.folder->parent_store, - emfb->view.folder->full_name, - CAMEL_STORE_FOLDER_INFO_FAST, - &ex)) != NULL) - em_folder_utils_copy_folder(fi, FALSE); - - camel_exception_clear (&ex); - - return; -} - -static void -emfb_folder_move(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderBrowser *emfb = data; - CamelFolderInfo *fi = NULL; - CamelException ex; - - camel_exception_init (&ex); - - /* FIXME: This function MUST become multi-threaded. - FIXME: This interface should NOT use a folderinfo */ - - if ((fi = camel_store_get_folder_info (emfb->view.folder->parent_store, - emfb->view.folder->full_name, - CAMEL_STORE_FOLDER_INFO_FAST, - &ex)) != NULL) - em_folder_utils_copy_folder(fi, TRUE); - - camel_exception_clear (&ex); - - return; -} - -static void -emfb_folder_delete(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderBrowser *emfb = data; - - em_folder_utils_delete_folder (emfb->view.folder); - - return; -} - -static void -emfb_folder_refresh(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderBrowser *emfb = data; - EMFolderTree *tree = g_object_get_data (G_OBJECT (emfb), "foldertree"); - CamelFolder *folder; - - if ((folder = em_folder_tree_get_selected_folder (tree)) != NULL) - mail_refresh_folder(folder, NULL, NULL); -} - - -static void -emfb_folder_rename(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderBrowser *emfb = data; - - em_folder_utils_rename_folder (emfb->view.folder); - - return; -} - -static void -emfb_folder_create(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderBrowser *emfb = data; - CamelFolderInfo *fi = NULL; - EMFolderTree *tree = g_object_get_data (G_OBJECT (emfb), "foldertree"); - - /* FIXME: This function MUST be multithreaded - FIXME: This interface should NOT use a folderinfo */ - if (emfb->view.folder) { - if ((fi = em_folder_tree_get_selected_folder_info (tree)) != NULL) { - em_folder_utils_create_folder (fi, tree, NULL); - camel_folder_info_free(fi); - } - } else { - em_folder_utils_create_folder (NULL, tree, NULL); - } - - return; -} - -static void -emfb_folder_expunge(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderBrowser *emfb = data; - - if (emfb->view.folder) - em_utils_expunge_folder(gtk_widget_get_toplevel((GtkWidget *)emfb), emfb->view.folder); -} - -static void -emfb_mark_all_read(BonoboUIComponent *uid, void *data, const char *path) -{ - /* FIXME: make a 'mark messages' function? */ - EMFolderView *emfv = data; - GPtrArray *uids; - int i; - - if (emfv->folder == NULL) - return; - if( em_utils_prompt_user((GtkWindow *)emfv, "/apps/evolution/mail/prompts/mark_all_read","mail:ask-mark-all-read", NULL)){ - uids = message_list_get_uids(emfv->list); - camel_folder_freeze(emfv->folder); - for (i=0;i<uids->len;i++) - camel_folder_set_message_flags(emfv->folder, uids->pdata[i], CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN); - camel_folder_thaw(emfv->folder); - message_list_free_uids(emfv->list, uids); - } -} - -static void -emfb_view_hide_read(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderView *emfv = data; - - message_list_hide_add(emfv->list, "(match-all (system-flag \"seen\"))", ML_HIDE_SAME, ML_HIDE_SAME); -} - -static void -emfb_view_hide_selected(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderView *emfv = data; - GPtrArray *uids; - - /* TODO: perhaps this should sit directly on message_list? */ - /* is it worth it, it's so trivial */ - - /* A new flag CAMEL_MESSAGE_HIDDEN is added by Sankar - while extending the CAMEL_MESSAGE_FLAGS for proxy permissions. - This can be used to hide messages. */ - - uids = message_list_get_selected(emfv->list); - message_list_hide_uids(emfv->list, uids); - message_list_free_uids(emfv->list, uids); -} - -static void -emfb_view_show_all(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderView *emfv = data; - - message_list_hide_clear(emfv->list); -} - -/* ********************************************************************** */ - -static void -emfb_mail_stop(BonoboUIComponent *uid, void *data, const char *path) -{ - mail_cancel_all(); -} - -static void -emfb_mail_post(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderView *emfv = data; - em_utils_post_to_folder (emfv->folder); -} - -static void -emfb_tools_filters(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderBrowser *emfb = data; - - em_utils_edit_filters ((GtkWidget *) emfb); -} - -static void -emfb_subscribe_editor_destroy(GtkWidget *w, EMFolderBrowser *emfb) -{ - emfb->priv->subscribe_editor = NULL; -} - -static void -emfb_tools_subscriptions(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderBrowser *emfb = data; - - if (emfb->priv->subscribe_editor) { - gdk_window_show(emfb->priv->subscribe_editor->window); - } else { - emfb->priv->subscribe_editor = (GtkWidget *)em_subscribe_editor_new(); - e_dialog_set_transient_for((GtkWindow *)emfb->priv->subscribe_editor, (GtkWidget *)emfb); - g_signal_connect(emfb->priv->subscribe_editor, "destroy", G_CALLBACK(emfb_subscribe_editor_destroy), emfb); - gtk_widget_show(emfb->priv->subscribe_editor); - } -} - -static void emfb_focus_search(BonoboUIComponent *uid, void *data, const char *path) { EMFolderBrowser *emfb = data; @@ -1743,47 +854,9 @@ emfb_help_debug (BonoboUIComponent *uid, void *data, const char *path) mail_component_show_logger ((GtkWidget *) data); } -static void -emfb_tools_vfolders(BonoboUIComponent *uid, void *data, const char *path) -{ - /* FIXME: rename/refactor this */ - vfolder_edit(); -} - static BonoboUIVerb emfb_verbs[] = { - BONOBO_UI_UNSAFE_VERB ("EditCut", emfb_edit_cut), - BONOBO_UI_UNSAFE_VERB ("EditCopy", emfb_edit_copy), - BONOBO_UI_UNSAFE_VERB ("EditPaste", emfb_edit_paste), - - BONOBO_UI_UNSAFE_VERB ("EditInvertSelection", emfb_edit_invert_selection), - BONOBO_UI_UNSAFE_VERB ("EditSelectAll", emfb_edit_select_all), - BONOBO_UI_UNSAFE_VERB ("EditSelectThread", emfb_edit_select_thread), - BONOBO_UI_UNSAFE_VERB ("EditSelectSubthread", emfb_edit_select_subthread), - BONOBO_UI_UNSAFE_VERB ("ChangeFolderProperties", emfb_folder_properties), - BONOBO_UI_UNSAFE_VERB ("FolderExpunge", emfb_folder_expunge), - /* HideDeleted is a toggle */ - BONOBO_UI_UNSAFE_VERB ("MessageMarkAllAsRead", emfb_mark_all_read), - BONOBO_UI_UNSAFE_VERB ("ViewHideRead", emfb_view_hide_read), - BONOBO_UI_UNSAFE_VERB ("ViewHideSelected", emfb_view_hide_selected), - BONOBO_UI_UNSAFE_VERB ("ViewShowAll", emfb_view_show_all), - /* ViewThreaded is a toggle */ - - BONOBO_UI_UNSAFE_VERB ("ViewThreadsExpandAll", emfb_expand_all_threads), - BONOBO_UI_UNSAFE_VERB ("ViewThreadsCollapseAll", emfb_collapse_all_threads), - - BONOBO_UI_UNSAFE_VERB ("FolderCopy", emfb_folder_copy), - BONOBO_UI_UNSAFE_VERB ("FolderMove", emfb_folder_move), - BONOBO_UI_UNSAFE_VERB ("FolderDelete", emfb_folder_delete), - BONOBO_UI_UNSAFE_VERB ("FolderRefresh", emfb_folder_refresh), - BONOBO_UI_UNSAFE_VERB ("FolderRename", emfb_folder_rename), - BONOBO_UI_UNSAFE_VERB ("FolderCreate", emfb_folder_create), BONOBO_UI_UNSAFE_VERB ("HelpDebug", emfb_help_debug), - BONOBO_UI_UNSAFE_VERB ("MailPost", emfb_mail_post), - BONOBO_UI_UNSAFE_VERB ("MailStop", emfb_mail_stop), - BONOBO_UI_UNSAFE_VERB ("ToolsFilters", emfb_tools_filters), - BONOBO_UI_UNSAFE_VERB ("ToolsSubscriptions", emfb_tools_subscriptions), - BONOBO_UI_UNSAFE_VERB ("ToolsVFolders", emfb_tools_vfolders), BONOBO_UI_UNSAFE_VERB ("FocusSearch", emfb_focus_search), /* ViewPreview is a toggle */ @@ -1791,16 +864,13 @@ static BonoboUIVerb emfb_verbs[] = { BONOBO_UI_VERB_END }; -static EPixmap emfb_pixmaps[] = { - E_PIXMAP ("/commands/FolderCreate", "folder-new", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/ChangeFolderProperties", "document-properties", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/FolderCopy", "folder-copy", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/FolderMove", "folder-move", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/MessageMarkAllAsRead", "mail-read", E_ICON_SIZE_MENU), - - E_PIXMAP_END -}; - +static gboolean +emfb_select_all_daemon (MessageList *ml) +{ + message_list_select_all(ml); + gtk_widget_grab_focus ((GtkWidget *)ml); + return FALSE; +} static void emfb_hide_deleted(BonoboUIComponent *uic, const char *path, Bonobo_UIComponent_EventType type, const char *state, void *data) @@ -1817,195 +887,6 @@ emfb_hide_deleted(BonoboUIComponent *uic, const char *path, Bonobo_UIComponent_E } static void -emfb_view_threaded(BonoboUIComponent *uic, const char *path, Bonobo_UIComponent_EventType type, const char *state, void *data) -{ - GConfClient *gconf; - EMFolderView *emfv = data; - - if (type != Bonobo_UIComponent_STATE_CHANGED) - return; - - gconf = mail_config_get_gconf_client (); - gconf_client_set_bool(gconf, "/apps/evolution/mail/display/thread_list", state[0] != '0', NULL); - - if (camel_object_meta_set(emfv->folder, "evolution:thread_list", state)) - camel_object_state_write(emfv->folder); - - /* FIXME: do set_threaded via meta-data listener on folder? */ - message_list_set_threaded(emfv->list, state[0] != '0'); - - /* FIXME: update selection state? */ -} - -static void -emfb_view_preview(BonoboUIComponent *uic, const char *path, Bonobo_UIComponent_EventType type, const char *state, void *data) -{ - GConfClient *gconf; - EMFolderView *emfv = data; - - if (type != Bonobo_UIComponent_STATE_CHANGED) - return; - - gconf = mail_config_get_gconf_client (); - gconf_client_set_bool(gconf, "/apps/evolution/mail/display/show_preview", state[0] != '0', NULL); - - if (camel_object_meta_set(emfv->folder, "evolution:show_preview", state)) - camel_object_state_write(emfv->folder); - - /* FIXME: do this via folder listener */ - em_folder_browser_show_preview((EMFolderBrowser *)emfv, state[0] != '0'); -} - -static void -emfb_show_next(BonoboUIComponent *uic, const char *path, Bonobo_UIComponent_EventType type, const char *state, void *data) -{ - GConfClient *gconf; - EMFolderBrowser *emfb = data; - - if (type != Bonobo_UIComponent_STATE_CHANGED) - return; - - gconf = mail_config_get_gconf_client (); - gconf_client_set_bool(gconf, "/apps/evolution/mail/display/show_wide", state[0] != '0', NULL); - - em_folder_browser_show_wide(emfb, state[0] != '0'); -} - -static void -emfb_show_below(BonoboUIComponent *uic, const char *path, Bonobo_UIComponent_EventType type, const char *state, void *data) -{ - GConfClient *gconf; - EMFolderBrowser *emfb = data; - - if (type != Bonobo_UIComponent_STATE_CHANGED) - return; - - gconf = mail_config_get_gconf_client (); - gconf_client_set_bool(gconf, "/apps/evolution/mail/display/show_wide", state[0] == '0', NULL); - - em_folder_browser_show_wide(emfb, state[0] == '0'); -} - -static void -emfb_list_scrolled (MessageList *ml, EMFolderBrowser *emfb) -{ - EMFolderView *emfv = (EMFolderView *) emfb; - double position; - char *state; - - position = message_list_get_scrollbar_position (ml); - state = g_strdup_printf ("%f", position); - - if (camel_object_meta_set (emfv->folder, "evolution:list_scroll_position", state)) - camel_object_state_write (emfv->folder); - - g_free (state); -} - -static gboolean -scroll_idle_cb (EMFolderBrowser *emfb) -{ - EMFolderView *emfv = (EMFolderView *) emfb; - double position; - char *state; - - if ((state = camel_object_meta_get (emfv->folder, "evolution:list_scroll_position"))) { - position = strtod (state, NULL); - g_free (state); - } else { - position = emfb->priv->default_scroll_position; - } - - message_list_set_scrollbar_position (emfv->list, position); - - emfb->priv->list_scrolled_id = g_signal_connect (emfv->list, "message_list_scrolled", G_CALLBACK (emfb_list_scrolled), emfb); - - emfb->priv->idle_scroll_id = 0; - - return FALSE; -} - -static void -emfb_gui_folder_changed(CamelFolder *folder, void *dummy, EMFolderBrowser *emfb) -{ - if (emfb->priv->select_uid) { - CamelMessageInfo *mi; - - mi = camel_folder_get_message_info(emfb->view.folder, emfb->priv->select_uid); - if (mi) { - camel_folder_free_message_info(emfb->view.folder, mi); - em_folder_view_set_message(&emfb->view, emfb->priv->select_uid, FALSE); - g_free (emfb->priv->select_uid); - emfb->priv->select_uid = NULL; - } - } - - g_object_unref(emfb); -} - -static void -emfb_folder_changed(CamelFolder *folder, CamelFolderChangeInfo *changes, EMFolderBrowser *emfb) -{ - g_object_ref(emfb); - mail_async_event_emit(emfb->view.async, MAIL_ASYNC_GUI, (MailAsyncFunc)emfb_gui_folder_changed, folder, NULL, emfb); -} - -static void -emfb_etree_unfreeze (GtkWidget *widget, GdkEvent *event, EMFolderView *emfv) -{ - - ETableItem *item = e_tree_get_item (emfv->list->tree); - - g_object_set_data (G_OBJECT (((GnomeCanvasItem *) item)->canvas), "freeze-cursor", 0); -} - - -/* TODO: This should probably be handled by message-list, by storing/queueing - up the select operation if its busy rebuilding the message-list */ -static void -emfb_list_built (MessageList *ml, EMFolderBrowser *emfb) -{ - EMFolderView *emfv = (EMFolderView *) emfb; - double position = 0.0f; - - g_signal_handler_disconnect (ml, emfb->priv->list_built_id); - emfb->priv->list_built_id = 0; - - if (emfv->list->cursor_uid == NULL) { - if (emfb->priv->select_uid) { - CamelMessageInfo *mi; - - /* If the message isn't in the folder yet, keep select_uid around, it could be caught by - folder_changed, at some later date */ - mi = camel_folder_get_message_info(emfv->folder, emfb->priv->select_uid); - if (mi) { - camel_folder_free_message_info(emfv->folder, mi); - em_folder_view_set_message(emfv, emfb->priv->select_uid, TRUE); - g_free (emfb->priv->select_uid); - emfb->priv->select_uid = NULL; - } - - /* change the default to the current position */ - position = message_list_get_scrollbar_position (ml); - } else { - /* NOTE: not all users want this, so we need a preference for it perhaps? see bug #52887 */ - /* FIXME: if the 1st message in the list is unread, this will actually select the second unread msg */ - /*message_list_select (ml, MESSAGE_LIST_SELECT_NEXT, 0, CAMEL_MESSAGE_SEEN, TRUE);*/ - } - } - - emfb->priv->default_scroll_position = position; - - /* FIXME: this is a gross workaround for an etable bug that I can't fix - bug #55303 */ - /* this needs to be a lower priority than anything in e-table-item/e-canvas, since - * e_canvas_item_region_show_relay() uses a timeout, we have to use a timeout of the - * same interval but a lower priority. */ - emfb->priv->idle_scroll_id = g_timeout_add_full (G_PRIORITY_LOW, 250, (GSourceFunc) scroll_idle_cb, emfb, NULL); - /* FIXME: This is another ugly hack done to hide a bug that above hack leaves. */ - g_signal_connect (((GtkScrolledWindow *) ml)->vscrollbar, "button-press-event", G_CALLBACK (emfb_etree_unfreeze), emfb); -} - -static void emfb_set_search_folder(EMFolderView *emfv, CamelFolder *folder, const char *uri) { EMFolderBrowser *emfb = (EMFolderBrowser *) emfv; @@ -2023,10 +904,10 @@ emfb_set_search_folder(EMFolderView *emfv, CamelFolder *folder, const char *uri) emfb->priv->idle_scroll_id = 0; } - if (emfb->view.folder) { - camel_object_remove_event(emfb->view.folder, emfb->priv->folder_changed_id); - emfb->priv->folder_changed_id = 0; - } +// if (emfb->view.folder) { +// camel_object_remove_event(emfb->view.folder, emfb->priv->folder_changed_id); +// emfb->priv->folder_changed_id = 0; +// } emfb_parent->set_folder(emfv, folder, uri); @@ -2049,7 +930,7 @@ emfb_set_folder(EMFolderView *emfv, CamelFolder *folder, const char *uri) struct _EMFolderBrowserPrivate *p = emfb->priv; gboolean different_folder; - message_list_freeze(emfv->list); +// message_list_freeze(emfv->list); if (emfb->priv->list_scrolled_id) { g_signal_handler_disconnect (emfv->list, emfb->priv->list_scrolled_id); @@ -2061,16 +942,16 @@ emfb_set_folder(EMFolderView *emfv, CamelFolder *folder, const char *uri) emfb->priv->idle_scroll_id = 0; } - if (emfb->view.folder && emfb->priv->folder_changed_id) { - camel_object_remove_event(emfb->view.folder, emfb->priv->folder_changed_id); - emfb->priv->folder_changed_id = 0; - } - - different_folder = - emfb->view.folder != NULL && - folder != emfb->view.folder; - - emfb_parent->set_folder(emfv, folder, uri); +// if (emfb->view.folder && emfb->priv->folder_changed_id) { +// camel_object_remove_event(emfb->view.folder, emfb->priv->folder_changed_id); +// emfb->priv->folder_changed_id = 0; +// } +// +// different_folder = +// emfb->view.folder != NULL && +// folder != emfb->view.folder; +// +// emfb_parent->set_folder(emfv, folder, uri); /* This is required since we get activated the first time before the folder is open and need to override the @@ -2092,32 +973,32 @@ emfb_set_folder(EMFolderView *emfv, CamelFolder *folder, const char *uri) gconf_client_set_bool (gconf, "/apps/evolution/mail/display/safe_list", FALSE, NULL); } - mail_refresh_folder(folder, NULL, NULL); - - emfb->priv->folder_changed_id = camel_object_hook_event(folder, "folder_changed", - (CamelObjectEventHookFunc)emfb_folder_changed, emfb); - - /* FIXME: this mostly copied from activate() */ - if ((sstate = camel_object_meta_get(folder, "evolution:show_preview"))) { - state = sstate[0] != '0'; - g_free(sstate); - } else - state = gconf_client_get_bool(gconf, "/apps/evolution/mail/display/show_preview", NULL); - em_folder_browser_show_preview(emfb, state); - if (emfv->uic) - bonobo_ui_component_set_prop(emfv->uic, "/commands/ViewPreview", "state", state?"1":"0", NULL); - - if ((sstate = camel_object_meta_get(folder, "evolution:thread_list"))) { - state = sstate[0] != '0'; - g_free(sstate); - } else - state = gconf_client_get_bool(gconf, "/apps/evolution/mail/display/thread_list", NULL); - message_list_set_threaded(emfv->list, state); - if (emfv->uic) { - bonobo_ui_component_set_prop(emfv->uic, "/commands/ViewThreaded", "state", state?"1":"0", NULL); - bonobo_ui_component_set_prop(emfv->uic, "/commands/ViewThreadsCollapseAll", "sensitive", state?"1":"0", NULL); - bonobo_ui_component_set_prop(emfv->uic, "/commands/ViewThreadsExpandAll", "sensitive", state?"1":"0", NULL); - } +// mail_refresh_folder(folder, NULL, NULL); +// +// emfb->priv->folder_changed_id = camel_object_hook_event(folder, "folder_changed", +// (CamelObjectEventHookFunc)emfb_folder_changed, emfb); +// +// /* FIXME: this mostly copied from activate() */ +// if ((sstate = camel_object_meta_get(folder, "evolution:show_preview"))) { +// state = sstate[0] != '0'; +// g_free(sstate); +// } else +// state = gconf_client_get_bool(gconf, "/apps/evolution/mail/display/show_preview", NULL); +// em_folder_browser_show_preview(emfb, state); +// if (emfv->uic) +// bonobo_ui_component_set_prop(emfv->uic, "/commands/ViewPreview", "state", state?"1":"0", NULL); +// +// if ((sstate = camel_object_meta_get(folder, "evolution:thread_list"))) { +// state = sstate[0] != '0'; +// g_free(sstate); +// } else +// state = gconf_client_get_bool(gconf, "/apps/evolution/mail/display/thread_list", NULL); +// message_list_set_threaded(emfv->list, state); +// if (emfv->uic) { +// bonobo_ui_component_set_prop(emfv->uic, "/commands/ViewThreaded", "state", state?"1":"0", NULL); +// bonobo_ui_component_set_prop(emfv->uic, "/commands/ViewThreadsCollapseAll", "sensitive", state?"1":"0", NULL); +// bonobo_ui_component_set_prop(emfv->uic, "/commands/ViewThreadsExpandAll", "sensitive", state?"1":"0", NULL); +// } if (emfv->uic) { state = (folder->folder_flags & CAMEL_FOLDER_IS_TRASH) == 0; @@ -2153,26 +1034,26 @@ emfb_set_folder(EMFolderView *emfv, CamelFolder *folder, const char *uri) e_search_bar_paint ((ESearchBar *)emfb->search); } - /* This function gets triggered several times at startup, - * so we don't want to reset the message suppression state - * unless we're actually switching to a different folder. */ - if (different_folder) - p->suppress_message_selection = FALSE; - - if (!p->suppress_message_selection) - sstate = camel_object_meta_get ( - folder, "evolution:selected_uid"); - else - sstate = NULL; - - g_free (p->select_uid); - p->select_uid = sstate; - - if (emfv->list->cursor_uid == NULL && emfb->priv->list_built_id == 0) - p->list_built_id = g_signal_connect(emfv->list, "message_list_built", G_CALLBACK (emfb_list_built), emfv); - } - - message_list_thaw(emfv->list); +// /* This function gets triggered several times at startup, +// * so we don't want to reset the message suppression state +// * unless we're actually switching to a different folder. */ +// if (different_folder) +// p->suppress_message_selection = FALSE; +// +// if (!p->suppress_message_selection) +// sstate = camel_object_meta_get ( +// folder, "evolution:selected_uid"); +// else +// sstate = NULL; +// +// g_free (p->select_uid); +// p->select_uid = sstate; +// +// if (emfv->list->cursor_uid == NULL && emfb->priv->list_built_id == 0) +// p->list_built_id = g_signal_connect(emfv->list, "message_list_built", G_CALLBACK (emfb_list_built), emfv); +// } +// +// message_list_thaw(emfv->list); } static void @@ -2184,35 +1065,6 @@ emfb_activate(EMFolderView *emfv, BonoboUIComponent *uic, int act) char *sstate; EMFolderBrowser *emfb = (EMFolderBrowser *) emfv; - gconf = mail_config_get_gconf_client (); - - /* parent loads all ui files via ui_files */ - emfb_parent->activate(emfv, uic, act); - - bonobo_ui_component_add_verb_list_with_data(uic, emfb_verbs, emfv); - e_pixmaps_update(uic, emfb_pixmaps); - - /* FIXME: finish */ - /* (Pre)view pane size (do this first because it affects the - preview settings - see folder_browser_set_message_preview() - internals for details) */ - g_signal_handler_block(emfb->vpane, emfb->priv->vpane_resize_id); - gtk_paned_set_position((GtkPaned *)emfb->vpane, gconf_client_get_int (gconf, emfb->priv->show_wide ? "/apps/evolution/mail/display/hpaned_size": "/apps/evolution/mail/display/paned_size", NULL)); - g_signal_handler_unblock(emfb->vpane, emfb->priv->vpane_resize_id); - - /* (Pre)view toggle */ - if (emfv->folder - && (sstate = camel_object_meta_get(emfv->folder, "evolution:show_preview"))) { - state = sstate[0] == '1'; - g_free(sstate); - } else { - state = gconf_client_get_bool(gconf, "/apps/evolution/mail/display/show_preview", NULL); - } - - bonobo_ui_component_set_prop(uic, "/commands/ViewPreview", "state", state?"1":"0", NULL); - em_folder_browser_show_preview((EMFolderBrowser *)emfv, state); - bonobo_ui_component_add_listener(uic, "ViewPreview", emfb_view_preview, emfv); - /* Stop button */ state = mail_msg_active((unsigned int)-1); bonobo_ui_component_set_prop(uic, "/commands/MailStop", "sensitive", state?"1":"0", NULL); @@ -2227,55 +1079,6 @@ emfb_activate(EMFolderView *emfv, BonoboUIComponent *uic, int act) bonobo_ui_component_set_prop(uic, "/commands/HideDeleted", "state", state ? "1" : "0", NULL); bonobo_ui_component_add_listener(uic, "HideDeleted", emfb_hide_deleted, emfv); em_folder_view_set_hide_deleted(emfv, state); /* <- not sure if this optimal, but it'll do */ - - /* FIXME: If we have no folder, we can't do a few of the lookups we need, - perhaps we should postpone till we can */ - - /* ViewThreaded */ - if (emfv->folder - && (sstate = camel_object_meta_get(emfv->folder, "evolution:thread_list"))) { - state = sstate[0] != '0'; - g_free(sstate); - } else { - state = gconf_client_get_bool(gconf, "/apps/evolution/mail/display/thread_list", NULL); - } - - bonobo_ui_component_set_prop(uic, "/commands/ViewThreaded", "state", state?"1":"0", NULL); - bonobo_ui_component_set_prop(uic, "/commands/ViewThreadsCollapseAll", "sensitive", state?"1":"0", NULL); - bonobo_ui_component_set_prop(uic, "/commands/ViewThreadsExpandAll", "sensitive", state?"1":"0", NULL); - bonobo_ui_component_add_listener(uic, "ViewThreaded", emfb_view_threaded, emfv); - message_list_set_threaded(emfv->list, state); - - /* Show wide display */ - if (emfb->priv->show_wide) { - bonobo_ui_component_set_prop(uic, "/commands/ViewAfter", "state", "1", NULL); - bonobo_ui_component_set_prop(uic, "/commands/ViewBelow", "state", "0", NULL); - } else { - bonobo_ui_component_set_prop(uic, "/commands/ViewAfter", "state", "0", NULL); - bonobo_ui_component_set_prop(uic, "/commands/ViewBelow", "state", "1", NULL); - } - - bonobo_ui_component_add_listener(uic, "ViewAfter", emfb_show_next, emfv); - bonobo_ui_component_add_listener(uic, "ViewBelow", emfb_show_below, emfv); - /* em_folder_browser_show_wide((EMFolderBrowser *)emfv, state); */ - - /* FIXME: Selection state */ - - /* FIXME: property menu customisation */ - /*folder_browser_setup_property_menu (fb, fb->uicomp);*/ - - if (((EMFolderBrowser *)emfv)->search) - e_search_bar_set_ui_component((ESearchBar *)((EMFolderBrowser *)emfv)->search, uic); - } else { - const BonoboUIVerb *v; - - for (v = &emfb_verbs[0]; v->cname; v++) - bonobo_ui_component_remove_verb(uic, v->cname); - - if (((EMFolderBrowser *)emfv)->search) - e_search_bar_set_ui_component((ESearchBar *)((EMFolderBrowser *)emfv)->search, NULL); - - emfb_parent->activate(emfv, uic, act); } } diff --git a/mail/em-folder-properties.c b/mail/em-folder-properties.c index 89cf3c7070..0eed463144 100644 --- a/mail/em-folder-properties.c +++ b/mail/em-folder-properties.c @@ -39,12 +39,13 @@ #include "em-folder-properties.h" #include "em-config.h" -#include "mail-component.h" #include "mail-ops.h" #include "mail-mt.h" #include "mail-vfolder.h" #include "mail-config.h" +#include "e-mail-shell-module.h" + struct _prop_data { void *object; CamelArgV *argv; @@ -287,7 +288,10 @@ static EMConfigItem emfp_items[] = { static gboolean emfp_items_translated = FALSE; static void -emfp_dialog_got_folder_quota (CamelFolder *folder, CamelFolderQuotaInfo *quota, void *data) +emfp_dialog_got_folder_quota (CamelFolder *folder, + const gchar *folder_uri, + CamelFolderQuotaInfo *quota, + void *data) { GtkWidget *dialog, *w; struct _prop_data *prop_data; @@ -295,20 +299,26 @@ emfp_dialog_got_folder_quota (CamelFolder *folder, CamelFolderQuotaInfo *quota, gint32 count, i,deleted; EMConfig *ec; EMConfigTargetFolder *target; + EShellModule *shell_module; + EShellWindow *shell_window; + EShellView *shell_view; CamelArgGetV *arggetv; CamelArgV *argv; + CamelStore *local_store; gboolean hide_deleted; GConfClient *gconf; CamelStore *store; - char *uri = (char *)data; - if (folder == NULL) { - g_free (uri); + if (folder == NULL) return; - } store = folder->parent_store; + shell_view = E_SHELL_VIEW (data); + shell_module = e_shell_view_get_shell_module (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + local_store = e_mail_shell_module_get_local_store (shell_module); + prop_data = g_malloc0 (sizeof (*prop_data)); prop_data->object = folder; camel_object_ref (folder); @@ -341,7 +351,7 @@ emfp_dialog_got_folder_quota (CamelFolder *folder, CamelFolderQuotaInfo *quota, camel_object_get (folder, NULL, CAMEL_FOLDER_TOTAL, &prop_data->total, NULL); } - if (store == mail_component_peek_local_store(NULL) + if (store == local_store && (!strcmp(prop_data->name, "Drafts") || !strcmp(prop_data->name, "Templates") || !strcmp(prop_data->name, "Inbox") @@ -387,11 +397,11 @@ emfp_dialog_got_folder_quota (CamelFolder *folder, CamelFolderQuotaInfo *quota, g_free (arggetv); prop_data->argv = argv; - dialog = gtk_dialog_new_with_buttons (_("Folder Properties"), NULL, - GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OK, GTK_RESPONSE_OK, - NULL); + dialog = gtk_dialog_new_with_buttons ( + _("Folder Properties"), GTK_WINDOW (shell_window), + GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); gtk_window_set_default_size ((GtkWindow *) dialog, 192, 160); gtk_widget_ensure_style (dialog); gtk_container_set_border_width ((GtkContainer *) ((GtkDialog *) dialog)->vbox, 12); @@ -411,7 +421,7 @@ emfp_dialog_got_folder_quota (CamelFolder *folder, CamelFolderQuotaInfo *quota, l = g_slist_prepend(l, &emfp_items[i]); e_config_add_items((EConfig *)ec, l, emfp_commit, NULL, emfp_free, prop_data); - target = em_config_target_new_folder(ec, folder, uri); + target = em_config_target_new_folder(ec, folder, folder_uri); e_config_set_target((EConfig *)ec, (EConfigTarget *)target); w = e_config_create_widget((EConfig *)ec); @@ -421,15 +431,17 @@ emfp_dialog_got_folder_quota (CamelFolder *folder, CamelFolderQuotaInfo *quota, g_signal_connect (dialog, "response", G_CALLBACK (emfp_dialog_response), prop_data); gtk_widget_show (dialog); - - g_free (uri); } static void emfp_dialog_got_folder (char *uri, CamelFolder *folder, void *data) { + EShellView *shell_view = data; + /* this should be called in a thread too */ - mail_get_folder_quota (folder, emfp_dialog_got_folder_quota, g_strdup (uri), mail_msg_unordered_push); + mail_get_folder_quota ( + folder, uri, emfp_dialog_got_folder_quota, + shell_view, mail_msg_unordered_push); } /** @@ -442,27 +454,32 @@ emfp_dialog_got_folder (char *uri, CamelFolder *folder, void *data) * as NULL, then the folder @uri will be loaded first. **/ void -em_folder_properties_show(GtkWindow *parent, CamelFolder *folder, const char *uri) +em_folder_properties_show (EShellView *shell_view, + CamelFolder *folder, + const gchar *uri) { + g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); + g_return_if_fail (uri != NULL); + /* HACK: its the old behaviour, not very 'neat' but it works */ - if (!strncmp(uri, "vfolder:", 8)) { - CamelURL *url = camel_url_new(uri, NULL); + if (!strncmp (uri, "vfolder:", 8)) { + CamelURL *url = camel_url_new (uri, NULL); /* MORE HACK: UNMATCHED is a special folder which you can't modify, so check for it here */ if (url == NULL || url->fragment == NULL || strcmp(url->fragment, CAMEL_UNMATCHED_NAME) != 0) { if (url) - camel_url_free(url); - vfolder_edit_rule(uri); + camel_url_free (url); + vfolder_edit_rule (uri); return; } - if (url) - camel_url_free(url); + if (url != NULL) + camel_url_free (url); } if (folder == NULL) - mail_get_folder(uri, 0, emfp_dialog_got_folder, NULL, mail_msg_unordered_push); + mail_get_folder(uri, 0, emfp_dialog_got_folder, shell_view, mail_msg_unordered_push); else - emfp_dialog_got_folder((char *)uri, folder, NULL); + emfp_dialog_got_folder((char *)uri, folder, shell_view); } diff --git a/mail/em-folder-properties.h b/mail/em-folder-properties.h index 8bae3848e7..35d80c293b 100644 --- a/mail/em-folder-properties.h +++ b/mail/em-folder-properties.h @@ -24,18 +24,15 @@ #ifndef __EM_FOLDER_PROPERTIES_H__ #define __EM_FOLDER_PROPERTIES_H__ -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ +#include <camel/camel-folder.h> +#include <shell/e-shell-view.h> -struct _CamelFolder; -struct _GtkWindow; +G_BEGIN_DECLS -void em_folder_properties_show(struct _GtkWindow *parent, struct _CamelFolder *folder, const char *uri); +void em_folder_properties_show (EShellView *shell_view, + CamelFolder *folder, + const gchar *uri); -#ifdef __cplusplus -} -#endif /* __cplusplus */ +G_END_DECLS #endif /* __EM_FOLDER_PROPERTIES_H__ */ diff --git a/mail/em-folder-selection-button.c b/mail/em-folder-selection-button.c index 9257c57b5d..e078f44f16 100644 --- a/mail/em-folder-selection-button.c +++ b/mail/em-folder-selection-button.c @@ -25,11 +25,9 @@ #endif #include <string.h> - -#include <e-util/e-util.h> #include <glib/gi18n.h> +#include <e-util/e-util.h> -#include "mail-component.h" #include "mail-config.h" #include "em-folder-tree.h" #include "em-folder-selector.h" @@ -37,250 +35,459 @@ #include "em-folder-selection-button.h" -static void em_folder_selection_button_class_init (EMFolderSelectionButtonClass *klass); -static void em_folder_selection_button_init (EMFolderSelectionButton *emfsb); -static void em_folder_selection_button_destroy (GtkObject *obj); -static void em_folder_selection_button_finalize (GObject *obj); -static void em_folder_selection_button_clicked (GtkButton *button); - -static GtkButtonClass *parent_class = NULL; +#define EM_FOLDER_SELECTION_BUTTON_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON, EMFolderSelectionButtonPrivate)) struct _EMFolderSelectionButtonPrivate { + gpointer model; /* weak pointer */ + GtkWidget *icon; GtkWidget *label; - GtkWidget *selector; - - char *uri; /* for single-select mode */ + gchar *uri; /* for single-select mode */ GList *uris; /* for multi-select mode */ - char *title; - char *caption; + gchar *title; + gchar *caption; gboolean multiple_select; }; enum { + PROP_0, + PROP_CAPTION, + PROP_MODEL, + PROP_MULTISELECT, + PROP_TITLE +}; + +enum { SELECTED, LAST_SIGNAL }; -static guint signals[LAST_SIGNAL] = { 0 }; +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; -GType -em_folder_selection_button_get_type (void) +static void +folder_selection_button_unselected (EMFolderSelectionButton *button) { - static GType type = 0; + const gchar *text; - if (!type) { - static const GTypeInfo info = { - sizeof (EMFolderSelectionButtonClass), - NULL, /* base_class_init */ - NULL, /* base_class_finalize */ - (GClassInitFunc) em_folder_selection_button_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EMFolderSelectionButton), - 0, /* n_preallocs */ - (GInstanceInitFunc) em_folder_selection_button_init, - }; + text = _("<click here to select a folder>"); + gtk_image_set_from_pixbuf (GTK_IMAGE (button->priv->icon), NULL); + gtk_label_set_text (GTK_LABEL (button->priv->label), text); +} + +static void +folder_selection_button_set_contents (EMFolderSelectionButton *button) +{ + EAccount *account; + GtkLabel *label; + const gchar *uri; + gchar *folder_name; + + uri = button->priv->uri; + label = GTK_LABEL (button->priv->label); + folder_name = em_utils_folder_name_from_uri (uri); - type = g_type_register_static (GTK_TYPE_BUTTON, "EMFolderSelectionButton", &info, 0); + if (folder_name == NULL) { + folder_selection_button_unselected (button); + return; } - return type; + account = mail_config_get_account_by_source_url (uri); + + if (account != NULL) { + gchar *tmp = folder_name; + + folder_name = g_strdup_printf ( + "%s/%s", e_account_get_string ( + account, E_ACCOUNT_NAME), _(folder_name)); + gtk_label_set_text (label, folder_name); + g_free (tmp); + } else + gtk_label_set_text (label, _(folder_name)); + + g_free (folder_name); } static void -em_folder_selection_button_class_init (EMFolderSelectionButtonClass *klass) +folder_selection_button_set_model (EMFolderSelectionButton *button, + EMFolderTreeModel *model) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass); - GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass); - - parent_class = g_type_class_ref (GTK_TYPE_BUTTON); - - object_class->finalize = em_folder_selection_button_finalize; - gtk_object_class->destroy = em_folder_selection_button_destroy; - button_class->clicked = em_folder_selection_button_clicked; - - signals[SELECTED] = g_signal_new ("selected", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (EMFolderSelectionButtonClass, selected), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + g_return_if_fail (button->priv->model == NULL); + + button->priv->model = model; + + g_object_add_weak_pointer ( + G_OBJECT (model), &button->priv->model); } static void -set_contents_unselected (EMFolderSelectionButton *button) +folder_selection_button_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { - gtk_image_set_from_pixbuf (GTK_IMAGE (button->priv->icon), NULL); - gtk_label_set_text (GTK_LABEL (button->priv->label), _("<click here to select a folder>")); + switch (property_id) { + case PROP_CAPTION: + em_folder_selection_button_set_caption ( + EM_FOLDER_SELECTION_BUTTON (object), + g_value_get_string (value)); + return; + + case PROP_MODEL: + folder_selection_button_set_model ( + EM_FOLDER_SELECTION_BUTTON (object), + g_value_get_object (value)); + return; + + case PROP_MULTISELECT: + em_folder_selection_button_set_multiselect ( + EM_FOLDER_SELECTION_BUTTON (object), + g_value_get_boolean (value)); + return; + + case PROP_TITLE: + em_folder_selection_button_set_title ( + EM_FOLDER_SELECTION_BUTTON (object), + g_value_get_string (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -set_contents (EMFolderSelectionButton *button) +folder_selection_button_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { - struct _EMFolderSelectionButtonPrivate *priv = button->priv; - char *folder_name = em_utils_folder_name_from_uri (priv->uri); + switch (property_id) { + case PROP_CAPTION: + g_value_set_string ( + value, + em_folder_selection_button_get_caption ( + EM_FOLDER_SELECTION_BUTTON (object))); + return; + + case PROP_MODEL: + g_value_set_object ( + value, + em_folder_selection_button_get_model ( + EM_FOLDER_SELECTION_BUTTON (object))); + return; + + case PROP_MULTISELECT: + g_value_set_boolean ( + value, + em_folder_selection_button_get_multiselect ( + EM_FOLDER_SELECTION_BUTTON (object))); + return; + + case PROP_TITLE: + g_value_set_string ( + value, + em_folder_selection_button_get_title ( + EM_FOLDER_SELECTION_BUTTON (object))); + return; + } - if (folder_name) { - EAccount *account = mail_config_get_account_by_source_url (priv->uri); + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} - if (account) { - char *tmp = folder_name; - folder_name = g_strdup_printf ("%s/%s", e_account_get_string (account, E_ACCOUNT_NAME), _(folder_name)); - g_free (tmp); - gtk_label_set_text (GTK_LABEL (priv->label), folder_name); - } else - gtk_label_set_text (GTK_LABEL (priv->label), _(folder_name)); +static void +folder_selection_button_dispose (GObject *object) +{ + EMFolderSelectionButtonPrivate *priv; - g_free (folder_name); - } else { - set_contents_unselected (button); + priv = EM_FOLDER_SELECTION_BUTTON_GET_PRIVATE (object); + + if (priv->model != NULL) { + g_object_remove_weak_pointer ( + G_OBJECT (priv->model), &priv->model); + priv->model = NULL; } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); } static void -em_folder_selection_button_init (EMFolderSelectionButton *emfsb) +folder_selection_button_finalize (GObject *object) { - struct _EMFolderSelectionButtonPrivate *priv; - GtkWidget *box; + EMFolderSelectionButtonPrivate *priv; - priv = g_new0 (struct _EMFolderSelectionButtonPrivate, 1); - emfsb->priv = priv; + priv = EM_FOLDER_SELECTION_BUTTON_GET_PRIVATE (object); - priv->multiple_select = FALSE; + g_list_foreach (priv->uris, (GFunc) g_free, NULL); + g_list_free (priv->uris); - box = gtk_hbox_new (FALSE, 4); + g_free (priv->title); + g_free (priv->caption); + g_free (priv->uri); - priv->icon = gtk_image_new (); - gtk_widget_show (priv->icon); - gtk_box_pack_start (GTK_BOX (box), priv->icon, FALSE, TRUE, 0); + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} - priv->label = gtk_label_new (""); - gtk_widget_show (priv->label); - gtk_label_set_justify (GTK_LABEL (priv->label), GTK_JUSTIFY_LEFT); - gtk_misc_set_alignment (GTK_MISC (priv->label), 0.0, 0.0); - gtk_box_pack_start (GTK_BOX (box), priv->label, TRUE, TRUE, 0); +static void +folder_selection_button_destroy (GtkObject *object) +{ + EMFolderSelectionButtonPrivate *priv; - gtk_widget_show (box); - gtk_container_add (GTK_CONTAINER (emfsb), box); + priv = EM_FOLDER_SELECTION_BUTTON_GET_PRIVATE (object); - set_contents (emfsb); + /* Chain up to parent's destroy() method. */ + GTK_OBJECT_CLASS (parent_class)->destroy (object); } static void -em_folder_selection_button_destroy (GtkObject *obj) +folder_selection_button_clicked (GtkButton *button) { - struct _EMFolderSelectionButtonPrivate *priv = ((EMFolderSelectionButton *) obj)->priv; + EMFolderSelectionButtonPrivate *priv; + EMFolderTree *emft; + GtkWidget *dialog; + + priv = EM_FOLDER_SELECTION_BUTTON_GET_PRIVATE (button); + + emft = (EMFolderTree *) em_folder_tree_new_with_model (priv->model); + + em_folder_tree_set_multiselect (emft, priv->multiple_select); + em_folder_tree_set_excluded ( + emft, EMFT_EXCLUDE_NOSELECT | + EMFT_EXCLUDE_VIRTUAL | EMFT_EXCLUDE_VTRASH); + + dialog = em_folder_selector_new ( + emft, EM_FOLDER_SELECTOR_CAN_CREATE, + priv->title, priv->caption, NULL); - if (priv->selector) { - gtk_widget_destroy(priv->selector); - priv->selector = NULL; + if (priv->multiple_select) + em_folder_selector_set_selected_list ( + EM_FOLDER_SELECTOR (dialog), priv->uris); + else + em_folder_selector_set_selected ( + EM_FOLDER_SELECTOR (dialog), priv->uri); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) + goto exit; + + if (priv->multiple_select) { + GList *uris; + + uris = em_folder_selector_get_selected_uris ( + EM_FOLDER_SELECTOR (dialog)); + em_folder_selection_button_set_selection_mult ( + EM_FOLDER_SELECTION_BUTTON (button), uris); + } else { + const gchar *uri; + + uri = em_folder_selector_get_selected_uri ( + EM_FOLDER_SELECTOR (dialog)); + em_folder_selection_button_set_selection ( + EM_FOLDER_SELECTION_BUTTON (button), uri); } - GTK_OBJECT_CLASS (parent_class)->destroy (obj); + g_signal_emit (button, signals[SELECTED], 0); + +exit: + gtk_widget_destroy (dialog); +} + +static void +folder_selection_button_class_init (EMFolderSelectionButtonClass *class) +{ + GObjectClass *object_class; + GtkObjectClass *gtk_object_class; + GtkButtonClass *button_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMFolderSelectionButtonPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = folder_selection_button_set_property; + object_class->get_property = folder_selection_button_get_property; + object_class->dispose = folder_selection_button_dispose; + object_class->finalize = folder_selection_button_finalize; + + gtk_object_class = GTK_OBJECT_CLASS (class); + gtk_object_class->destroy = folder_selection_button_destroy; + + button_class = GTK_BUTTON_CLASS (class); + button_class->clicked = folder_selection_button_clicked; + + g_object_class_install_property ( + object_class, + PROP_CAPTION, + g_param_spec_string ( + "caption", + NULL, + NULL, + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_MODEL, + g_param_spec_object ( + "model", + NULL, + NULL, + EM_TYPE_FOLDER_TREE_MODEL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_MULTISELECT, + g_param_spec_boolean ( + "multiselect", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_TITLE, + g_param_spec_string ( + "title", + NULL, + NULL, + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + signals[SELECTED] = g_signal_new ( + "selected", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EMFolderSelectionButtonClass, selected), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } static void -em_folder_selection_button_finalize (GObject *obj) +folder_selection_button_init (EMFolderSelectionButton *emfsb) { - struct _EMFolderSelectionButtonPrivate *priv = ((EMFolderSelectionButton *) obj)->priv; + GtkWidget *box; - GList *lst = ((EMFolderSelectionButton*) obj)->priv->uris; - g_list_foreach (lst, (GFunc) g_free, NULL); - g_list_free (lst); + emfsb->priv = EM_FOLDER_SELECTION_BUTTON_GET_PRIVATE (emfsb); - g_free (priv->title); - g_free (priv->caption); - g_free (priv->uri); - g_free (priv); + emfsb->priv->multiple_select = FALSE; + + box = gtk_hbox_new (FALSE, 4); - G_OBJECT_CLASS (parent_class)->finalize (obj); + emfsb->priv->icon = gtk_image_new (); + gtk_widget_show (emfsb->priv->icon); + gtk_box_pack_start (GTK_BOX (box), emfsb->priv->icon, FALSE, TRUE, 0); + + emfsb->priv->label = gtk_label_new (""); + gtk_widget_show (emfsb->priv->label); + gtk_label_set_justify (GTK_LABEL (emfsb->priv->label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (emfsb->priv->label), 0.0, 0.0); + gtk_box_pack_start (GTK_BOX (box), emfsb->priv->label, TRUE, TRUE, 0); + + gtk_widget_show (box); + gtk_container_add (GTK_CONTAINER (emfsb), box); + + folder_selection_button_set_contents (emfsb); } -static void -emfsb_selector_response (EMFolderSelector *emfs, int response, EMFolderSelectionButton *button) +GType +em_folder_selection_button_get_type (void) { - if (response == GTK_RESPONSE_OK) { - if (button->priv->multiple_select) { - GList *uris = em_folder_selector_get_selected_uris (emfs); + static GType type = 0; - em_folder_selection_button_set_selection_mult (button, uris); - g_signal_emit (button, signals[SELECTED], 0); - } else { - const char *uri = em_folder_selector_get_selected_uri (emfs); + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMFolderSelectionButtonClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) folder_selection_button_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMFolderSelectionButton), + 0, /* n_preallocs */ + (GInstanceInitFunc) folder_selection_button_init, + NULL /* value_table */ + }; - em_folder_selection_button_set_selection (button, uri); - g_signal_emit (button, signals[SELECTED], 0); - } + type = g_type_register_static ( + GTK_TYPE_BUTTON, "EMFolderSelectionButton", + &type_info, 0); } - gtk_widget_destroy ((GtkWidget *) emfs); + return type; } -static void -em_folder_selection_button_clicked (GtkButton *button) +GtkWidget * +em_folder_selection_button_new (EMFolderTreeModel *model, + const gchar *title, + const gchar *caption) { - struct _EMFolderSelectionButtonPrivate *priv = EM_FOLDER_SELECTION_BUTTON (button)->priv; - EMFolderTreeModel *model; - EMFolderTree *emft; - GtkWidget *dialog; + g_return_val_if_fail (EM_IS_FOLDER_TREE_MODEL (model), NULL); - if (GTK_BUTTON_CLASS (parent_class)->clicked != NULL) - (* GTK_BUTTON_CLASS (parent_class)->clicked) (button); + return g_object_new ( + EM_TYPE_FOLDER_SELECTION_BUTTON, + "model", model, "title", title, + "caption", caption, NULL); +} - if (priv->selector) { - gtk_window_present((GtkWindow *)priv->selector); - return; - } +EMFolderTreeModel * +em_folder_selection_button_get_model (EMFolderSelectionButton *button) +{ + g_return_val_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button), NULL); - model = mail_component_peek_tree_model (mail_component_peek ()); - emft = (EMFolderTree *) em_folder_tree_new_with_model (model); - g_object_unref (model); - em_folder_tree_set_multiselect (emft, priv->multiple_select); - em_folder_tree_set_excluded(emft, EMFT_EXCLUDE_NOSELECT|EMFT_EXCLUDE_VIRTUAL|EMFT_EXCLUDE_VTRASH); - dialog = em_folder_selector_new (emft, EM_FOLDER_SELECTOR_CAN_CREATE, priv->title, priv->caption, NULL); - if (priv->multiple_select) - em_folder_selector_set_selected_list ((EMFolderSelector *) dialog, priv->uris); - else - em_folder_selector_set_selected ((EMFolderSelector *) dialog, priv->uri); - g_signal_connect (dialog, "response", G_CALLBACK (emfsb_selector_response), button); - priv->selector = dialog; - g_signal_connect(dialog, "destroy", G_CALLBACK(gtk_widget_destroyed), &priv->selector); - gtk_widget_show (dialog); + return button->priv->model; } -GtkWidget * -em_folder_selection_button_new (const char *title, const char *caption) +const gchar * +em_folder_selection_button_get_caption (EMFolderSelectionButton *button) { - EMFolderSelectionButton *button = g_object_new (EM_TYPE_FOLDER_SELECTION_BUTTON, NULL); + g_return_val_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button), NULL); - button->priv->title = g_strdup (title); + return button->priv->caption; +} + +void +em_folder_selection_button_set_caption (EMFolderSelectionButton *button, + const gchar *caption) +{ + g_return_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button)); + + g_free (button->priv->caption); button->priv->caption = g_strdup (caption); - return GTK_WIDGET (button); + g_object_notify (G_OBJECT (button), "caption"); } -void -em_folder_selection_button_set_selection (EMFolderSelectionButton *button, const char *uri) +gboolean +em_folder_selection_button_get_multiselect (EMFolderSelectionButton *button) { - struct _EMFolderSelectionButtonPrivate *priv = button->priv; + g_return_val_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button), FALSE); + + return button->priv->multiple_select; +} +void +em_folder_selection_button_set_multiselect (EMFolderSelectionButton *button, + gboolean multiselect) +{ g_return_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button)); - if (priv->uri != uri) { - g_free (priv->uri); - priv->uri = g_strdup (uri); - } + button->priv->multiple_select = multiselect; - set_contents (button); + g_object_notify (G_OBJECT (button), "multiselect"); } -const char * +const gchar * em_folder_selection_button_get_selection (EMFolderSelectionButton *button) { g_return_val_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button), NULL); @@ -289,20 +496,40 @@ em_folder_selection_button_get_selection (EMFolderSelectionButton *button) } void -em_folder_selection_button_set_selection_mult (EMFolderSelectionButton *button, GList *uris) +em_folder_selection_button_set_selection (EMFolderSelectionButton *button, + const gchar *uri) +{ + g_return_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button)); + + if (g_strcmp0 (button->priv->uri, uri) == 0) + return; + + g_free (button->priv->uri); + button->priv->uri = g_strdup (uri); + + folder_selection_button_set_contents (button); +} + +GList * +em_folder_selection_button_get_selection_mult (EMFolderSelectionButton *button) +{ + g_return_val_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button), NULL); + + return button->priv->uris; +} + +void +em_folder_selection_button_set_selection_mult (EMFolderSelectionButton *button, + GList *uris) { - struct _EMFolderSelectionButtonPrivate *priv = button->priv; char *caption, *tmp, *tmp2; g_return_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button)); - if (priv->uris) { - g_list_foreach (priv->uris, (GFunc) g_free, NULL); - g_list_free (priv->uris); - priv->uris = NULL; - } + g_list_foreach (button->priv->uris, (GFunc) g_free, NULL); + g_list_free (button->priv->uris); - priv->uris = uris; + button->priv->uris = uris; /* compile the name */ caption = g_strdup (""); @@ -319,34 +546,36 @@ em_folder_selection_button_set_selection_mult (EMFolderSelectionButton *button, /* apparently, we do not know this folder, so we'll just skip it */ g_free (uris->data); uris = g_list_next (uris); - priv->uris = g_list_remove (priv->uris, uris->data); + button->priv->uris = g_list_remove ( + button->priv->uris, uris->data); } } if (caption[0]) - gtk_label_set_text (GTK_LABEL (priv->label), caption + 2); + gtk_label_set_text ( + GTK_LABEL (button->priv->label), caption + 2); else - set_contents_unselected (button); + folder_selection_button_unselected (button); g_free (caption); } -GList * -em_folder_selection_button_get_selection_mult (EMFolderSelectionButton *button) +const gchar * +em_folder_selection_button_get_title (EMFolderSelectionButton *button) { - g_return_val_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button), NULL); + g_return_val_if_fail (EM_FOLDER_SELECTION_BUTTON (button), NULL); - return button->priv->uris; + return button->priv->title; } void -em_folder_selection_button_set_multiselect (EMFolderSelectionButton *button, gboolean value) +em_folder_selection_button_set_title (EMFolderSelectionButton *button, + const gchar *title) { - button->priv->multiple_select = value; -} + g_return_if_fail (EM_FOLDER_SELECTION_BUTTON (button)); -gboolean -em_folder_selection_button_get_multiselect (EMFolderSelectionButton *button) -{ - return button->priv->multiple_select; + g_free (button->priv->title); + button->priv->title = g_strdup (title); + + g_object_notify (G_OBJECT (button), "title"); } diff --git a/mail/em-folder-selection-button.h b/mail/em-folder-selection-button.h index e9cd1c2a0e..a8b009b1c0 100644 --- a/mail/em-folder-selection-button.h +++ b/mail/em-folder-selection-button.h @@ -21,29 +21,41 @@ * */ -#ifndef __EM_FOLDER_SELECTION_BUTTON_H__ -#define __EM_FOLDER_SELECTION_BUTTON_H__ +#ifndef EM_FOLDER_SELECTION_BUTTON_H +#define EM_FOLDER_SELECTION_BUTTON_H #include <gtk/gtk.h> -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#define EM_TYPE_FOLDER_SELECTION_BUTTON (em_folder_selection_button_get_type ()) -#define EM_FOLDER_SELECTION_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON, EMFolderSelectionButton)) -#define EM_FOLDER_SELECTION_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EM_TYPE_FOLDER_SELECTION_BUTTON, EMFolderSelectionButtonClass)) -#define EM_IS_FOLDER_SELECTION_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON)) -#define EM_IS_FOLDER_SELECTION_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON)) - -typedef struct _EMFolderSelectionButton EMFolderSelectionButton; -typedef struct _EMFolderSelectionButtonClass EMFolderSelectionButtonClass; +#include <mail/em-folder-tree-model.h> + +/* Standard GObject macros */ +#define EM_TYPE_FOLDER_SELECTION_BUTTON \ + (em_folder_selection_button_get_type ()) +#define EM_FOLDER_SELECTION_BUTTON(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON, EMFolderSelectionButton)) +#define EM_FOLDER_SELECTION_BUTTON_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), EM_TYPE_FOLDER_SELECTION_BUTTON, EMFolderSelectionButtonClass)) +#define EM_IS_FOLDER_SELECTION_BUTTON(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON)) +#define EM_IS_FOLDER_SELECTION_BUTTON_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON)) +#define EM_FOLDER_SELECTION_BUTTON_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON, EMFolderSelectionButtonClass)) + +G_BEGIN_DECLS + +typedef struct _EMFolderSelectionButton EMFolderSelectionButton; +typedef struct _EMFolderSelectionButtonClass EMFolderSelectionButtonClass; +typedef struct _EMFolderSelectionButtonPrivate EMFolderSelectionButtonPrivate; struct _EMFolderSelectionButton { GtkButton parent; - - struct _EMFolderSelectionButtonPrivate *priv; + EMFolderSelectionButtonPrivate *priv; }; struct _EMFolderSelectionButtonClass { @@ -51,25 +63,43 @@ struct _EMFolderSelectionButtonClass { /* Signals. */ - void (* selected) (EMFolderSelectionButton *button); + void (*selected) (EMFolderSelectionButton *button); }; - -GType em_folder_selection_button_get_type (void); - -GtkWidget *em_folder_selection_button_new (const char *title, const char *caption); - -void em_folder_selection_button_set_selection (EMFolderSelectionButton *button, const char *uri); -const char *em_folder_selection_button_get_selection (EMFolderSelectionButton *button); - -void em_folder_selection_button_set_selection_mult (EMFolderSelectionButton *button, GList *uris); -GList *em_folder_selection_button_get_selection_mult (EMFolderSelectionButton *button); - -void em_folder_selection_button_set_multiselect (EMFolderSelectionButton *button, gboolean value); -gboolean em_folder_selection_button_get_multiselect (EMFolderSelectionButton *button); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __EM_FOLDER_SELECTION_BUTTON_H__ */ +GType em_folder_selection_button_get_type (void); +GtkWidget * em_folder_selection_button_new + (EMFolderTreeModel *model, + const gchar *title, + const gchar *caption); +EMFolderTreeModel * + em_folder_selection_button_get_model + (EMFolderSelectionButton *button); +const gchar * em_folder_selection_button_get_caption + (EMFolderSelectionButton *button); +void em_folder_selection_button_set_caption + (EMFolderSelectionButton *button, + const gchar *caption); +gboolean em_folder_selection_button_get_multiselect + (EMFolderSelectionButton *button); +void em_folder_selection_button_set_multiselect + (EMFolderSelectionButton *button, + gboolean multiselect); +const gchar * em_folder_selection_button_get_selection + (EMFolderSelectionButton *button); +void em_folder_selection_button_set_selection + (EMFolderSelectionButton *button, + const gchar *uri); +GList * em_folder_selection_button_get_selection_mult + (EMFolderSelectionButton *button); +void em_folder_selection_button_set_selection_mult + (EMFolderSelectionButton *button, + GList *uris); +const gchar * em_folder_selection_button_get_title + (EMFolderSelectionButton *button); +void em_folder_selection_button_set_title + (EMFolderSelectionButton *button, + const gchar *title); + +G_END_DECLS + +#endif /* EM_FOLDER_SELECTION_BUTTON_H */ diff --git a/mail/em-folder-selection.c b/mail/em-folder-selection.c index d56a470153..3a457407f7 100644 --- a/mail/em-folder-selection.c +++ b/mail/em-folder-selection.c @@ -32,7 +32,8 @@ #include "em-folder-tree.h" #include "em-folder-selector.h" #include "em-folder-selection.h" -#include "mail-component.h" + +#include "e-mail-shell-module.h" /* TODO: rmeove this file, it could just go on em-folder-selection or em-utils */ @@ -63,7 +64,7 @@ em_select_folder (GtkWindow *parent_window, const char *title, const char *oklab GtkWidget *dialog; EMFolderTree *emft; - model = mail_component_peek_tree_model (mail_component_peek ()); + model = e_mail_shell_module_get_folder_tree_model (mail_shell_module); emft = (EMFolderTree *) em_folder_tree_new_with_model (model); if (exclude) em_folder_tree_set_excluded_func(emft, exclude, user_data); diff --git a/mail/em-folder-selector.c b/mail/em-folder-selector.c index 3762e05bf2..1f5140701a 100644 --- a/mail/em-folder-selector.c +++ b/mail/em-folder-selector.c @@ -21,14 +21,8 @@ * */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - #include <string.h> - #include <glib/gi18n.h> - #include <e-util/e-util.h> #include <misc/e-gui-utils.h> @@ -42,87 +36,84 @@ #define d(x) - extern CamelSession *session; +static gpointer parent_class; +static void +folder_selector_finalize (GObject *object) +{ + EMFolderSelector *emfs = EM_FOLDER_SELECTOR (object); -static void em_folder_selector_class_init (EMFolderSelectorClass *klass); -static void em_folder_selector_init (EMFolderSelector *emfs); -static void em_folder_selector_destroy (GtkObject *obj); -static void em_folder_selector_finalize (GObject *obj); - - -static GtkDialogClass *parent_class = NULL; + g_free (emfs->selected_path); + g_free (emfs->selected_uri); + g_free (emfs->created_uri); + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} -GType -em_folder_selector_get_type (void) +static void +folder_selector_destroy (GtkObject *object) { - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof (EMFolderSelectorClass), - NULL, /* base_class_init */ - NULL, /* base_class_finalize */ - (GClassInitFunc) em_folder_selector_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EMFolderSelector), - 0, /* n_preallocs */ - (GInstanceInitFunc) em_folder_selector_init, - }; + EMFolderSelector *emfs = EM_FOLDER_SELECTOR (object); + EMFolderTreeModel *model; - type = g_type_register_static (GTK_TYPE_DIALOG, "EMFolderSelector", &info, 0); + if (emfs->created_id != 0) { + model = em_folder_tree_get_model (emfs->emft); + g_signal_handler_disconnect (model, emfs->created_id); + emfs->created_id = 0; } - return type; + /* Chain up to parent's destroy() method. */ + GTK_OBJECT_CLASS (parent_class)->destroy (object); } static void -em_folder_selector_class_init (EMFolderSelectorClass *klass) +folder_selector_class_init (EMFolderSelectorClass *class) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass); + GObjectClass *object_class; + GtkObjectClass *gtk_object_class; - parent_class = g_type_class_ref (GTK_TYPE_DIALOG); + parent_class = g_type_class_peek_parent (class); - object_class->finalize = em_folder_selector_finalize; - gtk_object_class->destroy = em_folder_selector_destroy; + object_class = G_OBJECT_CLASS (class); + object_class->finalize = folder_selector_finalize; + + gtk_object_class = GTK_OBJECT_CLASS (class); + gtk_object_class->destroy = folder_selector_destroy; } static void -em_folder_selector_init (EMFolderSelector *emfs) +folder_selector_init (EMFolderSelector *emfs) { emfs->selected_path = NULL; emfs->selected_uri = NULL; } -static void -em_folder_selector_destroy (GtkObject *obj) +GType +em_folder_selector_get_type (void) { - EMFolderSelector *emfs = (EMFolderSelector *) obj; - EMFolderTreeModel *model; - - if (emfs->created_id != 0) { - model = em_folder_tree_get_model (emfs->emft); - g_signal_handler_disconnect (model, emfs->created_id); - emfs->created_id = 0; - } - - GTK_OBJECT_CLASS (parent_class)->destroy (obj); -} + static GType type = 0; -static void -em_folder_selector_finalize (GObject *obj) -{ - EMFolderSelector *emfs = (EMFolderSelector *) obj; + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMFolderSelectorClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) folder_selector_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMFolderSelector), + 0, /* n_preallocs */ + (GInstanceInitFunc) folder_selector_init, + NULL /* value_table */ + }; - g_free (emfs->selected_path); - g_free (emfs->selected_uri); - g_free (emfs->created_uri); + type = g_type_register_static ( + GTK_TYPE_DIALOG, "EMFolderSelector", &type_info, 0); + } - G_OBJECT_CLASS (parent_class)->finalize (obj); + return type; } static void @@ -132,7 +123,9 @@ emfs_response (GtkWidget *dialog, int response, EMFolderSelector *emfs) return; g_object_set_data ((GObject *)emfs->emft, "select", GUINT_TO_POINTER (1)); - em_folder_utils_create_folder (NULL, emfs->emft, GTK_WINDOW (dialog)); + + /* FIXME Pass a parent window. */ + em_folder_utils_create_folder (NULL, emfs->emft, NULL); g_signal_stop_emission_by_name (emfs, "response"); } @@ -172,7 +165,7 @@ folder_activated_cb (EMFolderTree *emft, const char *path, const char *uri, EMFo void em_folder_selector_construct (EMFolderSelector *emfs, EMFolderTree *emft, guint32 flags, const char *title, const char *text, const char *oklabel) { - GtkWidget *label; + GtkWidget *widget; gtk_window_set_modal (GTK_WINDOW (emfs), FALSE); gtk_window_set_default_size (GTK_WINDOW (emfs), 350, 300); @@ -194,19 +187,29 @@ em_folder_selector_construct (EMFolderSelector *emfs, EMFolderTree *emft, guint3 gtk_dialog_set_response_sensitive (GTK_DIALOG (emfs), GTK_RESPONSE_OK, FALSE); gtk_dialog_set_default_response (GTK_DIALOG (emfs), GTK_RESPONSE_OK); + widget = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (widget), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); + gtk_box_pack_end ( + GTK_BOX (GTK_DIALOG (emfs)->vbox), widget, TRUE, TRUE, 6); + gtk_widget_show (widget); + emfs->emft = emft; - gtk_widget_show ((GtkWidget *) emft); + gtk_container_add (GTK_CONTAINER (widget), GTK_WIDGET (emft)); + gtk_widget_show (GTK_WIDGET (emft)); g_signal_connect (emfs->emft, "folder-selected", G_CALLBACK (folder_selected_cb), emfs); g_signal_connect (emfs->emft, "folder-activated", G_CALLBACK (folder_activated_cb), emfs); - gtk_box_pack_end (GTK_BOX (GTK_DIALOG (emfs)->vbox), (GtkWidget *)emft, TRUE, TRUE, 6); if (text != NULL) { - label = gtk_label_new (text); - gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); - gtk_widget_show (label); + widget = gtk_label_new (text); + gtk_label_set_justify (GTK_LABEL (widget), GTK_JUSTIFY_LEFT); + gtk_widget_show (widget); - gtk_box_pack_end (GTK_BOX (GTK_DIALOG (emfs)->vbox), label, FALSE, TRUE, 6); + gtk_box_pack_end (GTK_BOX (GTK_DIALOG (emfs)->vbox), widget, FALSE, TRUE, 6); } gtk_widget_grab_focus ((GtkWidget *) emfs->emft); diff --git a/mail/em-folder-selector.h b/mail/em-folder-selector.h index 06b1bc4520..a97831ec95 100644 --- a/mail/em-folder-selector.h +++ b/mail/em-folder-selector.h @@ -26,20 +26,30 @@ #include <gtk/gtk.h> -#ifdef cplusplus -extern "C" { -#pragma } -#endif /* cplusplus */ - -#define EM_TYPE_FOLDER_SELECTOR (em_folder_selector_get_type ()) -#define EM_FOLDER_SELECTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EM_TYPE_FOLDER_SELECTOR, EMFolderSelector)) -#define EM_FOLDER_SELECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EM_TYPE_FOLDER_SELECTOR, EMFolderSelectorClass)) -#define EM_IS_FOLDER_SELECTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EM_TYPE_FOLDER_SELECTOR)) -#define EM_IS_FOLDER_SELECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EM_TYPE_FOLDER_SELECTOR)) - -typedef struct _EMFolderSelector EMFolderSelector; +/* Standard GObject macros */ +#define EM_TYPE_FOLDER_SELECTOR \ + (em_folder_selector_get_type ()) +#define EM_FOLDER_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), EM_TYPE_FOLDER_SELECTOR, EMFolderSelector)) +#define EM_FOLDER_SELECTOR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), EM_TYPE_FOLDER_SELECTOR, EMFolderSelectorClass)) +#define EM_IS_FOLDER_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), EM_TYPE_FOLDER_SELECTOR)) +#define EM_IS_FOLDER_SELECTOR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), EM_TYPE_FOLDER_SELECTOR)) +#define EM_FOLDER_SELECTOR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), EM_TYPE_FOLDER_SELECTOR, EMFolderSelectorClass)) + +G_BEGIN_DECLS + +typedef struct _EMFolderSelector EMFolderSelector; +typedef struct _EMFolderSelectorClass EMFolderSelectorClass; typedef struct _EMFolderSelectorPrivate EMFolderSelectorPrivate; -typedef struct _EMFolderSelectorClass EMFolderSelectorClass; struct _EMFolderSelector { GtkDialog parent; @@ -87,8 +97,6 @@ const char *em_folder_selector_get_selected_path (EMFolderSelector *emfs); GList *em_folder_selector_get_selected_uris (EMFolderSelector *emfs); GList *em_folder_selector_get_selected_paths (EMFolderSelector *emfs); -#ifdef cplusplus -} -#endif /* cplusplus */ +G_END_DECLS #endif /* EM_FOLDER_SELECTOR_H */ diff --git a/mail/em-folder-tree-model.c b/mail/em-folder-tree-model.c index 8687b1cbd2..e774760ee3 100644 --- a/mail/em-folder-tree-model.c +++ b/mail/em-folder-tree-model.c @@ -10,7 +10,7 @@ * 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/> + * License along with the program; if not, see <http://www.gnu.org/licenses/> * * * Authors: @@ -20,9 +20,7 @@ * */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif +#include "em-folder-tree-model.h" #include <stdio.h> #include <string.h> @@ -37,8 +35,9 @@ #include <libedataserver/e-xml-utils.h> #include <libedataserver/e-data-server-util.h> -#include <e-util/e-util.h> -#include <e-util/e-mktemp.h> +#include "e-util/e-util.h" +#include "e-util/e-mktemp.h" +#include "e-util/e-account-utils.h" #include <glib/gi18n.h> @@ -50,138 +49,111 @@ #include "mail-mt.h" /* sigh, these 2 only needed for outbox total count checking - a mess */ -#include "mail-component.h" #include "mail-folder-cache.h" #include "em-utils.h" +#include "em-folder-utils.h" #include <camel/camel-folder.h> #include <camel/camel-vee-store.h> -#include "em-folder-tree-model.h" +#include "e-mail-shell-module.h" #define u(x) /* unread count debug */ #define d(x) +#define EM_FOLDER_TREE_MODEL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), EM_TYPE_FOLDER_TREE_MODEL, EMFolderTreeModelPrivate)) + +struct _EMFolderTreeModelPrivate { + gpointer shell_module; /* weak pointer */ +}; + static GType col_types[] = { G_TYPE_STRING, /* display name */ G_TYPE_POINTER, /* store object */ - G_TYPE_STRING, /* path */ + G_TYPE_STRING, /* full name */ + G_TYPE_STRING, /* icon name */ G_TYPE_STRING, /* uri */ G_TYPE_UINT, /* unread count */ G_TYPE_UINT, /* flags */ G_TYPE_BOOLEAN, /* is a store node */ + G_TYPE_BOOLEAN, /* is a folder node */ G_TYPE_BOOLEAN, /* has not-yet-loaded subfolders */ }; -/* GObject virtual method overrides */ -static void em_folder_tree_model_class_init (EMFolderTreeModelClass *klass); -static void em_folder_tree_model_init (EMFolderTreeModel *model); -static void em_folder_tree_model_finalize (GObject *obj); - -/* interface init methods */ -static void tree_model_iface_init (GtkTreeModelIface *iface); -static void tree_sortable_iface_init (GtkTreeSortableIface *iface); - static void account_changed (EAccountList *accounts, EAccount *account, gpointer user_data); static void account_removed (EAccountList *accounts, EAccount *account, gpointer user_data); enum { + PROP_0, + PROP_SHELL_MODULE +}; + +enum { LOADING_ROW, LOADED_ROW, FOLDER_ADDED, LAST_SIGNAL }; -static guint signals[LAST_SIGNAL] = { 0, }; -static GtkTreeStoreClass *parent_class = NULL; +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; -GType -em_folder_tree_model_get_type (void) +static void +store_info_free (EMFolderTreeModelStoreInfo *si) { - static GType type = 0; + camel_object_remove_event (si->store, si->created_id); + camel_object_remove_event (si->store, si->deleted_id); + camel_object_remove_event (si->store, si->renamed_id); + camel_object_remove_event (si->store, si->subscribed_id); + camel_object_remove_event (si->store, si->unsubscribed_id); - if (!type) { - static const GTypeInfo info = { - sizeof (EMFolderTreeModelClass), - NULL, /* base_class_init */ - NULL, /* base_class_finalize */ - (GClassInitFunc) em_folder_tree_model_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EMFolderTreeModel), - 0, /* n_preallocs */ - (GInstanceInitFunc) em_folder_tree_model_init, - }; - static const GInterfaceInfo tree_model_info = { - (GInterfaceInitFunc) tree_model_iface_init, - NULL, - NULL - }; - static const GInterfaceInfo sortable_info = { - (GInterfaceInitFunc) tree_sortable_iface_init, - NULL, - NULL - }; + g_free (si->display_name); + camel_object_unref (si->store); + gtk_tree_row_reference_free (si->row); + g_hash_table_destroy (si->full_hash); + g_free (si); +} + +static void +folder_tree_model_load_state (EMFolderTreeModel *model, + const gchar *filename) +{ + xmlNodePtr root, node; - type = g_type_register_static (GTK_TYPE_TREE_STORE, "EMFolderTreeModel", &info, 0); + if (model->state) + xmlFreeDoc (model->state); - g_type_add_interface_static (type, GTK_TYPE_TREE_MODEL, - &tree_model_info); - g_type_add_interface_static (type, GTK_TYPE_TREE_SORTABLE, - &sortable_info); + if ((model->state = e_xml_parse_file (filename)) != NULL) { + node = xmlDocGetRootElement (model->state); + if (!node || strcmp ((char *)node->name, "tree-state") != 0) { + /* it is not expected XML file, thus free it and use the default */ + xmlFreeDoc (model->state); + } else + return; } - return type; -} + /* setup some defaults - expand "Local Folders" and "Search Folders" */ + model->state = xmlNewDoc ((const unsigned char *)"1.0"); + root = xmlNewDocNode (model->state, NULL, (const unsigned char *)"tree-state", NULL); + xmlDocSetRootElement (model->state, root); + node = xmlNewChild (root, NULL, (const unsigned char *)"node", NULL); + xmlSetProp (node, (const unsigned char *)"name", (const unsigned char *)"local"); + xmlSetProp (node, (const unsigned char *)"expand", (const unsigned char *)"true"); -static void -em_folder_tree_model_class_init (EMFolderTreeModelClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - parent_class = g_type_class_ref (GTK_TYPE_TREE_STORE); - - object_class->finalize = em_folder_tree_model_finalize; - - /* signals */ - signals[LOADING_ROW] = - g_signal_new ("loading-row", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (EMFolderTreeModelClass, loading_row), - NULL, NULL, - e_marshal_VOID__POINTER_POINTER, - G_TYPE_NONE, 2, - G_TYPE_POINTER, - G_TYPE_POINTER); - - signals[LOADED_ROW] = - g_signal_new ("loaded-row", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (EMFolderTreeModelClass, loaded_row), - NULL, NULL, - e_marshal_VOID__POINTER_POINTER, - G_TYPE_NONE, 2, - G_TYPE_POINTER, - G_TYPE_POINTER); - - signals[FOLDER_ADDED] = - g_signal_new ("folder-added", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (EMFolderTreeModelClass, folder_added), - NULL, NULL, - e_marshal_VOID__STRING_STRING, - G_TYPE_NONE, 2, - G_TYPE_STRING, - G_TYPE_STRING); + node = xmlNewChild (root, NULL, (const unsigned char *)"node", NULL); + xmlSetProp (node, (const unsigned char *)"name", (const unsigned char *)"vfolder"); + xmlSetProp (node, (const unsigned char *)"expand", (const unsigned char *)"true"); } static int -sort_cb (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data) +folder_tree_model_sort (GtkTreeModel *model, + GtkTreeIter *a, + GtkTreeIter *b, + gpointer user_data) { extern CamelStore *vfolder_store; char *aname, *bname; @@ -190,13 +162,21 @@ sort_cb (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data guint32 aflags, bflags; int rv = -2; - gtk_tree_model_get (model, a, COL_BOOL_IS_STORE, &is_store, - COL_POINTER_CAMEL_STORE, &store, - COL_STRING_DISPLAY_NAME, &aname, COL_UINT_FLAGS, &aflags, -1); - gtk_tree_model_get (model, b, COL_STRING_DISPLAY_NAME, &bname, COL_UINT_FLAGS, &bflags, -1); + gtk_tree_model_get ( + model, a, + COL_BOOL_IS_STORE, &is_store, + COL_POINTER_CAMEL_STORE, &store, + COL_STRING_DISPLAY_NAME, &aname, + COL_UINT_FLAGS, &aflags, -1); + + gtk_tree_model_get ( + model, b, + COL_STRING_DISPLAY_NAME, &bname, + COL_UINT_FLAGS, &bflags, -1); if (is_store) { - /* On This Computer is always first and Search Folders is always last */ + /* On This Computer is always first, and Search Folders + * is always last. */ if (!strcmp (aname, _("On This Computer"))) rv = -1; else if (!strcmp (bname, _("On This Computer"))) @@ -206,13 +186,13 @@ sort_cb (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data else if (!strcmp (bname, _("Search Folders"))) rv = -1; } else if (store == vfolder_store) { - /* UNMATCHED is always last */ + /* UNMATCHED is always last. */ if (aname && !strcmp (aname, _("UNMATCHED"))) rv = 1; else if (bname && !strcmp (bname, _("UNMATCHED"))) rv = -1; } else { - /* Inbox is always first */ + /* Inbox is always first. */ if ((aflags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_INBOX) rv = -1; else if ((bflags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_INBOX) @@ -235,73 +215,56 @@ sort_cb (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data } static void -store_info_free (struct _EMFolderTreeModelStoreInfo *si) +folder_tree_model_set_shell_module (EMFolderTreeModel *model, + EShellModule *shell_module) { - camel_object_remove_event (si->store, si->created_id); - camel_object_remove_event (si->store, si->deleted_id); - camel_object_remove_event (si->store, si->renamed_id); - camel_object_remove_event (si->store, si->subscribed_id); - camel_object_remove_event (si->store, si->unsubscribed_id); + g_return_if_fail (model->priv->shell_module == NULL); - g_free (si->display_name); - camel_object_unref (si->store); - gtk_tree_row_reference_free (si->row); - g_hash_table_destroy (si->full_hash); - g_free (si); + model->priv->shell_module = shell_module; + + g_object_add_weak_pointer ( + G_OBJECT (shell_module), + &model->priv->shell_module); } static void -emft_model_unread_count_changed (GtkTreeModel *model, GtkTreeIter *iter) +folder_tree_model_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { - GtkTreeIter parent_iter; - GtkTreeIter child_iter = *iter; - - g_signal_handlers_block_by_func ( - model, emft_model_unread_count_changed, NULL); - - /* Folders are displayed with a bold weight to indicate that - they contain unread messages. We signal that parent rows - have changed here to update them. */ - - while (gtk_tree_model_iter_parent (model, &parent_iter, &child_iter)) { - GtkTreePath *parent_path; - - parent_path = gtk_tree_model_get_path (model, &parent_iter); - gtk_tree_model_row_changed (model, parent_path, &parent_iter); - gtk_tree_path_free (parent_path); - child_iter = parent_iter; + switch (property_id) { + case PROP_SHELL_MODULE: + folder_tree_model_set_shell_module ( + EM_FOLDER_TREE_MODEL (object), + g_value_get_object (value)); + return; } - g_signal_handlers_unblock_by_func ( - model, emft_model_unread_count_changed, NULL); + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -em_folder_tree_model_init (EMFolderTreeModel *model) +folder_tree_model_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { - model->store_hash = g_hash_table_new_full ( - g_direct_hash, g_direct_equal, - (GDestroyNotify) NULL, - (GDestroyNotify) store_info_free); - - model->uri_hash = g_hash_table_new_full ( - g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) gtk_tree_row_reference_free); - - gtk_tree_sortable_set_default_sort_func ((GtkTreeSortable *) model, sort_cb, NULL, NULL); + switch (property_id) { + case PROP_SHELL_MODULE: + g_value_set_object ( + value, em_folder_tree_model_get_shell_module ( + EM_FOLDER_TREE_MODEL (object))); + return; + } - model->accounts = mail_config_get_accounts (); - model->account_hash = g_hash_table_new (g_direct_hash, g_direct_equal); - model->account_changed_id = g_signal_connect (model->accounts, "account-changed", G_CALLBACK (account_changed), model); - model->account_removed_id = g_signal_connect (model->accounts, "account-removed", G_CALLBACK (account_removed), model); - //g_signal_connect (model, "row-changed", G_CALLBACK (emft_model_unread_count_changed), NULL); + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -em_folder_tree_model_finalize (GObject *obj) +folder_tree_model_finalize (GObject *object) { - EMFolderTreeModel *model = (EMFolderTreeModel *) obj; + EMFolderTreeModel *model = (EMFolderTreeModel *) object; g_free (model->filename); if (model->state) @@ -314,75 +277,231 @@ em_folder_tree_model_finalize (GObject *obj) g_signal_handler_disconnect (model->accounts, model->account_changed_id); g_signal_handler_disconnect (model->accounts, model->account_removed_id); - G_OBJECT_CLASS (parent_class)->finalize (obj); + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +folder_tree_model_constructed (GObject *object) +{ + EMFolderTreeModel *model = EM_FOLDER_TREE_MODEL (object); + EShellModule *shell_module; + const gchar *config_dir; + gchar *filename; + + shell_module = model->priv->shell_module; + config_dir = e_shell_module_get_config_dir (shell_module); + + filename = g_build_filename ( + config_dir, "folder-tree-expand-state.xml", NULL); + folder_tree_model_load_state (model, filename); + model->filename = filename; } +static void +folder_tree_model_class_init (EMFolderTreeModelClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMFolderTreeModelPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = folder_tree_model_set_property; + object_class->get_property = folder_tree_model_get_property; + object_class->finalize = folder_tree_model_finalize; + object_class->constructed = folder_tree_model_constructed; + + g_object_class_install_property ( + object_class, + PROP_SHELL_MODULE, + g_param_spec_object ( + "shell-module", + _("Shell Module"), + NULL, + E_TYPE_SHELL_MODULE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + signals[LOADING_ROW] = g_signal_new ( + "loading-row", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EMFolderTreeModelClass, loading_row), + NULL, NULL, + e_marshal_VOID__POINTER_POINTER, + G_TYPE_NONE, 2, + G_TYPE_POINTER, + G_TYPE_POINTER); + + signals[LOADED_ROW] = g_signal_new ( + "loaded-row", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EMFolderTreeModelClass, loaded_row), + NULL, NULL, + e_marshal_VOID__POINTER_POINTER, + G_TYPE_NONE, 2, + G_TYPE_POINTER, + G_TYPE_POINTER); + + signals[FOLDER_ADDED] = g_signal_new ( + "folder-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EMFolderTreeModelClass, folder_added), + NULL, NULL, + e_marshal_VOID__STRING_STRING, + G_TYPE_NONE, 2, + G_TYPE_STRING, + G_TYPE_STRING); +} + +static void +folder_tree_model_init (EMFolderTreeModel *model) +{ + GHashTable *store_hash; + GHashTable *uri_hash; + + store_hash = g_hash_table_new_full ( + g_direct_hash, g_direct_equal, + (GDestroyNotify) NULL, + (GDestroyNotify) store_info_free); + + uri_hash = g_hash_table_new_full ( + g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) gtk_tree_row_reference_free); + + model->priv = EM_FOLDER_TREE_MODEL_GET_PRIVATE (model); + model->store_hash = store_hash; + model->uri_hash = uri_hash; + + gtk_tree_store_set_column_types ( + GTK_TREE_STORE (model), NUM_COLUMNS, col_types); + gtk_tree_sortable_set_default_sort_func ( + GTK_TREE_SORTABLE (model), + folder_tree_model_sort, NULL, NULL); + gtk_tree_sortable_set_sort_column_id ( + GTK_TREE_SORTABLE (model), + GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, + GTK_SORT_ASCENDING); + + model->accounts = e_get_account_list (); + model->account_hash = g_hash_table_new (g_direct_hash, g_direct_equal); + model->account_changed_id = g_signal_connect ( + model->accounts, "account-changed", + G_CALLBACK (account_changed), model); + model->account_removed_id = g_signal_connect ( + model->accounts, "account-removed", + G_CALLBACK (account_removed), model); + //g_signal_connect ( + // model, "row-changed", + // G_CALLBACK (emft_model_unread_count_changed), NULL); +} static void tree_model_iface_init (GtkTreeModelIface *iface) { - ; } static void tree_sortable_iface_init (GtkTreeSortableIface *iface) { - ; +} + +GType +em_folder_tree_model_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMFolderTreeModelClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) folder_tree_model_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMFolderTreeModel), + 0, /* n_preallocs */ + (GInstanceInitFunc) folder_tree_model_init, + NULL /* value_table */ + }; + + static const GInterfaceInfo tree_model_info = { + (GInterfaceInitFunc) tree_model_iface_init, + NULL, + NULL + }; + + static const GInterfaceInfo sortable_info = { + (GInterfaceInitFunc) tree_sortable_iface_init, + NULL, + NULL + }; + + type = g_type_register_static ( + GTK_TYPE_TREE_STORE, "EMFolderTreeModel", + &type_info, 0); + + g_type_add_interface_static ( + type, GTK_TYPE_TREE_MODEL, &tree_model_info); + g_type_add_interface_static ( + type, GTK_TYPE_TREE_SORTABLE, &sortable_info); + } + + return type; } static void -em_folder_tree_model_load_state (EMFolderTreeModel *model, const char *filename) +emft_model_unread_count_changed (GtkTreeModel *model, GtkTreeIter *iter) { - xmlNodePtr root, node; + GtkTreeIter parent_iter; + GtkTreeIter child_iter = *iter; - if (model->state) - xmlFreeDoc (model->state); + g_signal_handlers_block_by_func ( + model, emft_model_unread_count_changed, NULL); - if ((model->state = e_xml_parse_file (filename)) != NULL) { - node = xmlDocGetRootElement (model->state); - if (!node || strcmp ((char *)node->name, "tree-state") != 0) { - /* it is not expected XML file, thus free it and use the default */ - xmlFreeDoc (model->state); - } else - return; - } + /* Folders are displayed with a bold weight to indicate that + they contain unread messages. We signal that parent rows + have changed here to update them. */ - /* setup some defaults - expand "Local Folders" and "Search Folders" */ - model->state = xmlNewDoc ((const unsigned char *)"1.0"); - root = xmlNewDocNode (model->state, NULL, (const unsigned char *)"tree-state", NULL); - xmlDocSetRootElement (model->state, root); + while (gtk_tree_model_iter_parent (model, &parent_iter, &child_iter)) { + GtkTreePath *parent_path; - node = xmlNewChild (root, NULL, (const unsigned char *)"node", NULL); - xmlSetProp (node, (const unsigned char *)"name", (const unsigned char *)"local"); - xmlSetProp (node, (const unsigned char *)"expand", (const unsigned char *)"true"); + parent_path = gtk_tree_model_get_path (model, &parent_iter); + gtk_tree_model_row_changed (model, parent_path, &parent_iter); + gtk_tree_path_free (parent_path); + child_iter = parent_iter; + } - node = xmlNewChild (root, NULL, (const unsigned char *)"node", NULL); - xmlSetProp (node, (const unsigned char *)"name", (const unsigned char *)"vfolder"); - xmlSetProp (node, (const unsigned char *)"expand", (const unsigned char *)"true"); + g_signal_handlers_unblock_by_func ( + model, emft_model_unread_count_changed, NULL); } + + EMFolderTreeModel * -em_folder_tree_model_new (const char *evolution_dir) +em_folder_tree_model_new (EShellModule *shell_module) { - EMFolderTreeModel *model; - char *filename; + g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), NULL); - model = g_object_new (EM_TYPE_FOLDER_TREE_MODEL, NULL); - gtk_tree_store_set_column_types ((GtkTreeStore *) model, NUM_COLUMNS, col_types); - gtk_tree_sortable_set_sort_column_id ((GtkTreeSortable *) model, - GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, - GTK_SORT_ASCENDING); + return g_object_new ( + EM_TYPE_FOLDER_TREE_MODEL, + "shell-module", shell_module, NULL); +} - filename = g_build_filename (evolution_dir, "mail", "config", "folder-tree-expand-state.xml", NULL); - em_folder_tree_model_load_state (model, filename); - model->filename = filename; +EShellModule * +em_folder_tree_model_get_shell_module (EMFolderTreeModel *model) +{ + g_return_val_if_fail (EM_IS_FOLDER_TREE_MODEL (model), NULL); - return model; + return model->priv->shell_module; } - static void account_changed (EAccountList *accounts, EAccount *account, gpointer user_data) { @@ -438,20 +557,26 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *ite struct _EMFolderTreeModelStoreInfo *si, CamelFolderInfo *fi, int fully_loaded) { + EShellModule *shell_module; GtkTreeRowReference *uri_row, *path_row; + GtkTreeStore *tree_store; unsigned int unread; GtkTreePath *path; GtkTreeIter sub; gboolean load = FALSE; - struct _CamelFolder *folder; + CamelFolder *folder; gboolean emitted = FALSE; const char *name; + const gchar *icon_name; guint32 flags; /* make sure we don't already know about it? */ if (g_hash_table_lookup (si->full_hash, fi->full_name)) return; - + + tree_store = GTK_TREE_STORE (model); + shell_module = model->priv->shell_module; + if (!fully_loaded) load = fi->child == NULL && !(fi->flags & (CAMEL_FOLDER_NOCHILDREN | CAMEL_FOLDER_NOINFERIORS)); @@ -468,7 +593,15 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *ite /* This is duplicated in mail-folder-cache too, should perhaps be functionised */ unread = fi->unread; if (mail_note_get_folder_from_uri(fi->uri, &folder) && folder) { - if (folder == mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX)) { + CamelFolder *local_drafts; + CamelFolder *local_outbox; + + local_drafts = e_mail_shell_module_get_folder ( + shell_module, E_MAIL_FOLDER_DRAFTS); + local_outbox = e_mail_shell_module_get_folder ( + shell_module, E_MAIL_FOLDER_OUTBOX); + + if (folder == local_outbox) { int total; if ((total = camel_folder_get_message_count (folder)) > 0) { @@ -480,7 +613,7 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *ite unread = total > 0 ? total : 0; } - if (folder == mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_DRAFTS)) { + if (folder == local_drafts) { int total; if ((total = camel_folder_get_message_count (folder)) > 0) { @@ -499,7 +632,7 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *ite /* TODO: maybe this should be handled by mail_get_folderinfo (except em-folder-tree doesn't use it, duh) */ flags = fi->flags; name = fi->name; - if (si->store == mail_component_peek_local_store(NULL)) { + if (si->store == e_mail_shell_module_get_local_store (shell_module)) { if (!strcmp(fi->full_name, "Drafts")) { name = _("Drafts"); } else if (!strcmp(fi->full_name, "Templates")) { @@ -516,31 +649,40 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *ite } } - gtk_tree_store_set ((GtkTreeStore *) model, iter, - COL_STRING_DISPLAY_NAME, name, - COL_POINTER_CAMEL_STORE, si->store, - COL_STRING_FULL_NAME, fi->full_name, - COL_STRING_URI, fi->uri, - COL_UINT_FLAGS, flags, - COL_BOOL_IS_STORE, FALSE, - COL_BOOL_LOAD_SUBDIRS, load, - -1); + /* Choose an icon name for the folder. */ + icon_name = em_folder_utils_get_icon_name (flags); + + gtk_tree_store_set ( + tree_store, iter, + COL_STRING_DISPLAY_NAME, name, + COL_POINTER_CAMEL_STORE, si->store, + COL_STRING_FULL_NAME, fi->full_name, + COL_STRING_ICON_NAME, icon_name, + COL_STRING_URI, fi->uri, + COL_UINT_FLAGS, flags, + COL_BOOL_IS_STORE, FALSE, + COL_BOOL_IS_FOLDER, TRUE, + COL_BOOL_LOAD_SUBDIRS, load, + -1); if (unread != ~0) - gtk_tree_store_set ((GtkTreeStore *) model, iter, COL_UINT_UNREAD, unread, -1); + gtk_tree_store_set (tree_store, iter, COL_UINT_UNREAD, unread, -1); if (load) { /* create a placeholder node for our subfolders... */ - gtk_tree_store_append ((GtkTreeStore *) model, &sub, iter); - gtk_tree_store_set ((GtkTreeStore *) model, &sub, - COL_STRING_DISPLAY_NAME, _("Loading..."), - COL_POINTER_CAMEL_STORE, NULL, - COL_STRING_FULL_NAME, NULL, - COL_BOOL_LOAD_SUBDIRS, FALSE, - COL_BOOL_IS_STORE, FALSE, - COL_STRING_URI, NULL, - COL_UINT_UNREAD, 0, - -1); + gtk_tree_store_append (tree_store, &sub, iter); + gtk_tree_store_set ( + tree_store, &sub, + COL_STRING_DISPLAY_NAME, _("Loading..."), + COL_POINTER_CAMEL_STORE, NULL, + COL_STRING_FULL_NAME, NULL, + COL_STRING_ICON_NAME, NULL, + COL_BOOL_LOAD_SUBDIRS, FALSE, + COL_BOOL_IS_STORE, FALSE, + COL_BOOL_IS_FOLDER, FALSE, + COL_STRING_URI, NULL, + COL_UINT_UNREAD, 0, + -1); path = gtk_tree_model_get_path ((GtkTreeModel *) model, iter); g_signal_emit (model, signals[LOADING_ROW], 0, path, iter); @@ -552,7 +694,7 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *ite fi = fi->child; do { - gtk_tree_store_append ((GtkTreeStore *) model, &sub, iter); + gtk_tree_store_append (tree_store, &sub, iter); if (!emitted) { path = gtk_tree_model_get_path ((GtkTreeModel *) model, iter); diff --git a/mail/em-folder-tree-model.h b/mail/em-folder-tree-model.h index 3247eee308..8236f3c303 100644 --- a/mail/em-folder-tree-model.h +++ b/mail/em-folder-tree-model.h @@ -20,42 +20,53 @@ * */ -#ifndef __EM_FOLDER_TREE_MODEL_H__ -#define __EM_FOLDER_TREE_MODEL_H__ +#ifndef EM_FOLDER_TREE_MODEL_H +#define EM_FOLDER_TREE_MODEL_H #include <gtk/gtk.h> - #include <libxml/tree.h> - #include <camel/camel-store.h> - #include <libedataserver/e-account-list.h> -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#define EM_TYPE_FOLDER_TREE_MODEL (em_folder_tree_model_get_type ()) -#define EM_FOLDER_TREE_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EM_TYPE_FOLDER_TREE_MODEL, EMFolderTreeModel)) -#define EM_FOLDER_TREE_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EM_TYPE_FOLDER_TREE_MODEL, EMFolderTreeModelClass)) -#define EM_IS_FOLDER_TREE_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EM_TYPE_FOLDER_TREE_MODEL)) -#define EM_IS_FOLDER_TREE_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EM_TYPE_FOLDER_TREE_MODEL)) -#define EM_FOLDER_TREE_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EM_TYPE_FOLDER_TREE_MODEL, EMFolderTreeModelClass)) +#include <shell/e-shell-module.h> + +/* Standard GObject macros */ +#define EM_TYPE_FOLDER_TREE_MODEL \ + (em_folder_tree_model_get_type ()) +#define EM_FOLDER_TREE_MODEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), EM_TYPE_FOLDER_TREE_MODEL, EMFolderTreeModel)) +#define EM_FOLDER_TREE_MODEL_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), EM_TYPE_FOLDER_TREE_MODEL, EMFolderTreeModelClass)) +#define EM_IS_FOLDER_TREE_MODEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), EM_TYPE_FOLDER_TREE_MODEL)) +#define EM_IS_FOLDER_TREE_MODEL_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), EM_TYPE_FOLDER_TREE_MODEL)) +#define EM_FOLDER_TREE_MODEL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), EM_TYPE_FOLDER_TREE_MODEL, EMFolderTreeModelClass)) + +G_BEGIN_DECLS typedef struct _EMFolderTreeModel EMFolderTreeModel; typedef struct _EMFolderTreeModelClass EMFolderTreeModelClass; +typedef struct _EMFolderTreeModelPrivate EMFolderTreeModelPrivate; typedef struct _EMFolderTreeModelStoreInfo EMFolderTreeModelStoreInfo; enum { COL_STRING_DISPLAY_NAME, /* string that appears in the tree */ COL_POINTER_CAMEL_STORE, /* CamelStore object */ COL_STRING_FULL_NAME, /* if node is a folder, the full path name of the folder, no leading / */ + COL_STRING_ICON_NAME, /* icon name for the folder */ COL_STRING_URI, /* the uri to get the store or folder object */ COL_UINT_UNREAD, /* unread count */ COL_UINT_FLAGS, /* FolderInfo.flags */ COL_BOOL_IS_STORE, /* toplevel store node? */ + COL_BOOL_IS_FOLDER, /* folder (not a store) */ COL_BOOL_LOAD_SUBDIRS, /* %TRUE only if the store/folder * has subfolders which have not yet * been added to the tree */ @@ -79,7 +90,8 @@ struct _EMFolderTreeModelStoreInfo { }; struct _EMFolderTreeModel { - GtkTreeStore parent_object; + GtkTreeStore parent; + EMFolderTreeModelPrivate *priv; char *filename; /* state filename */ xmlDocPtr state; /* saved expanded state from previous session */ @@ -114,11 +126,11 @@ struct _EMFolderTreeModelClass { }; -GType em_folder_tree_model_get_type (void); - - -EMFolderTreeModel *em_folder_tree_model_new (const char *evolution_dir); - +GType em_folder_tree_model_get_type (void); +EMFolderTreeModel * + em_folder_tree_model_new (EShellModule *shell_module); +EShellModule * em_folder_tree_model_get_shell_module + (EMFolderTreeModel *model); void em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *iter, struct _EMFolderTreeModelStoreInfo *si, @@ -147,8 +159,6 @@ void em_folder_tree_model_set_unread_count (EMFolderTreeModel *model, CamelStore gboolean em_folder_tree_model_is_type_inbox (EMFolderTreeModel *model, CamelStore *store, const char *full); char * em_folder_tree_model_get_folder_name (EMFolderTreeModel *model, CamelStore *store, const char *full); -#ifdef __cplusplus -} -#endif /* __cplusplus */ +G_END_DECLS -#endif /* __EM_FOLDER_TREE_MODEL_H__ */ +#endif /* EM_FOLDER_TREE_MODEL_H */ diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c index eebb15454c..eaf817a0b7 100644 --- a/mail/em-folder-tree.c +++ b/mail/em-folder-tree.c @@ -48,6 +48,7 @@ #include <camel/camel-file-utils.h> #include <camel/camel-stream-fs.h> +#include "e-util/e-account-utils.h" #include "e-util/e-mktemp.h" #include "e-util/e-request.h" #include "e-util/e-icon-factory.h" @@ -60,7 +61,6 @@ #include "mail-ops.h" #include "mail-tools.h" #include "mail-config.h" -#include "mail-component.h" #include "mail-send-recv.h" #include "mail-vfolder.h" @@ -73,8 +73,14 @@ #include "em-folder-properties.h" #include "em-event.h" +#include "e-mail-shell-module.h" + #define d(x) +#define EM_FOLDER_TREE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), EM_TYPE_FOLDER_TREE, EMFolderTreePrivate)) + struct _selected_uri { char *key; /* store:path or account/path */ char *uri; @@ -83,7 +89,6 @@ struct _selected_uri { }; struct _EMFolderTreePrivate { - GtkTreeView *treeview; EMFolderTreeModel *model; GSList *select_uris; /* selected_uri structures of each path pending selection. */ @@ -114,6 +119,7 @@ struct _EMFolderTreePrivate { enum { FOLDER_ACTIVATED, /* aka double-clicked or user hit enter */ FOLDER_SELECTED, + POPUP_EVENT, LAST_SIGNAL }; @@ -151,11 +157,6 @@ static guint signals[LAST_SIGNAL] = { 0 }; extern CamelSession *session; -static void em_folder_tree_class_init (EMFolderTreeClass *klass); -static void em_folder_tree_init (EMFolderTree *emft); -static void em_folder_tree_destroy (GtkObject *obj); -static void em_folder_tree_finalize (GObject *obj); - static gboolean emft_save_state (EMFolderTree *emft); static void emft_queue_save_state (EMFolderTree *emft); @@ -175,68 +176,170 @@ struct _emft_selection_data { gboolean set; }; -static GtkVBoxClass *parent_class = NULL; +static gpointer parent_class = NULL; -GType -em_folder_tree_get_type (void) +static void +folder_tree_emit_popup_event (EMFolderTree *emft, + GdkEvent *event) { - static GType type = 0; + g_signal_emit (emft, signals[POPUP_EVENT], 0, event); +} - if (!type) { - static const GTypeInfo info = { - sizeof (EMFolderTreeClass), - NULL, /* base_class_init */ - NULL, /* base_class_finalize */ - (GClassInitFunc) em_folder_tree_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EMFolderTree), - 0, /* n_preallocs */ - (GInstanceInitFunc) em_folder_tree_init, - }; +static void +emft_free_select_uri (struct _selected_uri *u) +{ + g_free (u->uri); + if (u->store) + camel_object_unref (u->store); + g_free (u->key); + g_free (u->path); + g_free (u); +} - type = g_type_register_static (GTK_TYPE_VBOX, "EMFolderTree", &info, 0); +static void +folder_tree_finalize (GObject *object) +{ + EMFolderTreePrivate *priv; + + priv = EM_FOLDER_TREE_GET_PRIVATE (object); + + if (priv->select_uris != NULL) { + g_slist_foreach ( + priv->select_uris, + (GFunc) emft_free_select_uri, NULL); + g_slist_free (priv->select_uris); + g_hash_table_destroy (priv->select_uris_table); + priv->select_uris = NULL; } - return type; + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +em_folder_tree_destroy (GtkObject *object) +{ + EMFolderTreePrivate *priv; + + priv = EM_FOLDER_TREE_GET_PRIVATE (object); + + if (priv->loaded_row_id != 0) { + g_signal_handler_disconnect (priv->model, priv->loaded_row_id); + priv->loaded_row_id = 0; + } + + if (priv->save_state_id != 0) { + g_source_remove (priv->save_state_id); + emft_save_state (EM_FOLDER_TREE (object)); + } + + if (priv->autoscroll_id != 0) { + g_source_remove (priv->autoscroll_id); + priv->autoscroll_id = 0; + } + + if (priv->autoexpand_id != 0) { + gtk_tree_row_reference_free (priv->autoexpand_row); + priv->autoexpand_row = NULL; + + g_source_remove (priv->autoexpand_id); + priv->autoexpand_id = 0; + } + + priv->model = NULL; + + /* Chain up to parent's destroy() method. */ + GTK_OBJECT_CLASS (parent_class)->destroy (object); } static void -em_folder_tree_class_init (EMFolderTreeClass *klass) +folder_tree_class_init (EMFolderTreeClass *class) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + GObjectClass *object_class; + GtkObjectClass *gtk_object_class; + GtkWidgetClass *widget_class; - parent_class = g_type_class_ref (GTK_TYPE_VBOX); + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMFolderTreePrivate)); - object_class->finalize = em_folder_tree_finalize; + object_class = G_OBJECT_CLASS (class); + object_class->finalize = folder_tree_finalize; + + gtk_object_class = GTK_OBJECT_CLASS (class); gtk_object_class->destroy = em_folder_tree_destroy; + widget_class = GTK_WIDGET_CLASS (class); widget_class->popup_menu = emft_popup_menu; - signals[FOLDER_SELECTED] = - g_signal_new ("folder-selected", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (EMFolderTreeClass, folder_selected), - NULL, NULL, - e_marshal_VOID__STRING_STRING_UINT, - G_TYPE_NONE, 3, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_UINT); - - signals[FOLDER_ACTIVATED] = - g_signal_new ("folder-activated", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (EMFolderTreeClass, folder_activated), - NULL, NULL, - e_marshal_VOID__STRING_STRING, - G_TYPE_NONE, 2, - G_TYPE_STRING, - G_TYPE_STRING); + signals[FOLDER_SELECTED] = g_signal_new ( + "folder-selected", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EMFolderTreeClass, folder_selected), + NULL, NULL, + e_marshal_VOID__STRING_STRING_UINT, + G_TYPE_NONE, 3, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_UINT); + + signals[FOLDER_ACTIVATED] = g_signal_new ( + "folder-activated", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EMFolderTreeClass, folder_activated), + NULL, NULL, + e_marshal_VOID__STRING_STRING, + G_TYPE_NONE, 2, + G_TYPE_STRING, + G_TYPE_STRING); + + signals[POPUP_EVENT] = g_signal_new ( + "popup-event", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (EMFolderTreeClass, popup_event), + NULL, NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, 1, + GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); +} + +static void +folder_tree_init (EMFolderTree *emft) +{ + GHashTable *select_uris_table; + + select_uris_table = g_hash_table_new (g_str_hash, g_str_equal); + + emft->priv = EM_FOLDER_TREE_GET_PRIVATE (emft); + emft->priv->select_uris_table = select_uris_table; +} + +GType +em_folder_tree_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMFolderTreeClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) folder_tree_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMFolderTree), + 0, /* n_preallocs */ + (GInstanceInitFunc) folder_tree_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_TREE_VIEW, "EMFolderTree", &type_info, 0); + } + + return type; } static gboolean @@ -261,87 +364,6 @@ subdirs_contain_unread (GtkTreeModel *model, GtkTreeIter *root) return FALSE; } - -enum { - FOLDER_ICON_NORMAL, - FOLDER_ICON_INBOX, - FOLDER_ICON_OUTBOX, - FOLDER_ICON_TRASH, - FOLDER_ICON_JUNK, - FOLDER_ICON_SHARED_TO_ME, - FOLDER_ICON_SHARED_BY_ME, - FOLDER_ICON_SENT, - FOLDER_ICON_VIRTUAL, - FOLDER_ICON_LAST -}; - -static GdkPixbuf *folder_icons[FOLDER_ICON_LAST]; - -static void -render_pixbuf (GtkTreeViewColumn *column, GtkCellRenderer *renderer, - GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) -{ - static gboolean initialised = FALSE; - GdkPixbuf *pixbuf = NULL; - gboolean is_store; - guint32 flags; - EMEventTargetCustomIcon *target; - const char *folder_name; - - if (!initialised) { - folder_icons[FOLDER_ICON_NORMAL] = e_icon_factory_get_icon ("folder", E_ICON_SIZE_MENU); - folder_icons[FOLDER_ICON_INBOX] = e_icon_factory_get_icon ("mail-inbox", E_ICON_SIZE_MENU); - folder_icons[FOLDER_ICON_OUTBOX] = e_icon_factory_get_icon ("mail-outbox", E_ICON_SIZE_MENU); - folder_icons[FOLDER_ICON_TRASH] = e_icon_factory_get_icon ("user-trash", E_ICON_SIZE_MENU); - folder_icons[FOLDER_ICON_JUNK] = e_icon_factory_get_icon ("mail-mark-junk", E_ICON_SIZE_MENU); - folder_icons[FOLDER_ICON_SHARED_TO_ME] = e_icon_factory_get_icon ("stock_shared-to-me", E_ICON_SIZE_MENU); - folder_icons[FOLDER_ICON_SHARED_BY_ME] = e_icon_factory_get_icon ("stock_shared-by-me", E_ICON_SIZE_MENU); - folder_icons[FOLDER_ICON_SENT] = e_icon_factory_get_icon ("mail-sent", E_ICON_SIZE_MENU); - folder_icons[FOLDER_ICON_VIRTUAL] = e_icon_factory_get_icon ("folder-saved-search", E_ICON_SIZE_MENU); - - initialised = TRUE; - } - - gtk_tree_model_get (model, iter, COL_BOOL_IS_STORE, &is_store, COL_UINT_FLAGS, &flags, -1); - - if (!is_store) { - switch((flags & CAMEL_FOLDER_TYPE_MASK)) { - case CAMEL_FOLDER_TYPE_INBOX: - pixbuf = folder_icons[FOLDER_ICON_INBOX]; - break; - case CAMEL_FOLDER_TYPE_OUTBOX: - pixbuf = folder_icons[FOLDER_ICON_OUTBOX]; - break; - case CAMEL_FOLDER_TYPE_TRASH: - pixbuf = folder_icons[FOLDER_ICON_TRASH]; - break; - case CAMEL_FOLDER_TYPE_JUNK: - pixbuf = folder_icons[FOLDER_ICON_JUNK]; - break; - case CAMEL_FOLDER_TYPE_SENT: - pixbuf = folder_icons[FOLDER_ICON_SENT]; - break; - default: - if (flags & CAMEL_FOLDER_SHARED_TO_ME) - pixbuf = folder_icons[FOLDER_ICON_SHARED_TO_ME]; - else if (flags & CAMEL_FOLDER_SHARED_BY_ME) - pixbuf = folder_icons[FOLDER_ICON_SHARED_BY_ME]; - else if (flags & CAMEL_FOLDER_VIRTUAL) - pixbuf = folder_icons[FOLDER_ICON_VIRTUAL]; - else { - pixbuf = folder_icons[FOLDER_ICON_NORMAL]; - g_object_set (renderer, "pixbuf", pixbuf, "visible", !is_store, NULL); - gtk_tree_model_get (model, iter, COL_STRING_FULL_NAME, &folder_name, -1); - target = em_event_target_new_custom_icon (em_event_peek(), renderer, folder_name, EM_EVENT_CUSTOM_ICON); - e_event_emit ((EEvent *)em_event_peek (), "folder.customicon", (EEventTarget *) target); - return; - } - } - } - - g_object_set (renderer, "pixbuf", pixbuf, "visible", !is_store, NULL); -} - static void render_display_name (GtkTreeViewColumn *column, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) @@ -413,90 +435,6 @@ emft_select_func(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath * return (flags & emft->priv->excluded) == 0; } -static void -emft_free_select_uri(void *v, void *data) -{ - struct _selected_uri *u = v; - - g_free(u->uri); - if (u->store) - camel_object_unref(u->store); - g_free(u->key); - g_free(u->path); - g_free(u); -} - -static void -em_folder_tree_init (EMFolderTree *emft) -{ - struct _EMFolderTreePrivate *priv; - - priv = g_new0 (struct _EMFolderTreePrivate, 1); - priv->select_uris_table = g_hash_table_new(g_str_hash, g_str_equal); - priv->treeview = NULL; - priv->model = NULL; - priv->drag_row = NULL; - - emft->priv = priv; -} - -static void -em_folder_tree_finalize (GObject *obj) -{ - EMFolderTree *emft = (EMFolderTree *) obj; - - if (emft->priv->select_uris) { - g_slist_foreach(emft->priv->select_uris, emft_free_select_uri, emft); - g_slist_free(emft->priv->select_uris); - g_hash_table_destroy(emft->priv->select_uris_table); - emft->priv->select_uris = NULL; - } - - g_free (emft->priv); - - G_OBJECT_CLASS (parent_class)->finalize (obj); -} - -static void -em_folder_tree_destroy (GtkObject *obj) -{ - EMFolderTree *emft = (EMFolderTree *) obj; - struct _EMFolderTreePrivate *priv = emft->priv; - - if (priv->loading_row_id != 0) { - g_signal_handler_disconnect (priv->model, priv->loading_row_id); - priv->loading_row_id = 0; - } - - if (priv->loaded_row_id != 0) { - g_signal_handler_disconnect (priv->model, priv->loaded_row_id); - priv->loaded_row_id = 0; - } - - if (priv->save_state_id != 0) { - g_source_remove (priv->save_state_id); - emft_save_state (emft); - } - - if (priv->autoscroll_id != 0) { - g_source_remove (priv->autoscroll_id); - priv->autoscroll_id = 0; - } - - if (priv->autoexpand_id != 0) { - gtk_tree_row_reference_free (priv->autoexpand_row); - priv->autoexpand_row = NULL; - - g_source_remove (priv->autoexpand_id); - priv->autoexpand_id = 0; - } - - priv->treeview = NULL; - priv->model = NULL; - - GTK_OBJECT_CLASS (parent_class)->destroy (obj); -} - static GtkTreeView * folder_tree_new (EMFolderTree *emft, EMFolderTreeModel *model) { @@ -510,7 +448,10 @@ folder_tree_new (EMFolderTree *emft, EMFolderTreeModel *model) gconf = mail_config_get_gconf_client (); side_bar_search = gconf_client_get_bool (gconf, "/apps/evolution/mail/display/side_bar_search", NULL); - tree = gtk_tree_view_new_with_model ((GtkTreeModel *) model); + /* FIXME[KILL-BONOBO] Gross hack */ + tree = GTK_WIDGET (emft); + gtk_tree_view_set_model ( + GTK_TREE_VIEW (tree), GTK_TREE_MODEL (model)); GTK_WIDGET_SET_FLAGS(tree, GTK_CAN_FOCUS); column = gtk_tree_view_column_new (); @@ -518,7 +459,10 @@ folder_tree_new (EMFolderTree *emft, EMFolderTreeModel *model) renderer = gtk_cell_renderer_pixbuf_new (); gtk_tree_view_column_pack_start (column, renderer, FALSE); - gtk_tree_view_column_set_cell_data_func (column, renderer, render_pixbuf, NULL, NULL); + gtk_tree_view_column_add_attribute ( + column, renderer, "icon-name", COL_STRING_ICON_NAME); + gtk_tree_view_column_add_attribute ( + column, renderer, "visible", COL_BOOL_IS_FOLDER); renderer = gtk_cell_renderer_text_new (); if (!gconf_client_get_bool (gconf, "/apps/evolution/mail/display/no_folder_dots", NULL)) @@ -542,39 +486,30 @@ em_folder_tree_construct (EMFolderTree *emft, EMFolderTreeModel *model) { struct _EMFolderTreePrivate *priv = emft->priv; GtkTreeSelection *selection; - GtkWidget *scrolled; - - scrolled = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), GTK_SHADOW_IN); priv->model = model; - priv->treeview = folder_tree_new (emft, model); - gtk_widget_show ((GtkWidget *) priv->treeview); + folder_tree_new (emft, model); + gtk_widget_show (GTK_WIDGET (emft)); - g_signal_connect (priv->treeview, "row-expanded", G_CALLBACK (emft_tree_row_expanded), emft); - g_signal_connect (priv->treeview, "test-collapse-row", G_CALLBACK (emft_tree_test_collapse_row), emft); - g_signal_connect (priv->treeview, "row-activated", G_CALLBACK (emft_tree_row_activated), emft); - g_signal_connect (priv->treeview, "button-press-event", G_CALLBACK (emft_tree_button_press), emft); - g_signal_connect (priv->treeview, "key-press-event", G_CALLBACK (emft_tree_user_event), emft); + g_signal_connect (emft, "row-expanded", G_CALLBACK (emft_tree_row_expanded), emft); + g_signal_connect (emft, "test-collapse-row", G_CALLBACK (emft_tree_test_collapse_row), emft); + g_signal_connect (emft, "row-activated", G_CALLBACK (emft_tree_row_activated), emft); + g_signal_connect (emft, "button-press-event", G_CALLBACK (emft_tree_button_press), emft); + g_signal_connect (emft, "key-press-event", G_CALLBACK (emft_tree_user_event), emft); - selection = gtk_tree_view_get_selection ((GtkTreeView *) priv->treeview); + selection = gtk_tree_view_get_selection ((GtkTreeView *) emft); g_signal_connect (selection, "changed", G_CALLBACK (emft_tree_selection_changed), emft); - - gtk_container_add ((GtkContainer *) scrolled, (GtkWidget *) priv->treeview); - gtk_widget_show (scrolled); - - gtk_box_pack_start ((GtkBox *) emft, scrolled, TRUE, TRUE, 0); } GtkWidget * -em_folder_tree_new (void) +em_folder_tree_new (EShellModule *shell_module) { EMFolderTreeModel *model; EMFolderTree *emft; - model = em_folder_tree_model_new (e_get_user_data_dir ()); + g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), NULL); + + model = e_mail_shell_module_get_folder_tree_model (shell_module); emft = (EMFolderTree *) em_folder_tree_new_with_model (model); g_object_unref (model); @@ -586,18 +521,20 @@ static void emft_select_uri(EMFolderTree *emft, GtkTreePath *path, struct _selected_uri *u) { struct _EMFolderTreePrivate *priv = emft->priv; + GtkTreeView *tree_view; GtkTreeSelection *selection; - selection = gtk_tree_view_get_selection(priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); gtk_tree_selection_select_path(selection, path); if (!priv->cursor_set) { - gtk_tree_view_set_cursor (priv->treeview, path, NULL, FALSE); + gtk_tree_view_set_cursor (tree_view, path, NULL, FALSE); priv->cursor_set = TRUE; } - gtk_tree_view_scroll_to_cell (priv->treeview, path, NULL, TRUE, 0.8f, 0.0f); + gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.8f, 0.0f); g_hash_table_remove(priv->select_uris_table, u->key); priv->select_uris = g_slist_remove(priv->select_uris, u); - emft_free_select_uri((void *)u, NULL); + emft_free_select_uri(u); } static void @@ -606,7 +543,9 @@ emft_expand_node (EMFolderTreeModel *model, const char *key, EMFolderTree *emft) struct _EMFolderTreePrivate *priv = emft->priv; struct _EMFolderTreeModelStoreInfo *si; extern CamelStore *vfolder_store; + EShellModule *shell_module; GtkTreeRowReference *row; + GtkTreeView *tree_view; GtkTreePath *path; EAccount *account; CamelStore *store; @@ -624,7 +563,10 @@ emft_expand_node (EMFolderTreeModel *model, const char *key, EMFolderTree *emft) memcpy (uid, key, n); uid[n] = '\0'; - if ((account = mail_config_get_account_by_uid (uid)) && account->enabled) { + tree_view = GTK_TREE_VIEW (emft); + shell_module = em_folder_tree_model_get_shell_module (model); + + if ((account = e_get_account_by_uid (uid)) && account->enabled) { CamelException ex; camel_exception_init (&ex); @@ -639,7 +581,7 @@ emft_expand_node (EMFolderTreeModel *model, const char *key, EMFolderTree *emft) camel_object_ref (store); } else if (!strcmp (uid, "local")) { - if (!(store = mail_component_peek_local_store (NULL))) + if (!(store = e_mail_shell_module_get_local_store (shell_module))) return; camel_object_ref (store); @@ -661,7 +603,7 @@ emft_expand_node (EMFolderTreeModel *model, const char *key, EMFolderTree *emft) row = si->row; path = gtk_tree_row_reference_get_path (row); - gtk_tree_view_expand_to_path (priv->treeview, path); + gtk_tree_view_expand_to_path (tree_view, path); u = g_hash_table_lookup(emft->priv->select_uris_table, key); if (u) @@ -675,6 +617,7 @@ emft_maybe_expand_row (EMFolderTreeModel *model, GtkTreePath *tree_path, GtkTree { struct _EMFolderTreePrivate *priv = emft->priv; struct _EMFolderTreeModelStoreInfo *si; + GtkTreeView *tree_view; gboolean is_store; CamelStore *store; EAccount *account; @@ -683,6 +626,8 @@ emft_maybe_expand_row (EMFolderTreeModel *model, GtkTreePath *tree_path, GtkTree struct _selected_uri *u; gboolean is_expanded; + tree_view = GTK_TREE_VIEW (emft); + gtk_tree_model_get ((GtkTreeModel *) model, iter, COL_STRING_FULL_NAME, &full_name, COL_POINTER_CAMEL_STORE, &store, @@ -690,7 +635,7 @@ emft_maybe_expand_row (EMFolderTreeModel *model, GtkTreePath *tree_path, GtkTree -1); si = g_hash_table_lookup (model->store_hash, store); - if ((account = mail_config_get_account_by_name (si->display_name))) { + if ((account = e_get_account_by_name (si->display_name))) { key = g_strdup_printf ("%s/%s", account->uid, full_name ? full_name : ""); } else if (CAMEL_IS_VEE_STORE (store)) { /* vfolder store */ @@ -704,8 +649,8 @@ emft_maybe_expand_row (EMFolderTreeModel *model, GtkTreePath *tree_path, GtkTree u = g_hash_table_lookup(priv->select_uris_table, key); if (is_expanded || u) { if (is_expanded) { - gtk_tree_view_expand_to_path (priv->treeview, tree_path); - gtk_tree_view_expand_row (priv->treeview, tree_path, FALSE); + gtk_tree_view_expand_to_path (tree_view, tree_path); + gtk_tree_view_expand_row (tree_view, tree_path, FALSE); } else { char *c = strrchr (key, '/'); @@ -736,7 +681,7 @@ em_folder_tree_new_with_model (EMFolderTreeModel *model) emft->priv->loading_row_id = g_signal_connect (model, "loading-row", G_CALLBACK (emft_maybe_expand_row), emft); emft->priv->loaded_row_id = g_signal_connect (model, "loaded-row", G_CALLBACK (emft_maybe_expand_row), emft); - a11y = gtk_widget_get_accessible (GTK_WIDGET (emft->priv->treeview)); + a11y = gtk_widget_get_accessible (GTK_WIDGET (emft)); atk_object_set_name (a11y, _("Mail Folder Tree")); return (GtkWidget *) emft; @@ -1018,6 +963,7 @@ tree_drag_data_received(GtkWidget *widget, GdkDragContext *context, int x, int y { struct _EMFolderTreePrivate *priv = emft->priv; GtkTreeViewDropPosition pos; + GtkTreeView *tree_view; GtkTreePath *dest_path; struct _DragDataReceivedAsync *m; gboolean is_store; @@ -1026,7 +972,9 @@ tree_drag_data_received(GtkWidget *widget, GdkDragContext *context, int x, int y char *full_name; int i; - if (!gtk_tree_view_get_dest_row_at_pos (priv->treeview, x, y, &dest_path, &pos)) + tree_view = GTK_TREE_VIEW (emft); + + if (!gtk_tree_view_get_dest_row_at_pos (tree_view, x, y, &dest_path, &pos)) return; /* this means we are receiving no data */ @@ -1104,6 +1052,7 @@ emft_drop_target(EMFolderTree *emft, GdkDragContext *context, GtkTreePath *path) struct _EMFolderTreePrivate *p = emft->priv; char *full_name = NULL, *uri = NULL, *src_uri = NULL; CamelStore *local, *sstore, *dstore; + EShellModule *shell_module; GdkAtom atom = GDK_NONE; gboolean is_store; GtkTreeIter iter; @@ -1121,7 +1070,8 @@ emft_drop_target(EMFolderTree *emft, GdkDragContext *context, GtkTreePath *path) COL_POINTER_CAMEL_STORE, &dstore, COL_STRING_URI, &uri, -1); - local = mail_component_peek_local_store (NULL); + shell_module = em_folder_tree_model_get_shell_module (p->model); + local = e_mail_shell_module_get_local_store (shell_module); targets = context->targets; @@ -1299,10 +1249,13 @@ tree_drag_drop (GtkWidget *widget, GdkDragContext *context, int x, int y, guint { struct _EMFolderTreePrivate *priv = emft->priv; GtkTreeViewColumn *column; + GtkTreeView *tree_view; int cell_x, cell_y; GtkTreePath *path; GdkAtom target; + tree_view = GTK_TREE_VIEW (emft); + if (priv->autoscroll_id != 0) { g_source_remove (priv->autoscroll_id); priv->autoscroll_id = 0; @@ -1316,7 +1269,7 @@ tree_drag_drop (GtkWidget *widget, GdkDragContext *context, int x, int y, guint priv->autoexpand_id = 0; } - if (!gtk_tree_view_get_path_at_pos (priv->treeview, x, y, &path, &column, &cell_x, &cell_y)) + if (!gtk_tree_view_get_path_at_pos (tree_view, x, y, &path, &column, &cell_x, &cell_y)) return FALSE; target = emft_drop_target(emft, context, path); @@ -1344,6 +1297,9 @@ static void tree_drag_leave (GtkWidget *widget, GdkDragContext *context, guint time, EMFolderTree *emft) { struct _EMFolderTreePrivate *priv = emft->priv; + GtkTreeView *tree_view; + + tree_view = GTK_TREE_VIEW (emft); if (priv->autoscroll_id != 0) { g_source_remove (priv->autoscroll_id); @@ -1358,7 +1314,7 @@ tree_drag_leave (GtkWidget *widget, GdkDragContext *context, guint time, EMFolde priv->autoexpand_id = 0; } - gtk_tree_view_set_drag_dest_row(emft->priv->treeview, NULL, GTK_TREE_VIEW_DROP_BEFORE); + gtk_tree_view_set_drag_dest_row(tree_view, NULL, GTK_TREE_VIEW_DROP_BEFORE); } @@ -1367,19 +1323,20 @@ tree_drag_leave (GtkWidget *widget, GdkDragContext *context, guint time, EMFolde static gboolean tree_autoscroll (EMFolderTree *emft) { - struct _EMFolderTreePrivate *priv = emft->priv; GtkAdjustment *vadjustment; + GtkTreeView *tree_view; GdkRectangle rect; GdkWindow *window; int offset, y; float value; /* get the y pointer position relative to the treeview */ - window = gtk_tree_view_get_bin_window (priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + window = gtk_tree_view_get_bin_window (tree_view); gdk_window_get_pointer (window, NULL, &y, NULL); /* rect is in coorinates relative to the scrolled window relative to the treeview */ - gtk_tree_view_get_visible_rect (priv->treeview, &rect); + gtk_tree_view_get_visible_rect (tree_view, &rect); /* move y into the same coordinate system as rect */ y += rect.y; @@ -1391,7 +1348,7 @@ tree_autoscroll (EMFolderTree *emft) return TRUE; } - vadjustment = gtk_tree_view_get_vadjustment (priv->treeview); + vadjustment = gtk_tree_view_get_vadjustment (tree_view); value = CLAMP (vadjustment->value + offset, 0.0, vadjustment->upper - vadjustment->page_size); gtk_adjustment_set_value (vadjustment, value); @@ -1403,10 +1360,12 @@ static gboolean tree_autoexpand (EMFolderTree *emft) { struct _EMFolderTreePrivate *priv = emft->priv; + GtkTreeView *tree_view; GtkTreePath *path; + tree_view = GTK_TREE_VIEW (emft); path = gtk_tree_row_reference_get_path (priv->autoexpand_row); - gtk_tree_view_expand_row (priv->treeview, path, FALSE); + gtk_tree_view_expand_row (tree_view, path, FALSE); gtk_tree_path_free (path); return TRUE; @@ -1418,13 +1377,16 @@ tree_drag_motion (GtkWidget *widget, GdkDragContext *context, int x, int y, guin struct _EMFolderTreePrivate *priv = emft->priv; GtkTreeModel *model = (GtkTreeModel *) priv->model; GtkTreeViewDropPosition pos; + GtkTreeView *tree_view; GdkDragAction action = 0; GtkTreePath *path; GtkTreeIter iter; GdkAtom target; int i; - if (!gtk_tree_view_get_dest_row_at_pos(priv->treeview, x, y, &path, &pos)) + tree_view = GTK_TREE_VIEW (emft); + + if (!gtk_tree_view_get_dest_row_at_pos(tree_view, x, y, &path, &pos)) return FALSE; if (priv->autoscroll_id == 0) @@ -1432,7 +1394,7 @@ tree_drag_motion (GtkWidget *widget, GdkDragContext *context, int x, int y, guin gtk_tree_model_get_iter (model, &iter, path); - if (gtk_tree_model_iter_has_child (model, &iter) && !gtk_tree_view_row_expanded (priv->treeview, path)) { + if (gtk_tree_model_iter_has_child (model, &iter) && !gtk_tree_view_row_expanded (tree_view, path)) { if (priv->autoexpand_id != 0) { GtkTreePath *autoexpand_path; @@ -1468,10 +1430,10 @@ tree_drag_motion (GtkWidget *widget, GdkDragContext *context, int x, int y, guin action = context->suggested_action; if (action == GDK_ACTION_COPY && (context->actions & GDK_ACTION_MOVE)) action = GDK_ACTION_MOVE; - gtk_tree_view_set_drag_dest_row(priv->treeview, path, GTK_TREE_VIEW_DROP_INTO_OR_AFTER); + gtk_tree_view_set_drag_dest_row(tree_view, path, GTK_TREE_VIEW_DROP_INTO_OR_AFTER); break; default: - gtk_tree_view_set_drag_dest_row(priv->treeview, path, GTK_TREE_VIEW_DROP_INTO_OR_AFTER); + gtk_tree_view_set_drag_dest_row(tree_view, path, GTK_TREE_VIEW_DROP_INTO_OR_AFTER); action = context->suggested_action; break; } @@ -1491,11 +1453,14 @@ void em_folder_tree_enable_drag_and_drop (EMFolderTree *emft) { struct _EMFolderTreePrivate *priv; + GtkTreeView *tree_view; static int setup = 0; int i; g_return_if_fail (EM_IS_FOLDER_TREE (emft)); + tree_view = GTK_TREE_VIEW (emft); + priv = emft->priv; if (!setup) { for (i=0; i<NUM_DRAG_TYPES; i++) @@ -1507,23 +1472,27 @@ em_folder_tree_enable_drag_and_drop (EMFolderTree *emft) setup = 1; } - gtk_drag_source_set((GtkWidget *)priv->treeview, GDK_BUTTON1_MASK, drag_types, NUM_DRAG_TYPES, GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK); - gtk_drag_dest_set((GtkWidget *)priv->treeview, GTK_DEST_DEFAULT_ALL, drop_types, NUM_DROP_TYPES, GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK); + gtk_drag_source_set((GtkWidget *)tree_view, GDK_BUTTON1_MASK, drag_types, NUM_DRAG_TYPES, GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK); + gtk_drag_dest_set((GtkWidget *)tree_view, GTK_DEST_DEFAULT_ALL, drop_types, NUM_DROP_TYPES, GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK); - g_signal_connect (priv->treeview, "drag-begin", G_CALLBACK (tree_drag_begin), emft); - g_signal_connect (priv->treeview, "drag-data-delete", G_CALLBACK (tree_drag_data_delete), emft); - g_signal_connect (priv->treeview, "drag-data-get", G_CALLBACK (tree_drag_data_get), emft); - g_signal_connect (priv->treeview, "drag-data-received", G_CALLBACK (tree_drag_data_received), emft); - g_signal_connect (priv->treeview, "drag-drop", G_CALLBACK (tree_drag_drop), emft); - g_signal_connect (priv->treeview, "drag-end", G_CALLBACK (tree_drag_end), emft); - g_signal_connect (priv->treeview, "drag-leave", G_CALLBACK (tree_drag_leave), emft); - g_signal_connect (priv->treeview, "drag-motion", G_CALLBACK (tree_drag_motion), emft); + g_signal_connect (tree_view, "drag-begin", G_CALLBACK (tree_drag_begin), emft); + g_signal_connect (tree_view, "drag-data-delete", G_CALLBACK (tree_drag_data_delete), emft); + g_signal_connect (tree_view, "drag-data-get", G_CALLBACK (tree_drag_data_get), emft); + g_signal_connect (tree_view, "drag-data-received", G_CALLBACK (tree_drag_data_received), emft); + g_signal_connect (tree_view, "drag-drop", G_CALLBACK (tree_drag_drop), emft); + g_signal_connect (tree_view, "drag-end", G_CALLBACK (tree_drag_end), emft); + g_signal_connect (tree_view, "drag-leave", G_CALLBACK (tree_drag_leave), emft); + g_signal_connect (tree_view, "drag-motion", G_CALLBACK (tree_drag_motion), emft); } void em_folder_tree_set_multiselect (EMFolderTree *tree, gboolean mode) { - GtkTreeSelection *sel = gtk_tree_view_get_selection ((GtkTreeView *) tree->priv->treeview); + GtkTreeSelection *sel; + GtkTreeView *tree_view; + + tree_view = GTK_TREE_VIEW (tree); + sel = gtk_tree_view_get_selection (tree_view); tree->priv->do_multiselect = mode; gtk_tree_selection_set_mode (sel, mode ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE); @@ -1543,10 +1512,14 @@ void em_folder_tree_set_excluded_func(EMFolderTree *emft, EMFTExcludeFunc exclud GList * em_folder_tree_get_selected_uris (EMFolderTree *emft) { - GtkTreeSelection *selection = gtk_tree_view_get_selection (emft->priv->treeview); + GtkTreeSelection *selection; + GtkTreeView *tree_view; + GtkTreeModel *model; GList *list = NULL, *rows, *l; GSList *sl; - GtkTreeModel *model; + + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); /* at first, add lost uris */ for (sl = emft->priv->select_uris; sl; sl = g_slist_next(sl)) @@ -1583,9 +1556,13 @@ get_selected_uris_path_iterate (GtkTreeModel *model, GtkTreePath *treepath, GtkT GList * em_folder_tree_get_selected_paths (EMFolderTree *emft) { - GtkTreeSelection *selection = gtk_tree_view_get_selection (emft->priv->treeview); + GtkTreeSelection *selection; + GtkTreeView *tree_view; GList *list = NULL; + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); + gtk_tree_selection_selected_foreach (selection, get_selected_uris_path_iterate, &list); return list; @@ -1596,7 +1573,7 @@ emft_clear_selected_list(EMFolderTree *emft) { struct _EMFolderTreePrivate *priv = emft->priv; - g_slist_foreach(priv->select_uris, emft_free_select_uri, emft); + g_slist_foreach(priv->select_uris, (GFunc) emft_free_select_uri, NULL); g_slist_free(priv->select_uris); g_hash_table_destroy(priv->select_uris_table); priv->select_uris = NULL; @@ -1734,13 +1711,13 @@ emft_get_folder_info__done (struct _EMFolderTreeGetFolderInfo *m) struct _EMFolderTreeModelStoreInfo *si; GtkTreeIter root, iter, titer; CamelFolderInfo *fi; + GtkTreeView *tree_view; GtkTreeStore *model; GtkTreePath *path; gboolean is_store; /* check that we haven't been destroyed */ - if (priv->treeview == NULL) - return; + g_return_if_fail (GTK_IS_TREE_VIEW (m->emft)); /* check that our parent folder hasn't been deleted/unsubscribed */ if (!gtk_tree_row_reference_valid (m->root)) @@ -1751,7 +1728,8 @@ emft_get_folder_info__done (struct _EMFolderTreeGetFolderInfo *m) return; } - model = (GtkTreeStore *) gtk_tree_view_get_model (priv->treeview); + tree_view = GTK_TREE_VIEW (m->emft); + model = (GtkTreeStore *) gtk_tree_view_get_model (tree_view); path = gtk_tree_row_reference_get_path (m->root); gtk_tree_model_get_iter ((GtkTreeModel *) model, &root, path); @@ -1759,7 +1737,7 @@ emft_get_folder_info__done (struct _EMFolderTreeGetFolderInfo *m) /* if we had an error, then we need to re-set the load subdirs state and collapse the node */ if (!m->fi && camel_exception_is_set(&m->base.ex)) { gtk_tree_store_set(model, &root, COL_BOOL_LOAD_SUBDIRS, TRUE, -1); - gtk_tree_view_collapse_row (priv->treeview, path); + gtk_tree_view_collapse_row (tree_view, path); gtk_tree_path_free (path); return; } @@ -1798,7 +1776,7 @@ emft_get_folder_info__done (struct _EMFolderTreeGetFolderInfo *m) if (is_store) { path = gtk_tree_model_get_path ((GtkTreeModel *) model, &root); - gtk_tree_view_collapse_row (priv->treeview, path); + gtk_tree_view_collapse_row (tree_view, path); emft_queue_save_state (m->emft); gtk_tree_path_free (path); return; @@ -1854,7 +1832,7 @@ emft_update_model_expanded_state (struct _EMFolderTreePrivate *priv, GtkTreeIter -1); si = g_hash_table_lookup (priv->model->store_hash, store); - if ((account = mail_config_get_account_by_name (si->display_name))) { + if ((account = e_get_account_by_name (si->display_name))) { key = g_strdup_printf ("%s/%s", account->uid, full_name ? full_name : ""); } else if (CAMEL_IS_VEE_STORE (store)) { /* vfolder store */ @@ -1957,53 +1935,6 @@ emft_tree_row_activated (GtkTreeView *treeview, GtkTreePath *tree_path, GtkTreeV g_free(uri); } -#if 0 -static void -emft_popup_view (GtkWidget *item, EMFolderTree *emft) -{ - -} - -static void -emft_popup_open_new (GtkWidget *item, EMFolderTree *emft) -{ -} -#endif - -static void -emft_popup_copy(EPopup *ep, EPopupItem *item, void *data) -{ - EMFolderTree *emft = data; - CamelFolderInfo *fi = NULL; - - /* FIXME: use async apis */ - if ((fi = em_folder_tree_get_selected_folder_info (emft)) != NULL) - em_folder_utils_copy_folder(fi, FALSE); -} - -static void -emft_popup_move(EPopup *ep, EPopupItem *item, void *data) -{ - EMFolderTree *emft = data; - CamelFolderInfo *fi = NULL; - - /* FIXME: use async apis */ - if ((fi = em_folder_tree_get_selected_folder_info (emft)) != NULL) - em_folder_utils_copy_folder(fi, TRUE); -} - -static void -emft_popup_new_folder (EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderTree *emft = data; - CamelFolderInfo *fi; - - if ((fi = em_folder_tree_get_selected_folder_info (emft)) != NULL) { - em_folder_utils_create_folder (fi, emft, NULL); - camel_folder_info_free(fi); - } -} - static void selfunc (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) { @@ -2030,247 +1961,15 @@ emft_selection_get_selected (GtkTreeSelection *selection, GtkTreeModel **model, } } -static void -emft_popup_delete_folder (EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderTree *emft = data; - CamelFolder *folder; - - if ((folder = em_folder_tree_get_selected_folder (emft)) != NULL) { - em_folder_utils_delete_folder(folder); - } -} - -static void -emft_popup_rename_folder (EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderTree *emft = data; - CamelFolder *folder; - - if ((folder = em_folder_tree_get_selected_folder (emft)) != NULL) { - em_folder_utils_rename_folder(folder); - } -} - -static void -emft_popup_refresh_folder (EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderTree *emft = data; - CamelFolder *folder; - - if ((folder = em_folder_tree_get_selected_folder (emft)) != NULL) - mail_refresh_folder(folder, NULL, NULL); -} - -static void -emft_popup_flush_outbox (EPopup *ep, EPopupItem *pitem, void *data) -{ - mail_send (); -} - -static void -emft_popup_empty_trash (EPopup *ep, EPopupItem *pitem, void *data) -{ - em_utils_empty_trash (data); -} - -static void -emft_popup_properties (EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderTree *emft = data; - struct _EMFolderTreePrivate *priv = emft->priv; - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - char *uri; - - selection = gtk_tree_view_get_selection (priv->treeview); - if (!emft_selection_get_selected (selection, &model, &iter)) - return; - - gtk_tree_model_get (model, &iter, COL_STRING_URI, &uri, -1); - em_folder_properties_show (NULL, NULL, uri); - g_free (uri); -} - -static void -emft_popup_uvfolder (EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderTree *emft = data; - CamelFolder *folder; - - if ((folder = em_folder_tree_get_selected_folder (emft)) != NULL) { - char *meta = camel_object_meta_get(folder, "vfolder:unread"); - if (!meta || strcmp(meta, "false") == 0) - camel_object_meta_set(folder, "vfolder:unread", "true"); - else - camel_object_meta_set(folder, "vfolder:unread", "false"); - camel_object_state_write (folder); - g_free (meta); - } -} - -static EPopupItem emft_popup_items[] = { -#if 0 - { E_POPUP_ITEM, "00.emc.00", N_("_View"), emft_popup_view, NULL, NULL, EM_POPUP_FOLDER_SELECT }, - { E_POPUP_ITEM, "00.emc.01", N_("Open in _New Window"), emft_popup_open_new, NULL, NULL, EM_POPUP_FOLDER_SELECT }, - - { E_POPUP_BAR, "10.emc" }, -#endif - /* FIXME: need to disable for nochildren folders */ - { E_POPUP_ITEM, "10.emc.00", N_("_New Folder..."), emft_popup_new_folder, NULL, "folder-new", 0, EM_POPUP_FOLDER_INFERIORS }, - - { E_POPUP_ITEM, "10.emc.05", N_("_Copy..."), emft_popup_copy, NULL, "folder-copy", 0, EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_SELECT }, - { E_POPUP_ITEM, "10.emc.06", N_("_Move..."), emft_popup_move, NULL, "folder-move", 0, EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_DELETE }, - - /* FIXME: need to disable for undeletable folders */ - { E_POPUP_BAR, "20.emc" }, - { E_POPUP_ITEM, "20.emc.01", N_("_Delete"), emft_popup_delete_folder, NULL, "edit-delete", 0, EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_DELETE }, - - { E_POPUP_BAR, "30.emc" }, - { E_POPUP_ITEM, "30.emc.02", N_("_Rename..."), emft_popup_rename_folder, NULL, NULL, 0, EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_DELETE }, - { E_POPUP_ITEM, "30.emc.03", N_("Re_fresh"), emft_popup_refresh_folder, NULL, "view-refresh", EM_POPUP_FOLDER_NONSTATIC, EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_SELECT}, - { E_POPUP_ITEM, "30.emc.04", N_("Fl_ush Outbox"), emft_popup_flush_outbox, NULL, "mail-send", EM_POPUP_FOLDER_OUTBOX, 0 }, - - - { E_POPUP_BAR, "99.emc" }, - { E_POPUP_ITEM, "99.emc.00", N_("_Properties"), emft_popup_properties, NULL, "document-properties", 0, EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_SELECT } -}; -static EPopupItem trash_popup_item = {E_POPUP_ITEM, "30.emc.05", N_("_Empty Trash"), emft_popup_empty_trash,NULL,NULL, 1, EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_SELECT}; - -static void -emft_popup_free(EPopup *ep, GSList *items, void *data) -{ - g_slist_free(items); -} - static gboolean -emft_popup (EMFolderTree *emft, GdkEvent *event) +emft_popup_menu (GtkWidget *widget) { - GtkTreeView *treeview; - GtkTreeSelection *selection; - CamelStore *local, *store; - EMPopupTargetFolder *target; - GtkTreeModel *model; - GtkTreeIter iter; - GSList *menus = NULL; - guint32 info_flags = 0; - guint32 flags = 0; - guint32 folder_type_flags = 0; - gboolean isstore; - char *uri, *full_name; - GtkMenu *menu; - EMPopup *emp; - CamelFolder *selfolder = NULL; - int i; - - treeview = emft->priv->treeview; - - /* this centralises working out when the user's done something */ - emft_tree_user_event(treeview, (GdkEvent *)event, emft); - - /* FIXME: we really need the folderinfo to build a proper menu */ - selection = gtk_tree_view_get_selection (treeview); - if (!emft_selection_get_selected (selection, &model, &iter)) - return FALSE; - - gtk_tree_model_get (model, &iter, COL_POINTER_CAMEL_STORE, &store, - COL_STRING_URI, &uri, COL_STRING_FULL_NAME, &full_name, - COL_BOOL_IS_STORE, &isstore, COL_UINT_FLAGS, &folder_type_flags, -1); - - /* Stores have full_name == NULL, otherwise its just a placeholder */ - /* NB: This is kind of messy */ - if (!isstore && full_name == NULL) { - g_free (uri); - return FALSE; - } - - /* TODO: em_popup_target_folder_new? */ - if (isstore) { - flags |= EM_POPUP_FOLDER_STORE; - } else { - flags |= EM_POPUP_FOLDER_FOLDER; - - local = mail_component_peek_local_store (NULL); - - /* don't allow deletion of special local folders */ - if (!(store == local && is_special_local_folder (full_name))) - flags |= EM_POPUP_FOLDER_DELETE; - - /* hack for vTrash/vJunk */ - if (!strcmp (full_name, CAMEL_VTRASH_NAME) || !strcmp (full_name, CAMEL_VJUNK_NAME)) - info_flags |= CAMEL_FOLDER_VIRTUAL | CAMEL_FOLDER_NOINFERIORS; - - selfolder = em_folder_tree_get_selected_folder (emft); - - if (folder_type_flags & CAMEL_FOLDER_SYSTEM) - flags &= ~EM_POPUP_FOLDER_DELETE; - - if (em_utils_folder_is_outbox (selfolder, NULL)) - info_flags |= CAMEL_FOLDER_TYPE_OUTBOX; - } - - /** @HookPoint-EMPopup: Folder Tree Context Menu - * @Id: org.gnome.evolution.mail.foldertree.popup - * @Class: org.gnome.evolution.mail.popup:1.0 - * @Target: EMPopupTargetFolder - * - * This is the context menu shown on the folder tree. - */ - emp = em_popup_new ("org.gnome.evolution.mail.foldertree.popup"); - - /* FIXME: pass valid fi->flags here */ - target = em_popup_target_new_folder (emp, uri, info_flags, flags); - - for (i = 0; i < sizeof (emft_popup_items) / sizeof (emft_popup_items[0]); i++) - menus = g_slist_prepend (menus, &emft_popup_items[i]); - - if ((folder_type_flags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_TRASH) - menus = g_slist_prepend (menus, &trash_popup_item); - if (!isstore && strstr(uri, "vfolder")) { - /* This is a vfolder, so lets add hacked up menu item. */ - static EPopupItem *item = NULL; - char *meta = camel_object_meta_get (selfolder, "vfolder:unread"); - - if (!item) - item = g_malloc0(sizeof(*item)); - if (meta && (strcmp (meta, "true") == 0)) - item->type = E_POPUP_TOGGLE | E_POPUP_ACTIVE; - else - item->type = E_POPUP_TOGGLE & ~E_POPUP_ACTIVE; - item->path = "99.emc.99"; - item->label = _("_Unread Search Folder"); - item->activate = emft_popup_uvfolder; - item->visible = EM_POPUP_FOLDER_SELECT; - item->user_data = NULL; - menus = g_slist_prepend (menus, item); - g_free (meta); - } - - e_popup_add_items ((EPopup *)emp, menus, NULL, emft_popup_free, emft); - - menu = e_popup_create_menu_once ((EPopup *)emp, (EPopupTarget *)target, 0); - - if (event == NULL || event->type == GDK_KEY_PRESS) { - /* FIXME: menu pos function */ - gtk_menu_popup (menu, NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time()); - } else { - gtk_menu_popup (menu, NULL, NULL, NULL, NULL, event->button.button, event->button.time); - } - - g_free (full_name); - g_free (uri); + folder_tree_emit_popup_event (EM_FOLDER_TREE (widget), NULL); return TRUE; } static gboolean -emft_popup_menu (GtkWidget *widget) -{ - return emft_popup (EM_FOLDER_TREE (widget), NULL); -} - -static gboolean emft_tree_button_press (GtkTreeView *treeview, GdkEventButton *event, EMFolderTree *emft) { GtkTreeSelection *selection; @@ -2298,7 +1997,9 @@ emft_tree_button_press (GtkTreeView *treeview, GdkEventButton *event, EMFolderTr gtk_tree_path_free (tree_path); - return emft_popup (emft, (GdkEvent *)event); + folder_tree_emit_popup_event (emft, (GdkEvent *) event); + + return TRUE; } /* This is called for keyboard and mouse events, it seems the only way @@ -2357,6 +2058,7 @@ em_folder_tree_set_selected (EMFolderTree *emft, const char *uri, gboolean expan void em_folder_tree_select_next_path (EMFolderTree *emft, gboolean skip_read_folders) { + GtkTreeView *tree_view; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter, parent, child; @@ -2366,7 +2068,8 @@ em_folder_tree_select_next_path (EMFolderTree *emft, gboolean skip_read_folders) g_return_if_fail (EM_IS_FOLDER_TREE (emft)); - selection = gtk_tree_view_get_selection(emft->priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection(tree_view); if (gtk_tree_selection_get_selected(selection, &model, &iter)) { current_path = gtk_tree_model_get_path (model, &iter); @@ -2401,16 +2104,16 @@ em_folder_tree_select_next_path (EMFolderTree *emft, gboolean skip_read_folders) } if (path) { - if (!gtk_tree_view_row_expanded (emft->priv->treeview, path)) - gtk_tree_view_expand_to_path (emft->priv->treeview, path); + if (!gtk_tree_view_row_expanded (tree_view, path)) + gtk_tree_view_expand_to_path (tree_view, path); gtk_tree_selection_select_path(selection, path); if (!priv->cursor_set) { - gtk_tree_view_set_cursor (priv->treeview, path, NULL, FALSE); + gtk_tree_view_set_cursor (tree_view, path, NULL, FALSE); priv->cursor_set = TRUE; } - gtk_tree_view_scroll_to_cell (priv->treeview, path, NULL, TRUE, 0.5f, 0.0f); + gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.5f, 0.0f); } return; } @@ -2436,6 +2139,7 @@ get_last_child (GtkTreeModel *model, GtkTreeIter *iter) void em_folder_tree_select_prev_path (EMFolderTree *emft, gboolean skip_read_folders) { + GtkTreeView *tree_view; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter, child; @@ -2445,7 +2149,8 @@ em_folder_tree_select_prev_path (EMFolderTree *emft, gboolean skip_read_folders) g_return_if_fail (EM_IS_FOLDER_TREE (emft)); - selection = gtk_tree_view_get_selection(emft->priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); if (gtk_tree_selection_get_selected(selection, &model, &iter)){ @@ -2479,17 +2184,17 @@ em_folder_tree_select_prev_path (EMFolderTree *emft, gboolean skip_read_folders) } if (path) { - if (!gtk_tree_view_row_expanded (priv->treeview, path)) { - gtk_tree_view_expand_to_path (priv->treeview, path); + if (!gtk_tree_view_row_expanded (tree_view, path)) { + gtk_tree_view_expand_to_path (tree_view, path); } gtk_tree_selection_select_path(selection, path); if (!priv->cursor_set) { - gtk_tree_view_set_cursor (priv->treeview, path, NULL, FALSE); + gtk_tree_view_set_cursor (tree_view, path, NULL, FALSE); priv->cursor_set = TRUE; } - gtk_tree_view_scroll_to_cell (priv->treeview, path, NULL, TRUE, 0.5f, 0.0f); + gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.5f, 0.0f); } return; } @@ -2498,6 +2203,7 @@ em_folder_tree_select_prev_path (EMFolderTree *emft, gboolean skip_read_folders) char * em_folder_tree_get_selected_uri (EMFolderTree *emft) { + GtkTreeView *tree_view; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter; @@ -2505,7 +2211,9 @@ em_folder_tree_get_selected_uri (EMFolderTree *emft) g_return_val_if_fail (EM_IS_FOLDER_TREE (emft), NULL); - selection = gtk_tree_view_get_selection(emft->priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); + if (gtk_tree_selection_get_selected(selection, &model, &iter)) gtk_tree_model_get(model, &iter, COL_STRING_URI, &uri, -1); @@ -2515,6 +2223,7 @@ em_folder_tree_get_selected_uri (EMFolderTree *emft) char * em_folder_tree_get_selected_path (EMFolderTree *emft) { + GtkTreeView *tree_view; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter; @@ -2522,7 +2231,9 @@ em_folder_tree_get_selected_path (EMFolderTree *emft) g_return_val_if_fail (EM_IS_FOLDER_TREE (emft), NULL); - selection = gtk_tree_view_get_selection(emft->priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); + if (gtk_tree_selection_get_selected(selection, &model, &iter)) gtk_tree_model_get(model, &iter, COL_STRING_FULL_NAME, &name, -1); @@ -2532,6 +2243,7 @@ em_folder_tree_get_selected_path (EMFolderTree *emft) CamelFolder * em_folder_tree_get_selected_folder (EMFolderTree *emft) { + GtkTreeView *tree_view; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter; @@ -2544,7 +2256,9 @@ em_folder_tree_get_selected_folder (EMFolderTree *emft) camel_exception_init (&ex); - selection = gtk_tree_view_get_selection(emft->priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); + if (gtk_tree_selection_get_selected(selection, &model, &iter)) gtk_tree_model_get (model, &iter, COL_POINTER_CAMEL_STORE, &store, COL_STRING_FULL_NAME, &full_name, -1); @@ -2560,6 +2274,7 @@ em_folder_tree_get_selected_folder (EMFolderTree *emft) CamelFolderInfo * em_folder_tree_get_selected_folder_info (EMFolderTree *emft) { + GtkTreeView *tree_view; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter; @@ -2572,7 +2287,9 @@ em_folder_tree_get_selected_folder_info (EMFolderTree *emft) camel_exception_init (&ex); - selection = gtk_tree_view_get_selection(emft->priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); + if (gtk_tree_selection_get_selected(selection, &model, &iter)) gtk_tree_model_get (model, &iter, COL_POINTER_CAMEL_STORE, &store, COL_STRING_FULL_NAME, &full_name, diff --git a/mail/em-folder-tree.h b/mail/em-folder-tree.h index e89be47506..f0dfe72d10 100644 --- a/mail/em-folder-tree.h +++ b/mail/em-folder-tree.h @@ -21,28 +21,38 @@ * */ -#ifndef __EM_FOLDER_TREE_H__ -#define __EM_FOLDER_TREE_H__ +#ifndef EM_FOLDER_TREE_H +#define EM_FOLDER_TREE_H #include <gtk/gtk.h> #include <camel/camel-store.h> - -#include "mail/em-folder-tree-model.h" - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#define EM_TYPE_FOLDER_TREE (em_folder_tree_get_type ()) -#define EM_FOLDER_TREE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EM_TYPE_FOLDER_TREE, EMFolderTree)) -#define EM_FOLDER_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EM_TYPE_FOLDER_TREE, EMFolderTreeClass)) -#define EM_IS_FOLDER_TREE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EM_TYPE_FOLDER_TREE)) -#define EM_IS_FOLDER_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EM_TYPE_FOLDER_TREE)) -#define EM_FOLDER_TREE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EM_TYPE_FOLDER_TREE, EMFolderTreeClass)) +#include <shell/e-shell-module.h> +#include <mail/em-folder-tree-model.h> + +/* Standard GObject macros */ +#define EM_TYPE_FOLDER_TREE \ + (em_folder_tree_get_type ()) +#define EM_FOLDER_TREE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), EM_TYPE_FOLDER_TREE, EMFolderTree)) +#define EM_FOLDER_TREE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), EM_TYPE_FOLDER_TREE, EMFolderTreeClass)) +#define EM_IS_FOLDER_TREE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), EM_TYPE_FOLDER_TREE)) +#define EM_IS_FOLDER_TREE_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), EM_TYPE_FOLDER_TREE)) +#define EM_FOLDER_TREE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), EM_TYPE_FOLDER_TREE, EMFolderTreeClass)) + +G_BEGIN_DECLS typedef struct _EMFolderTree EMFolderTree; typedef struct _EMFolderTreeClass EMFolderTreeClass; +typedef struct _EMFolderTreePrivate EMFolderTreePrivate; /* not sure this api is the best, but its the easiest to implement and will cover what we need */ #define EMFT_EXCLUDE_NOSELECT CAMEL_FOLDER_NOSELECT @@ -54,22 +64,27 @@ typedef struct _EMFolderTreeClass EMFolderTreeClass; typedef gboolean (*EMFTExcludeFunc)(EMFolderTree *emft, GtkTreeModel *model, GtkTreeIter *iter, void *data); struct _EMFolderTree { - GtkVBox parent_object; - - struct _EMFolderTreePrivate *priv; + GtkTreeView parent_object; + EMFolderTreePrivate *priv; }; struct _EMFolderTreeClass { - GtkVBoxClass parent_class; + GtkTreeViewClass parent_class; /* signals */ - void (* folder_activated) (EMFolderTree *emft, const char *full_name, const char *uri); - void (* folder_selected) (EMFolderTree *emft, const char *full_name, const char *uri, guint32 flags); + void (*folder_activated) (EMFolderTree *emft, + const gchar *full_name, + const gchar *uri); + void (*folder_selected) (EMFolderTree *emft, + const gchar *full_name, + const gchar *uri, + guint32 flags); + void (*popup_event) (EMFolderTree *emft); }; GType em_folder_tree_get_type (void); -GtkWidget *em_folder_tree_new (void); +GtkWidget *em_folder_tree_new (EShellModule *shell_module); GtkWidget *em_folder_tree_new_with_model (EMFolderTreeModel *model); void em_folder_tree_enable_drag_and_drop (EMFolderTree *emft); @@ -95,8 +110,6 @@ EMFolderTreeModelStoreInfo *em_folder_tree_get_model_storeinfo (EMFolderTree *em gboolean em_folder_tree_create_folder (EMFolderTree *emft, const char *full_name, const char *uri); -#ifdef __cplusplus -} -#endif /* __cplusplus */ +G_END_DECLS -#endif /* __EM_FOLDER_TREE_H__ */ +#endif /* EM_FOLDER_TREE_H */ diff --git a/mail/em-folder-utils.c b/mail/em-folder-utils.c index 80d4fde143..ff93c9b5a9 100644 --- a/mail/em-folder-utils.c +++ b/mail/em-folder-utils.c @@ -40,8 +40,6 @@ #include <glib/gi18n.h> #include <camel/camel-session.h> -#include <camel/camel-store.h> -#include <camel/camel-folder.h> #include <camel/camel-vee-store.h> #include <camel/camel-vtrash-folder.h> #include <camel/camel-stream-mem.h> @@ -59,7 +57,6 @@ #include "mail-ops.h" #include "mail-tools.h" #include "mail-config.h" -#include "mail-component.h" #include "mail-vfolder.h" #include "mail-folder-cache.h" @@ -72,6 +69,8 @@ #include "em-folder-selection.h" #include "em-folder-properties.h" +#include "e-mail-shell-module.h" + #define d(x) extern CamelSession *session; @@ -270,6 +269,7 @@ emfu_copy_folder_selected (const char *uri, void *data) { struct _copy_folder_data *cfd = data; CamelStore *fromstore = NULL, *tostore = NULL; + CamelStore *local_store; char *tobase = NULL; CamelException ex; CamelURL *url; @@ -281,13 +281,15 @@ emfu_copy_folder_selected (const char *uri, void *data) camel_exception_init (&ex); + local_store = e_mail_shell_module_get_local_store (mail_shell_module); + if (!(fromstore = camel_session_get_store (session, cfd->fi->uri, &ex))) { e_error_run(NULL, cfd->delete?"mail:no-move-folder-notexist":"mail:no-copy-folder-notexist", cfd->fi->full_name, uri, ex.desc, NULL); goto fail; } - if (cfd->delete && fromstore == mail_component_peek_local_store (NULL) && emfu_is_special_local_folder (cfd->fi->full_name)) { + if (cfd->delete && fromstore == local_store && emfu_is_special_local_folder (cfd->fi->full_name)) { GtkWidget *w = e_error_new (NULL, "mail:no-rename-special-folder", cfd->fi->full_name, NULL); em_utils_show_error_silent (w); @@ -399,13 +401,13 @@ emfu_delete_response (GtkWidget *dialog, int response, gpointer data) void em_folder_utils_delete_folder (CamelFolder *folder) { - CamelStore *local; + CamelStore *local_store; GtkWidget *dialog; int flags = 0; - local = mail_component_peek_local_store (NULL); + local_store = e_mail_shell_module_get_local_store (mail_shell_module); - if (folder->parent_store == local && emfu_is_special_local_folder (folder->full_name)) { + if (folder->parent_store == local_store && emfu_is_special_local_folder (folder->full_name)) { dialog = e_error_new (NULL, "mail:no-delete-special-folder", folder->full_name, NULL); em_utils_show_error_silent (dialog); return; @@ -434,14 +436,14 @@ em_folder_utils_rename_folder (CamelFolder *folder) { char *prompt, *new_name; const char *p; - CamelStore *local; + CamelStore *local_store; gboolean done = FALSE; size_t base_len; - local = mail_component_peek_local_store (NULL); + local_store = e_mail_shell_module_get_local_store (mail_shell_module); /* don't allow user to rename one of the special local folders */ - if (folder->parent_store == local && emfu_is_special_local_folder (folder->full_name)) { + if (folder->parent_store == local_store && emfu_is_special_local_folder (folder->full_name)) { e_error_run(NULL, "mail:no-rename-special-folder", folder->full_name, NULL); return; @@ -692,10 +694,10 @@ em_folder_utils_create_folder (CamelFolderInfo *folderinfo, EMFolderTree *emft, EMFolderTreeModel *model; GtkWidget *dialog; - model = mail_component_peek_tree_model (mail_component_peek ()); + model = e_mail_shell_module_get_folder_tree_model (mail_shell_module); folder_tree = (EMFolderTree *) em_folder_tree_new_with_model (model); - dialog = em_folder_selector_create_new (folder_tree, 0, _("Create folder"), _("Specify where to create the folder:")); + dialog = em_folder_selector_create_new (folder_tree, 0, _("Create Folder"), _("Specify where to create the folder:")); if (folderinfo != NULL) em_folder_selector_set_selected ((EMFolderSelector *) dialog, folderinfo->uri); if (parent) { @@ -707,3 +709,38 @@ em_folder_utils_create_folder (CamelFolderInfo *folderinfo, EMFolderTree *emft, g_signal_connect (dialog, "response", G_CALLBACK (emfu_popup_new_folder_response), emft); gtk_widget_show (dialog); } + +const gchar * +em_folder_utils_get_icon_name (guint32 flags) +{ + const gchar *icon_name; + + switch (flags & CAMEL_FOLDER_TYPE_MASK) { + case CAMEL_FOLDER_TYPE_INBOX: + icon_name = "mail-inbox"; + break; + case CAMEL_FOLDER_TYPE_OUTBOX: + icon_name = "mail-outbox"; + break; + case CAMEL_FOLDER_TYPE_TRASH: + icon_name = "user-trash"; + break; + case CAMEL_FOLDER_TYPE_JUNK: + icon_name = "mail-mark-junk"; + break; + case CAMEL_FOLDER_TYPE_SENT: + icon_name = "mail-sent"; + break; + default: + if (flags & CAMEL_FOLDER_SHARED_TO_ME) + icon_name = "stock_shared-to-me"; + else if (flags & CAMEL_FOLDER_SHARED_BY_ME) + icon_name = "stock_shared-by-me"; + else if (flags & CAMEL_FOLDER_VIRTUAL) + icon_name = "folder-saved-search"; + else + icon_name = "folder"; + } + + return icon_name; +} diff --git a/mail/em-folder-utils.h b/mail/em-folder-utils.h index 73b7bc96b2..deed1407e9 100644 --- a/mail/em-folder-utils.h +++ b/mail/em-folder-utils.h @@ -21,20 +21,37 @@ * */ -#ifndef _EM_FOLDER_UTILS_H -#define _EM_FOLDER_UTILS_H +#ifndef EM_FOLDER_UTILS_H +#define EM_FOLDER_UTILS_H -struct _GtkWindow; +#include <gtk/gtk.h> +#include <camel/camel-folder.h> +#include <camel/camel-store.h> +#include <mail/em-folder-tree.h> -int em_folder_utils_copy_folders(CamelStore *fromstore, const char *frombase, CamelStore *tostore, const char *tobase, int delete); +G_BEGIN_DECLS -/* FIXME: These api's are really busted, there is no consistency and most rely on the wrong data */ +gint em_folder_utils_copy_folders (CamelStore *fromstore, + const gchar *frombase, + CamelStore *tostore, + const gchar *tobase, + int delete); -void em_folder_utils_copy_folder (struct _CamelFolderInfo *folderinfo, int delete); +/* FIXME These API's are really busted. There is no consistency and + * most rely on the wrong data. */ -void em_folder_utils_delete_folder (struct _CamelFolder *folder); -void em_folder_utils_rename_folder (struct _CamelFolder *folder); +void em_folder_utils_copy_folder (CamelFolderInfo *folderinfo, + int delete); -void em_folder_utils_create_folder (struct _CamelFolderInfo *folderinfo, EMFolderTree * emft, struct _GtkWindow *parent); +void em_folder_utils_delete_folder (CamelFolder *folder); +void em_folder_utils_rename_folder (CamelFolder *folder); -#endif +void em_folder_utils_create_folder (CamelFolderInfo *folderinfo, + EMFolderTree * emft, + GtkWindow *parent); + +const gchar * em_folder_utils_get_icon_name (guint32 flags); + +G_END_DECLS + +#endif /* EM_FOLDER_UTILS_H */ diff --git a/mail/em-folder-view.c b/mail/em-folder-view.c index 8e220955fa..5b97f2dcb8 100644 --- a/mail/em-folder-view.c +++ b/mail/em-folder-view.c @@ -27,6 +27,7 @@ #include <sys/stat.h> #include <unistd.h> +#include <glib/gi18n.h> #include <glib/gstdio.h> #include <gdk/gdkkeysyms.h> @@ -54,13 +55,6 @@ #include <camel/camel-offline-store.h> #include <camel/camel-vee-store.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 <bonobo/bonobo-ui-util.h> - #include <gtkhtml/gtkhtml.h> #include <gtkhtml/gtkhtml-embedded.h> #include <gtkhtml/gtkhtml-stream.h> @@ -71,10 +65,8 @@ #include "menus/gal-view-etable.h" #include "menus/gal-view-factory-etable.h" #include "menus/gal-view-instance.h" -#include "menus/gal-view-menus.h" #include "misc/e-charset-picker.h" -#include <misc/e-filter-bar.h> #include <misc/e-spinner.h> #include "e-util/e-error.h" @@ -84,6 +76,7 @@ #include "e-util/e-profile-event.h" #include "e-util/e-util-private.h" #include "e-util/e-util-labels.h" +#include "shell/e-shell.h" #include "filter/filter-rule.h" @@ -94,111 +87,77 @@ #include "em-folder-browser.h" #include "em-mailer-prefs.h" #include "em-folder-browser.h" -#include "em-message-browser.h" #include "message-list.h" #include "em-utils.h" #include "em-composer-utils.h" #include "em-menu.h" #include "em-event.h" +#include "e-mail-shell-module.h" #include "mail-mt.h" #include "mail-ops.h" #include "mail-config.h" #include "mail-autofilter.h" #include "mail-vfolder.h" -#include "mail-component.h" #include "mail-tools.h" -#include "evolution-shell-component-utils.h" /* Pixmap stuff, sigh */ - #ifdef HAVE_XFREE #include <X11/XF86keysym.h> #endif -static void emfv_list_message_selected(MessageList *ml, const char *uid, EMFolderView *emfv); -static void emfv_list_built(MessageList *ml, EMFolderView *emfv); -static int emfv_list_right_click(ETree *tree, gint row, ETreePath path, gint col, GdkEvent *event, EMFolderView *emfv); -static void emfv_list_double_click(ETree *tree, gint row, ETreePath path, gint col, GdkEvent *event, EMFolderView *emfv); -static int emfv_list_key_press(ETree *tree, int row, ETreePath path, int col, GdkEvent *ev, EMFolderView *emfv); -static void emfv_list_selection_change(ETree *tree, EMFolderView *emfv); - -static void emfv_format_link_clicked(EMFormatHTMLDisplay *efhd, const char *uri, EMFolderView *); -static int emfv_format_popup_event(EMFormatHTMLDisplay *efhd, GdkEventButton *event, const char *uri, CamelMimePart *part, EMFolderView *); - -static void emfv_enable_menus(EMFolderView *emfv); - -static void emfv_set_folder(EMFolderView *emfv, CamelFolder *folder, const char *uri); -static void emfv_set_folder_uri(EMFolderView *emfv, const char *uri); -static void emfv_set_message(EMFolderView *emfv, const char *uid, int nomarkseen); -static void emfv_activate(EMFolderView *emfv, BonoboUIComponent *uic, int state); - -static void emfv_message_reply(EMFolderView *emfv, int mode); -static void vfolder_type_current (EMFolderView *emfv, int type); -static void filter_type_current (EMFolderView *emfv, int type); - -static void emfv_setting_setup(EMFolderView *emfv); - -static void emfv_on_url_cb(GObject *emitter, const char *url, EMFolderView *emfv); -static void emfv_on_url(EMFolderView *emfv, const char *uri, const char *nice_uri); - -static void emfv_set_seen (EMFolderView *emfv, const char *uid); -static gboolean emfv_on_html_button_released_cb (GtkHTML *html, GdkEventButton *button, EMFolderView *emfv); -static gboolean emfv_popup_menu (GtkWidget *widget); - - /* this is added to emfv->enable_map in :init() */ static const EMFolderViewEnable emfv_enable_map[] = { { "EditCut", EM_POPUP_SELECT_MANY }, { "EditCopy", EM_FOLDER_VIEW_SELECT_SELECTION }, { "EditPaste", EM_POPUP_SELECT_FOLDER }, - { "SelectAllText", EM_POPUP_SELECT_ONE }, +// { "SelectAllText", EM_POPUP_SELECT_ONE }, /* FIXME: should these be single-selection? */ { "MailNext", EM_POPUP_SELECT_MANY|EM_FOLDER_VIEW_SELECT_NEXT_MSG }, - { "MailNextFlagged", EM_POPUP_SELECT_MANY }, - { "MailNextUnread", EM_POPUP_SELECT_MANY }, - { "MailNextThread", EM_POPUP_SELECT_MANY }, +// { "MailNextFlagged", EM_POPUP_SELECT_MANY }, +// { "MailNextUnread", EM_POPUP_SELECT_MANY }, +// { "MailNextThread", EM_POPUP_SELECT_MANY }, { "MailPrevious", EM_POPUP_SELECT_MANY|EM_FOLDER_VIEW_SELECT_PREV_MSG }, - { "MailPreviousFlagged", EM_POPUP_SELECT_MANY }, - { "MailPreviousUnread", EM_POPUP_SELECT_MANY }, +// { "MailPreviousFlagged", EM_POPUP_SELECT_MANY }, +// { "MailPreviousUnread", EM_POPUP_SELECT_MANY }, { "AddSenderToAddressbook", EM_POPUP_SELECT_ADD_SENDER }, - { "MessageApplyFilters", EM_POPUP_SELECT_MANY }, - { "MessageFilterJunk", EM_POPUP_SELECT_MANY }, - { "MessageCopy", EM_POPUP_SELECT_MANY }, - { "MessageDelete", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_DELETE }, - { "MessageDeleteKey", EM_POPUP_SELECT_MANY}, - { "MessageForward", EM_POPUP_SELECT_MANY }, - { "MessageForwardAttached", EM_POPUP_SELECT_MANY }, - { "MessageForwardInline", EM_POPUP_SELECT_ONE }, - { "MessageForwardQuoted", EM_POPUP_SELECT_ONE }, - { "MessageRedirect", EM_POPUP_SELECT_ONE }, - { "MessageMarkAsRead", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_READ }, - { "MessageMarkAsUnRead", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_UNREAD }, - { "MessageMarkAsImportant", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_IMPORTANT }, - { "MessageMarkAsUnimportant", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_UNIMPORTANT }, - { "MessageMarkAsJunk", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_JUNK }, - { "MessageMarkAsNotJunk", EM_POPUP_SELECT_MANY}, +// { "MessageApplyFilters", EM_POPUP_SELECT_MANY }, +// { "MessageFilterJunk", EM_POPUP_SELECT_MANY }, +// { "MessageCopy", EM_POPUP_SELECT_MANY }, +// { "MessageDelete", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_DELETE }, +// { "MessageDeleteKey", EM_POPUP_SELECT_MANY}, +// { "MessageForward", EM_POPUP_SELECT_MANY }, +// { "MessageForwardAttached", EM_POPUP_SELECT_MANY }, +// { "MessageForwardInline", EM_POPUP_SELECT_ONE }, +// { "MessageForwardQuoted", EM_POPUP_SELECT_ONE }, +// { "MessageRedirect", EM_POPUP_SELECT_ONE }, +// { "MessageMarkAsRead", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_READ }, +// { "MessageMarkAsUnRead", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_UNREAD }, +// { "MessageMarkAsImportant", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_IMPORTANT }, +// { "MessageMarkAsUnimportant", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_UNIMPORTANT }, +// { "MessageMarkAsJunk", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_JUNK }, +// { "MessageMarkAsNotJunk", EM_POPUP_SELECT_MANY}, { "MessageFollowUpFlag", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_FLAG_FOLLOWUP }, { "MessageFollowUpComplete", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_FLAG_COMPLETED }, { "MessageFollowUpClear", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_FLAG_CLEAR }, - { "MessageMove", EM_POPUP_SELECT_MANY }, - { "MessageOpen", EM_POPUP_SELECT_MANY }, - { "MessagePostReply", EM_POPUP_SELECT_ONE }, - { "MessageReplyAll", EM_POPUP_SELECT_ONE }, - { "MessageReplyList", EM_POPUP_SELECT_ONE|EM_POPUP_SELECT_MAILING_LIST }, - { "MessageReplySender", EM_POPUP_SELECT_ONE }, - { "MessageEdit", EM_POPUP_SELECT_ONE }, - { "MessageSaveAs", EM_POPUP_SELECT_MANY }, +// { "MessageMove", EM_POPUP_SELECT_MANY }, +// { "MessageOpen", EM_POPUP_SELECT_MANY }, +// { "MessagePostReply", EM_POPUP_SELECT_ONE }, +// { "MessageReplyAll", EM_POPUP_SELECT_ONE }, +// { "MessageReplyList", EM_POPUP_SELECT_ONE|EM_POPUP_SELECT_MAILING_LIST }, +// { "MessageReplySender", EM_POPUP_SELECT_ONE }, +// { "MessageEdit", EM_POPUP_SELECT_ONE }, +// { "MessageSaveAs", EM_POPUP_SELECT_MANY }, { "MessageSearch", EM_POPUP_SELECT_ONE| EM_FOLDER_VIEW_PREVIEW_PRESENT }, - { "MessageUndelete", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_UNDELETE }, - { "PrintMessage", EM_POPUP_SELECT_ONE }, - { "PrintPreviewMessage", EM_POPUP_SELECT_ONE }, +// { "MessageUndelete", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_UNDELETE }, +// { "PrintMessage", EM_POPUP_SELECT_ONE }, +// { "PrintPreviewMessage", EM_POPUP_SELECT_ONE }, - { "TextZoomIn", EM_POPUP_SELECT_ONE }, - { "TextZoomOut", EM_POPUP_SELECT_ONE }, - { "TextZoomReset", EM_POPUP_SELECT_ONE }, +// { "TextZoomIn", EM_POPUP_SELECT_ONE }, +// { "TextZoomOut", EM_POPUP_SELECT_ONE }, +// { "TextZoomReset", EM_POPUP_SELECT_ONE }, { "ToolsFilterMailingList", EM_POPUP_SELECT_ONE|EM_POPUP_SELECT_MAILING_LIST}, { "ToolsFilterRecipient", EM_POPUP_SELECT_ONE }, @@ -209,11 +168,11 @@ static const EMFolderViewEnable emfv_enable_map[] = { { "ToolsVFolderSender", EM_POPUP_SELECT_ONE }, { "ToolsVFolderSubject", EM_POPUP_SELECT_ONE }, - { "ViewLoadImages", EM_POPUP_SELECT_ONE }, - { "ViewSource", EM_POPUP_SELECT_ONE }, +// { "ViewLoadImages", EM_POPUP_SELECT_ONE }, +// { "ViewSource", EM_POPUP_SELECT_ONE }, - /* always enabled */ - { "MailStop", 0 }, +// /* always enabled */ +// { "MailStop", 0 }, { NULL }, }; @@ -227,9 +186,6 @@ struct _EMFolderViewPrivate { GtkWidget *invisible; char *selection_uri; - GalViewInstance *view_instance; - GalViewMenus *view_menus; - char *selected_uid; }; @@ -244,17 +200,6 @@ enum { static guint signals[LAST_SIGNAL]; -static void emfv_selection_get(GtkWidget *widget, GtkSelectionData *data, guint info, guint time_stamp, EMFolderView *emfv); -static void emfv_selection_clear_event(GtkWidget *widget, GdkEventSelection *event, EMFolderView *emfv); - -#ifdef ENABLE_PROFILING -static void -emfv_format_complete(EMFormat *emf, EMFolderView *emfv) -{ - e_profile_event_emit("goto.done", emf->uid?emf->uid:"", 0); -} -#endif - static void emfv_init(GObject *o) { @@ -262,42 +207,42 @@ emfv_init(GObject *o) struct _EMFolderViewPrivate *p; extern CamelSession *session; - gtk_box_set_homogeneous (GTK_BOX (emfv), FALSE); - - p = emfv->priv = g_malloc0(sizeof(struct _EMFolderViewPrivate)); - - emfv->statusbar_active = TRUE; - emfv->list_active = FALSE; - - emfv->ui_files = g_slist_append(NULL, - g_build_filename (EVOLUTION_UIDIR, - "evolution-mail-message.xml", - NULL)); - - emfv->ui_app_name = "evolution-mail"; +// gtk_box_set_homogeneous (GTK_BOX (emfv), FALSE); +// +// p = emfv->priv = g_malloc0(sizeof(struct _EMFolderViewPrivate)); +// +// emfv->statusbar_active = TRUE; +// emfv->list_active = FALSE; +// +// emfv->ui_files = g_slist_append(NULL, +// g_build_filename (EVOLUTION_UIDIR, +// "evolution-mail-message.xml", +// NULL)); +// +// emfv->ui_app_name = "evolution-mail"; emfv->enable_map = g_slist_prepend(NULL, (void *)emfv_enable_map); - emfv->list = (MessageList *)message_list_new(); - g_signal_connect(emfv->list, "message_selected", G_CALLBACK(emfv_list_message_selected), emfv); - g_signal_connect(emfv->list, "message_list_built", G_CALLBACK(emfv_list_built), emfv); - - /* FIXME: should this hang off message-list instead? */ - g_signal_connect(emfv->list->tree, "right_click", G_CALLBACK(emfv_list_right_click), emfv); - g_signal_connect(emfv->list->tree, "double_click", G_CALLBACK(emfv_list_double_click), emfv); - g_signal_connect(emfv->list->tree, "key_press", G_CALLBACK(emfv_list_key_press), emfv); - g_signal_connect(emfv->list->tree, "selection_change", G_CALLBACK(emfv_list_selection_change), emfv); - - emfv->preview = (EMFormatHTMLDisplay *)em_format_html_display_new(); - /* FIXME: set_session should NOT be called here. Should it be a constructor attribute? */ - em_format_set_session ((EMFormat *) emfv->preview, session); - g_signal_connect(emfv->preview, "link_clicked", G_CALLBACK(emfv_format_link_clicked), emfv); +// emfv->list = (MessageList *)message_list_new(); +// g_signal_connect(emfv->list, "message_selected", G_CALLBACK(emfv_list_message_selected), emfv); +// g_signal_connect(emfv->list, "message_list_built", G_CALLBACK(emfv_list_built), emfv); +// +// /* FIXME: should this hang off message-list instead? */ +// g_signal_connect(emfv->list->tree, "right_click", G_CALLBACK(emfv_list_right_click), emfv); +// g_signal_connect(emfv->list->tree, "double_click", G_CALLBACK(emfv_list_double_click), emfv); +// g_signal_connect(emfv->list->tree, "key_press", G_CALLBACK(emfv_list_key_press), emfv); +// g_signal_connect(emfv->list->tree, "selection_change", G_CALLBACK(emfv_list_selection_change), emfv); +// +// emfv->preview = (EMFormatHTMLDisplay *)em_format_html_display_new(); +// /* FIXME: set_session should NOT be called here. Should it be a constructor attribute? */ +// em_format_set_session ((EMFormat *) emfv->preview, session); +// g_signal_connect(emfv->preview, "link_clicked", G_CALLBACK(emfv_format_link_clicked), emfv); g_signal_connect(emfv->preview, "popup_event", G_CALLBACK(emfv_format_popup_event), emfv); - g_signal_connect (emfv->preview, "on_url", G_CALLBACK (emfv_on_url_cb), emfv); - g_signal_connect (((EMFormatHTML *)emfv->preview)->html, "button-release-event", G_CALLBACK (emfv_on_html_button_released_cb), emfv); -#ifdef ENABLE_PROFILING - g_signal_connect(emfv->preview, "complete", G_CALLBACK (emfv_format_complete), emfv); -#endif +// g_signal_connect (emfv->preview, "on_url", G_CALLBACK (emfv_on_url_cb), emfv); +// g_signal_connect (((EMFormatHTML *)emfv->preview)->html, "button-release-event", G_CALLBACK (emfv_on_html_button_released_cb), emfv); +//#ifdef ENABLE_PROFILING +// g_signal_connect(emfv->preview, "complete", G_CALLBACK (emfv_format_complete), emfv); +//#endif p->invisible = gtk_invisible_new(); g_signal_connect(p->invisible, "selection_get", G_CALLBACK(emfv_selection_get), emfv); g_signal_connect(p->invisible, "selection_clear_event", G_CALLBACK(emfv_selection_clear_event), emfv); @@ -305,87 +250,6 @@ emfv_init(GObject *o) gtk_selection_add_target(p->invisible, GDK_SELECTION_CLIPBOARD, GDK_SELECTION_TYPE_STRING, 1); emfv->async = mail_async_event_new(); - - emfv_setting_setup(emfv); -} - -static void -free_one_ui_file (gpointer data, - gpointer user_data) -{ - g_free (data); -} - -static void -emfv_finalise(GObject *o) -{ - EMFolderView *emfv = (EMFolderView *)o; - struct _EMFolderViewPrivate *p = emfv->priv; - - g_slist_foreach (emfv->ui_files, free_one_ui_file, NULL); - g_slist_free(emfv->ui_files); - g_slist_free(emfv->enable_map); - - g_free(p); - - ((GObjectClass *)emfv_parent)->finalize(o); -} - -static void -emfv_destroy (GtkObject *o) -{ - EMFolderView *emfv = (EMFolderView *) o; - struct _EMFolderViewPrivate *p = emfv->priv; - - p->destroyed = TRUE; - - if (emfv->list && emfv->list->seen_id) { - g_source_remove(emfv->list->seen_id); - emfv->list->seen_id = 0; - } - - if (p->setting_notify_id) { - GConfClient *gconf = gconf_client_get_default(); - - gconf_client_notify_remove(gconf, p->setting_notify_id); - p->setting_notify_id = 0; - g_object_unref(gconf); - } - - if (emfv->folder) { - camel_object_unref(emfv->folder); - g_free(emfv->folder_uri); - emfv->folder = NULL; - emfv->folder_uri = NULL; - } - - if (emfv->async) { - mail_async_event_destroy(emfv->async); - emfv->async = NULL; - } - - if (p->invisible) { - gtk_object_destroy((GtkObject *)p->invisible); - p->invisible = NULL; - } - - if (p->selected_id != 0) { - g_source_remove(p->selected_id); - p->selected_id = 0; - } - - g_free(p->selected_uid); - p->selected_uid = NULL; - - g_free (emfv->displayed_uid); - emfv->displayed_uid = NULL; - - emfv->preview = NULL; - emfv->list = NULL; - emfv->preview_active = FALSE; - emfv->uic = NULL; - - ((GtkObjectClass *) emfv_parent)->destroy (o); } static void @@ -404,7 +268,7 @@ emfv_class_init(GObjectClass *klass) ((EMFolderViewClass *)klass)->set_message = emfv_set_message; ((EMFolderViewClass *)klass)->activate = emfv_activate; - ((EMFolderViewClass *)klass)->on_url = emfv_on_url; +// ((EMFolderViewClass *)klass)->on_url = emfv_on_url; signals[EMFV_ON_URL] = g_signal_new ("on-url", G_OBJECT_CLASS_TYPE (klass), @@ -434,365 +298,6 @@ emfv_class_init(GObjectClass *klass) 0); } -GType -em_folder_view_get_type(void) -{ - static GType type = 0; - - if (type == 0) { - static const GTypeInfo info = { - sizeof(EMFolderViewClass), - NULL, NULL, - (GClassInitFunc)emfv_class_init, - NULL, NULL, - sizeof(EMFolderView), 0, - (GInstanceInitFunc)emfv_init - }; - emfv_parent = g_type_class_ref(gtk_vbox_get_type()); - type = g_type_register_static(gtk_vbox_get_type(), "EMFolderView", &info, 0); - } - - return type; -} - -GtkWidget *em_folder_view_new(void) -{ - EMFolderView *emfv = g_object_new(em_folder_view_get_type(), NULL); - - return (GtkWidget *)emfv; -} - -/* flag all selected messages. Return number flagged */ -/* FIXME: Should this be part of message-list instead? */ -int -em_folder_view_mark_selected(EMFolderView *emfv, guint32 mask, guint32 set) -{ - GPtrArray *uids; - int i; - - if (emfv->folder == NULL) - return 0; - - uids = message_list_get_selected(emfv->list); - if (!CAMEL_IS_VEE_FOLDER(emfv->folder)) - camel_folder_freeze(emfv->folder); - - for (i=0; i<uids->len; i++) - camel_folder_set_message_flags(emfv->folder, uids->pdata[i], mask, set); - - message_list_free_uids(emfv->list, uids); - if (!CAMEL_IS_VEE_FOLDER(emfv->folder)) - camel_folder_thaw(emfv->folder); - - return i; -} - -/* should this be elsewhere/take a uid list? */ -int -em_folder_view_open_selected(EMFolderView *emfv) -{ - GPtrArray *uids, *views; - int i = 0; - - uids = message_list_get_selected(emfv->list); - - if (uids->len >= 10) { - char *num = g_strdup_printf("%d", uids->len); - int doit; - - doit = em_utils_prompt_user((GtkWindow *)gtk_widget_get_toplevel((GtkWidget *)emfv), - "/apps/evolution/mail/prompts/open_many", - "mail:ask-open-many", num, NULL); - g_free(num); - if (!doit) { - message_list_free_uids(emfv->list, uids); - return 0; - } - } - - if (em_utils_folder_is_drafts(emfv->folder, emfv->folder_uri) - || em_utils_folder_is_templates(emfv->folder, emfv->folder_uri) - || em_utils_folder_is_outbox(emfv->folder, emfv->folder_uri)) { - em_utils_edit_messages(emfv->folder, uids, TRUE); - return uids->len; - } - - /* for vfolders we need to edit the *original*, not the vfolder copy */ - views = g_ptr_array_new(); - for (i=0;i<uids->len;i++) { - if (camel_object_is((CamelObject *)emfv->folder, camel_vee_folder_get_type())) { - CamelVeeMessageInfo *vinfo = (CamelVeeMessageInfo *)camel_folder_get_message_info(emfv->folder, uids->pdata[i]); - - if (vinfo) { - char *uid; - /* TODO: get_location shouldn't strdup the uid */ - CamelFolder *f = camel_vee_folder_get_location((CamelVeeFolder *)emfv->folder, vinfo, &uid); - char *uri = mail_tools_folder_to_url(f); - - if (em_utils_folder_is_drafts(f, uri) || em_utils_folder_is_outbox(f, uri)) { - GPtrArray *edits = g_ptr_array_new(); - - g_ptr_array_add(edits, uid); - em_utils_edit_messages(f, edits, TRUE); - } else { - g_free(uid); - g_ptr_array_add(views, g_strdup(uids->pdata[i])); - } - g_free(uri); - } - } else { - g_ptr_array_add(views, g_strdup(uids->pdata[i])); - } - } - - /* TODO: have an em_utils_open_messages call? */ - for (i=0; i<views->len; i++) { - EMMessageBrowser *emmb; - - emmb = (EMMessageBrowser *)em_message_browser_window_new(); - message_list_set_threaded(((EMFolderView *)emmb)->list, emfv->list->threaded); - /* always keep actual message in a list view, even it doesn't belong to the filter anymore */ - message_list_ensure_message (((EMFolderView *)emmb)->list, views->pdata[i]); - message_list_set_search (((EMFolderView *)emmb)->list, emfv->list->search); - em_folder_view_set_hide_deleted((EMFolderView *)emmb, emfv->hide_deleted); - /* FIXME: session needs to be passed easier than this */ - em_format_set_session((EMFormat *)((EMFolderView *)emmb)->preview, ((EMFormat *)emfv->preview)->session); - em_folder_view_set_folder((EMFolderView *)emmb, emfv->folder, emfv->folder_uri); - em_folder_view_set_message((EMFolderView *)emmb, views->pdata[i], FALSE); - gtk_widget_show(emmb->window); - /* TODO: this loads the message twice (!) */ - em_utils_handle_receipt (emfv->folder, uids->pdata[i], NULL); - g_free(views->pdata[i]); - } - g_ptr_array_free(views, TRUE); - - message_list_free_uids(emfv->list, uids); - - return i; -} - -/* ******************************************************************************** */ -static void -emfv_list_display_view(GalViewInstance *instance, GalView *view, EMFolderView *emfv) -{ - if (GAL_IS_VIEW_ETABLE(view)) - gal_view_etable_attach_tree(GAL_VIEW_ETABLE(view), emfv->list->tree); -} - -static void -emfv_setup_view_instance(EMFolderView *emfv) -{ - static GalViewCollection *collection = NULL; - struct _EMFolderViewPrivate *p = emfv->priv; - gboolean outgoing, show_wide=FALSE; - char *id; - - g_return_if_fail (emfv->folder); - g_return_if_fail (emfv->folder_uri); - - if (collection == NULL) { - ETableSpecification *spec; - GalViewFactory *factory; - const char *evolution_dir; - char *dir; - char *galviewsmaildir; - char *etspecfile; - - collection = gal_view_collection_new (); - - gal_view_collection_set_title (collection, _("Mail")); - - evolution_dir = mail_component_peek_base_directory (mail_component_peek ()); - galviewsmaildir = g_build_filename (EVOLUTION_GALVIEWSDIR, - "mail", - NULL); - dir = g_build_filename (evolution_dir, "views", NULL); - gal_view_collection_set_storage_directories (collection, galviewsmaildir, dir); - g_free (dir); - g_free (galviewsmaildir); - - spec = e_table_specification_new (); - etspecfile = g_build_filename (EVOLUTION_ETSPECDIR, - "message-list.etspec", - NULL); - if (!e_table_specification_load_from_file (spec, etspecfile)) - g_error ("Unable to load ETable specification file " - "for mail"); - g_free (etspecfile); - - factory = gal_view_factory_etable_new (spec); - g_object_unref (spec); - gal_view_collection_add_factory (collection, factory); - g_object_unref (factory); - - gal_view_collection_load (collection); - } - - if (p->view_instance) { - g_object_unref(p->view_instance); - p->view_instance = NULL; - } - - if (p->view_menus) { - g_object_unref(p->view_menus); - p->view_menus = NULL; - } - - /* TODO: should this go through mail-config api? */ - id = mail_config_folder_to_safe_url (emfv->folder); - p->view_instance = gal_view_instance_new (collection, id); - - show_wide = emfv->list_active ? em_folder_browser_get_wide ((EMFolderBrowser *) emfv):FALSE; - if (show_wide) { - char *safe_id, *filename; - - /* Force to use the wide view */ - g_free (p->view_instance->custom_filename); - g_free (p->view_instance->current_view_filename); - safe_id = g_strdup (id); - e_filename_make_safe (safe_id); - filename = g_strdup_printf ("custom_wide_view-%s.xml", safe_id); - p->view_instance->custom_filename = g_build_filename (collection->local_dir, filename, NULL); - g_free (filename); - filename = g_strdup_printf ("current_wide_view-%s.xml", safe_id); - p->view_instance->current_view_filename = g_build_filename (collection->local_dir, filename, NULL); - g_free (filename); - g_free (safe_id); - } - g_free (id); - - outgoing = em_utils_folder_is_drafts (emfv->folder, emfv->folder_uri) - || em_utils_folder_is_sent (emfv->folder, emfv->folder_uri) - || em_utils_folder_is_outbox (emfv->folder, emfv->folder_uri); - - if (outgoing) { - if (show_wide) - gal_view_instance_set_default_view(p->view_instance, "Wide_View_Sent"); - else - gal_view_instance_set_default_view(p->view_instance, "As_Sent_Folder"); - } else if (show_wide) { - gal_view_instance_set_default_view(p->view_instance, "Wide_View_Normal"); - } - - gal_view_instance_load(p->view_instance); - - if (!gal_view_instance_exists(p->view_instance)) { - struct stat st; - char *path; - - path = mail_config_folder_to_cachename (emfv->folder, "et-header-"); - if (path && g_stat (path, &st) == 0 && st.st_size > 0 && S_ISREG (st.st_mode)) { - ETableSpecification *spec; - ETableState *state; - GalView *view; - char *etspecfile; - - spec = e_table_specification_new (); - etspecfile = g_build_filename (EVOLUTION_ETSPECDIR, - "message-list.etspec", - NULL); - e_table_specification_load_from_file (spec, etspecfile); - g_free (etspecfile); - view = gal_view_etable_new (spec, ""); - g_object_unref (spec); - - state = e_table_state_new (); - e_table_state_load_from_file (state, path); - gal_view_etable_set_state (GAL_VIEW_ETABLE (view), state); - g_object_unref (state); - - gal_view_instance_set_custom_view(p->view_instance, view); - g_object_unref (view); - } - - g_free (path); - } - - g_signal_connect(p->view_instance, "display_view", G_CALLBACK(emfv_list_display_view), emfv); - emfv_list_display_view(p->view_instance, gal_view_instance_get_current_view(p->view_instance), emfv); - - if (emfv->list_active && emfv->uic) { - p->view_menus = gal_view_menus_new(p->view_instance); - gal_view_menus_apply(p->view_menus, emfv->uic, NULL); - } -} - -void em_folder_view_setup_view_instance (EMFolderView *emfv) -{ - emfv_setup_view_instance (emfv); -} - -/* ********************************************************************** */ - -static void -emfv_set_folder(EMFolderView *emfv, CamelFolder *folder, const char *uri) -{ - int isout = (folder && uri - && (em_utils_folder_is_drafts(folder, uri) - || em_utils_folder_is_sent(folder, uri) - || em_utils_folder_is_outbox(folder, uri))); - - if (folder == emfv->folder) - return; - - if (emfv->priv->selected_id) - g_source_remove(emfv->priv->selected_id); - - if (emfv->preview) - em_format_format ((EMFormat *) emfv->preview, NULL, NULL, NULL); - - message_list_set_folder(emfv->list, folder, uri, isout); - g_free(emfv->folder_uri); - emfv->folder_uri = uri ? g_strdup(uri):NULL; - - if (emfv->folder) { - emfv->hide_deleted = emfv->list->hidedeleted; /* <- a bit nasty but makes it track the display better */ - mail_sync_folder (emfv->folder, NULL, NULL); - camel_object_unref(emfv->folder); - } - - emfv->folder = folder; - if (folder) { - /* We need to set this up to get the right view options for the message-list, - * even if we're not showing it */ - emfv_setup_view_instance(emfv); - camel_object_ref(folder); - } - - emfv_enable_menus(emfv); - - /* TODO: should probably be called after all processing, not just this class's impl */ - g_signal_emit(emfv, signals[EMFV_LOADED], 0); -} - -static void -emfv_got_folder(char *uri, CamelFolder *folder, void *data) -{ - EMFolderView *emfv = data; - - em_folder_view_set_folder(emfv, folder, uri); -} - -static void -emfv_set_folder_uri(EMFolderView *emfv, const char *uri) -{ - mail_get_folder(uri, 0, emfv_got_folder, emfv, mail_msg_fast_ordered_push); -} - -static void -emfv_set_message(EMFolderView *emfv, const char *uid, int nomarkseen) -{ - e_profile_event_emit("goto.uid", uid?uid:"<none>", 0); - - /* This could possible race with other set messages, but likelyhood is small */ - emfv->priv->nomarkseen = nomarkseen; - message_list_select_uid(emfv->list, uid); - /* force an update, since we may not get an updated event if we select the same uid */ - emfv_list_message_selected(emfv->list, uid, emfv); -} - -/* ********************************************************************** */ - static void emfv_selection_get(GtkWidget *widget, GtkSelectionData *data, guint info, guint time_stamp, EMFolderView *emfv) { @@ -820,694 +325,6 @@ emfv_selection_clear_event(GtkWidget *widget, GdkEventSelection *event, EMFolder /* Popup menu In many cases these are the functions called by the bonobo callbacks too */ -static void -emfv_popup_open(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - em_folder_view_open_selected(emfv); -} - -static void -emfv_popup_edit (EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - GPtrArray *uids; - - if (!em_utils_check_user_can_send_mail((GtkWidget *)emfv)) - return; - - uids = message_list_get_selected(emfv->list); - em_utils_edit_messages (emfv->folder, uids, FALSE); -} - -static void -emfv_popup_saveas(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - GPtrArray *uids; - - uids = message_list_get_selected(emfv->list); - em_utils_save_messages((GtkWidget *)emfv, emfv->folder, uids); -} - -static void -emfv_view_load_images(BonoboUIComponent *uic, void *data, const char *path) -{ - EMFolderView *emfv = data; - - if (emfv->preview) - em_format_html_load_http((EMFormatHTML *)emfv->preview); -} - -static void -emfv_popup_print(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - em_folder_view_print(emfv, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG); -} - -static void -emfv_popup_copy_text(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - gtk_html_copy (((EMFormatHTML *)emfv->preview)->html); -} - -static void -emfv_popup_source(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - EMMessageBrowser *emmb; - GPtrArray *uids; - - uids = message_list_get_selected(emfv->list); - - emmb = (EMMessageBrowser *)em_message_browser_window_new(); - em_format_set_session((EMFormat *)((EMFolderView *)emmb)->preview, ((EMFormat *)emfv->preview)->session); - message_list_ensure_message (((EMFolderView *)emmb)->list, uids->pdata[0]); - em_folder_view_set_folder((EMFolderView *)emmb, emfv->folder, emfv->folder_uri); - em_format_set_mode((EMFormat *)((EMFolderView *)emmb)->preview, EM_FORMAT_SOURCE); - em_folder_view_set_message((EMFolderView *)emmb, uids->pdata[0], FALSE); - gtk_widget_show(emmb->window); - - message_list_free_uids(emfv->list, uids); -} - -static void -emfv_mail_compose(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderView *emfv = data; - - if (!em_utils_check_user_can_send_mail((GtkWidget *)emfv)) - return; - - em_utils_compose_new_message(emfv->folder_uri); -} - -static void -emfv_popup_reply_sender(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - emfv_message_reply(emfv, REPLY_MODE_SENDER); -} - -static void -emfv_popup_reply_list(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - emfv_message_reply(emfv, REPLY_MODE_LIST); -} - -static void -emfv_popup_reply_all(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - emfv_message_reply(emfv, REPLY_MODE_ALL); -} - -static void -emfv_popup_forward(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - GPtrArray *uids; - - if (!em_utils_check_user_can_send_mail((GtkWidget *)emfv)) - return; - - uids = message_list_get_selected(emfv->list); - em_utils_forward_messages (emfv->folder, uids, emfv->folder_uri); -} - -static void -emfv_popup_flag_followup(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - GPtrArray *uids = message_list_get_selected(emfv->list); - - em_utils_flag_for_followup((GtkWidget *)emfv, emfv->folder, uids); -} - -static void -emfv_popup_flag_completed(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - GPtrArray *uids; - - uids = message_list_get_selected(emfv->list); - em_utils_flag_for_followup_completed((GtkWidget *)emfv, emfv->folder, uids); - - if (emfv->preview) - em_format_redraw (emfv->preview); -} - -static void -emfv_popup_flag_clear(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - GPtrArray *uids = message_list_get_selected(emfv->list); - - em_utils_flag_for_followup_clear((GtkWidget *)emfv, emfv->folder, uids); - - if (emfv->preview) - em_format_redraw (emfv->preview); -} - -static void -emfv_popup_mark_read(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - em_folder_view_mark_selected(emfv, CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN); -} - -static void -emfv_popup_mark_unread(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - em_folder_view_mark_selected(emfv, CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_DELETED, 0); - - if (emfv->list->seen_id) { - g_source_remove(emfv->list->seen_id); - emfv->list->seen_id = 0; - } -} - -static void -emfv_popup_mark_important(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - em_folder_view_mark_selected(emfv, CAMEL_MESSAGE_FLAGGED|CAMEL_MESSAGE_DELETED, CAMEL_MESSAGE_FLAGGED); -} - -static void -emfv_popup_mark_unimportant(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - em_folder_view_mark_selected(emfv, CAMEL_MESSAGE_FLAGGED, 0); -} - -static void -emfv_select_next_message (EMFolderView *emfv, int count, gboolean always_can_previous) -{ - if (emfv && count == 1) { - if (!message_list_select (emfv->list, MESSAGE_LIST_SELECT_NEXT, 0, 0) && (emfv->hide_deleted || always_can_previous)) - message_list_select (emfv->list, MESSAGE_LIST_SELECT_PREVIOUS, 0, 0); - } -} - -static void -emfv_popup_mark_junk (EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - int count; - - count = em_folder_view_mark_selected(emfv, - CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_JUNK|CAMEL_MESSAGE_NOTJUNK|CAMEL_MESSAGE_JUNK_LEARN, - CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_JUNK|CAMEL_MESSAGE_JUNK_LEARN); - - emfv_select_next_message (emfv, count, TRUE); -} - -static void -emfv_popup_mark_nojunk (EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - int count; - - count = em_folder_view_mark_selected(emfv, - CAMEL_MESSAGE_JUNK|CAMEL_MESSAGE_NOTJUNK|CAMEL_MESSAGE_JUNK_LEARN, - CAMEL_MESSAGE_NOTJUNK|CAMEL_MESSAGE_JUNK_LEARN); - - emfv_select_next_message (emfv, count, TRUE); -} - -#define DelInVFolderCheckName "DelInVFolderCheck" -#define DelInVFolderKey "/apps/evolution/mail/prompts/delete_in_vfolder" - -static void -emfv_delete_msg_response (GtkWidget *dialog, int response, gpointer data) -{ - if (response == GTK_RESPONSE_OK) { - EMFolderView *emfv = data; - int count; - GPtrArray *uids; - - if (dialog) { - GList *children, *l; - GtkWidget *check = NULL; - - children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox)); - for (l = children; l; l = l->next) { - if (GTK_IS_ALIGNMENT (l->data)) { - check = gtk_bin_get_child (GTK_BIN (l->data)); - - if (check && GTK_IS_CHECK_BUTTON (check) && - !strcmp (gtk_widget_get_name (check), DelInVFolderCheckName)) - break; - - check = NULL; - } - } - - if (check) { - GConfClient *gconf = gconf_client_get_default (); - gconf_client_set_bool (gconf, DelInVFolderKey, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check)), NULL); - g_object_unref (gconf); - } - - g_list_free (children); - } - - uids = message_list_get_selected(emfv->list); - if (!CAMEL_IS_VEE_FOLDER(emfv->folder)) - camel_folder_freeze(emfv->folder); - - for (count=0; count < uids->len; count++) { - if (camel_folder_get_message_flags (emfv->folder, uids->pdata[count]) & CAMEL_MESSAGE_USER_NOT_DELETABLE) { - if (emfv->preview_active) { - GtkHTMLStream *hstream = gtk_html_begin(((EMFormatHTML *)emfv->preview)->html); - - gtk_html_stream_printf(hstream, "<h2>%s</h2><p>%s</p>", - _("Mail Deletion Failed"), - _("You do not have sufficient permissions to delete this mail.")); - gtk_html_stream_close(hstream, GTK_HTML_STREAM_OK); - } else { - GtkWidget *w = e_error_new (NULL, "mail:no-delete-permission", "", NULL); - em_utils_show_error_silent (w); - } - - count = -1; - break; - } else - camel_folder_set_message_flags(emfv->folder, uids->pdata[count], CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_DELETED, CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_DELETED ); - } - - message_list_free_uids(emfv->list, uids); - if (!CAMEL_IS_VEE_FOLDER(emfv->folder)) - camel_folder_thaw(emfv->folder); - - emfv_select_next_message (emfv, count, FALSE); - } - - if (dialog) - gtk_widget_destroy (dialog); -} - -static void -emfv_popup_delete (EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - GConfClient *gconf = gconf_client_get_default (); - - if (emfv->folder && emfv->folder->parent_store && CAMEL_IS_VEE_STORE (emfv->folder->parent_store) - && !gconf_client_get_bool (gconf, DelInVFolderKey, NULL)) { - GtkWidget *dialog, *checkbox, *align; - - dialog = e_error_new (NULL, "mail:ask-delete-vfolder-msg", emfv->folder->full_name, NULL); - g_signal_connect (dialog, "response", G_CALLBACK (emfv_delete_msg_response), emfv); - checkbox = gtk_check_button_new_with_label (_("Do not ask me again.")); - gtk_widget_set_name (checkbox, DelInVFolderCheckName); - align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0); - gtk_container_add (GTK_CONTAINER (align), checkbox); - gtk_widget_show (checkbox); - gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->vbox), align, TRUE, TRUE, 6); - gtk_widget_show (align); - gtk_widget_show (dialog); - } else { - emfv_delete_msg_response (NULL, GTK_RESPONSE_OK, emfv); - } - - g_object_unref (gconf); -} -#undef DelInVFolderCheckName -#undef DelInVFolderKey - -static void -emfv_popup_undelete(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - em_folder_view_mark_selected(emfv, CAMEL_MESSAGE_DELETED, 0); -} - -struct _move_data { - EMFolderView *emfv; - GPtrArray *uids; - int delete; -}; - -static char *default_xfer_messages_uri = NULL; - -static void -emfv_popup_move_cb(const char *uri, void *data) -{ - struct _move_data *d = data; - - if (uri) { - g_free (default_xfer_messages_uri); - default_xfer_messages_uri = g_strdup (uri); - mail_transfer_messages(d->emfv->folder, d->uids, d->delete, uri, 0, NULL, NULL); - } else - em_utils_uids_free(d->uids); - - g_object_unref(d->emfv); - g_free(d); -} - -static void -emfv_popup_move(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - struct _move_data *d; - - d = g_malloc(sizeof(*d)); - d->emfv = emfv; - g_object_ref(emfv); - d->uids = message_list_get_selected(emfv->list); - d->delete = TRUE; - - em_select_folder ((GtkWindow *) emfv, _("Select folder"), _("_Move"), default_xfer_messages_uri, NULL, emfv_popup_move_cb, d); -} - -static void -emfv_popup_copy(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - struct _move_data *d; - - d = g_malloc(sizeof(*d)); - d->emfv = emfv; - g_object_ref(emfv); - d->uids = message_list_get_selected(emfv->list); - d->delete = FALSE; - - em_select_folder ((GtkWindow *) emfv, _("Select folder"), _("C_opy"), default_xfer_messages_uri, NULL, emfv_popup_move_cb, d); -} - -static void -emfv_set_label (EMFolderView *emfv, const char *label) -{ - GPtrArray *uids = message_list_get_selected (emfv->list); - int i; - - for (i = 0; i < uids->len; i++) - camel_folder_set_message_user_flag (emfv->folder, uids->pdata[i], label, TRUE); - - message_list_free_uids (emfv->list, uids); -} - -static void -emfv_unset_label (EMFolderView *emfv, const char *label) -{ - GPtrArray *uids = message_list_get_selected (emfv->list); - int i; - - for (i = 0; i < uids->len; i++) { - camel_folder_set_message_user_flag (emfv->folder, uids->pdata[i], label, FALSE); - camel_folder_set_message_user_tag (emfv->folder, uids->pdata[i], "label", NULL); - } - - message_list_free_uids (emfv->list, uids); -} - -static void -emfv_popup_label_clear(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - GSList *l; - EUtilLabel *label; - - for (l = mail_config_get_labels (); l; l = l->next) { - label = l->data; - emfv_unset_label(emfv, label->tag); - } -} - -static void -emfv_popup_label_set(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - - if (pitem->type & E_POPUP_ACTIVE) - emfv_set_label (emfv, pitem->user_data); - else - emfv_unset_label (emfv, pitem->user_data); -} - -static void -emfv_popup_label_new (EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - char *tag = e_util_labels_add_with_dlg (NULL, NULL); - - if (tag) { - emfv_set_label (emfv, tag); - g_free (tag); - } -} - -static void -emfv_popup_add_sender(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - GPtrArray *uids = message_list_get_selected(emfv->list); - CamelMessageInfo *info; - const char *addr; - - if (uids->len == 1 - && (info = camel_folder_get_message_info(emfv->folder, uids->pdata[0])) != NULL - && (addr = camel_message_info_from(info)) != NULL - && addr[0] != 0) - em_utils_add_address((GtkWidget *)emfv, addr); - - em_utils_uids_free(uids); -} - -static void -emfv_popup_apply_filters(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - GPtrArray *uids = message_list_get_selected(emfv->list); - - mail_filter_on_demand(emfv->folder, uids); -} - -static void -emfv_popup_filter_junk(EPopup *ep, EPopupItem *pitem, void *data) -{ - EMFolderView *emfv = data; - GPtrArray *uids = message_list_get_selected(emfv->list); - - mail_filter_junk(emfv->folder, uids); -} - -/* filter callbacks, this will eventually be a wizard, see - filter_type_current/vfolder_type_current for implementation */ - -#define EMFV_POPUP_AUTO_TYPE(autotype, name, type) \ -static void \ -name(EPopup *ep, EPopupItem *item, void *data) \ -{ \ - EMFolderView *emfv = data; \ - autotype(emfv, type); \ -} - -EMFV_POPUP_AUTO_TYPE(vfolder_type_current, emfv_popup_vfolder_subject, AUTO_SUBJECT) -EMFV_POPUP_AUTO_TYPE(vfolder_type_current, emfv_popup_vfolder_sender, AUTO_FROM) -EMFV_POPUP_AUTO_TYPE(vfolder_type_current, emfv_popup_vfolder_recipients, AUTO_TO) -EMFV_POPUP_AUTO_TYPE(vfolder_type_current, emfv_popup_vfolder_mlist, AUTO_MLIST) - -EMFV_POPUP_AUTO_TYPE(filter_type_current, emfv_popup_filter_subject, AUTO_SUBJECT) -EMFV_POPUP_AUTO_TYPE(filter_type_current, emfv_popup_filter_sender, AUTO_FROM) -EMFV_POPUP_AUTO_TYPE(filter_type_current, emfv_popup_filter_recipients, AUTO_TO) -EMFV_POPUP_AUTO_TYPE(filter_type_current, emfv_popup_filter_mlist, AUTO_MLIST) - -/* TODO: Move some of these to be 'standard' menu's */ - -static EPopupItem emfv_popup_items[] = { - { E_POPUP_ITEM, "00.emfv.00", N_("_Copy"), emfv_popup_copy_text, NULL, "edit-copy", EM_FOLDER_VIEW_SELECT_DISPLAY|EM_FOLDER_VIEW_SELECT_SELECTION }, - - { E_POPUP_BAR, "10.emfv", NULL, NULL, NULL, NULL }, - - { E_POPUP_ITEM, "10.emfv.00", N_("_Reply to Sender"), emfv_popup_reply_sender, NULL, "mail-reply-sender", EM_POPUP_SELECT_ONE }, - { E_POPUP_ITEM, "10.emfv.01", N_("Reply to _All"), emfv_popup_reply_all, NULL, "mail-reply-all", EM_POPUP_SELECT_ONE }, - { E_POPUP_ITEM, "10.emfv.02", N_("_Forward"), emfv_popup_forward, NULL, "mail-forward", EM_POPUP_SELECT_MANY }, - - { E_POPUP_BAR, "20.emfv", NULL, NULL, NULL, NULL }, - /* EM_POPUP_EDIT was used here. This is changed to EM_POPUP_SELECT_ONE as Edit-as-new-messaeg need not be restricted to Sent-Items folder alone */ - { E_POPUP_ITEM, "20.emfv.00", N_("_Edit as New Message..."), emfv_popup_edit, NULL, NULL, EM_POPUP_SELECT_ONE }, - { E_POPUP_ITEM, "20.emfv.01", N_("_Save As..."), emfv_popup_saveas, NULL, "document-save-as", EM_POPUP_SELECT_MANY }, - { E_POPUP_ITEM, "20.emfv.02", N_("_Print..."), emfv_popup_print, NULL, "document-print", EM_POPUP_SELECT_ONE }, - - { E_POPUP_BAR, "40.emfv", NULL, NULL, NULL, NULL }, - { E_POPUP_ITEM, "40.emfv.00", N_("_Delete"), emfv_popup_delete, NULL, "edit-delete", EM_POPUP_SELECT_DELETE|EM_FOLDER_VIEW_SELECT_LISTONLY }, - { E_POPUP_ITEM, "40.emfv.01", N_("U_ndelete"), emfv_popup_undelete, NULL, NULL, EM_POPUP_SELECT_UNDELETE|EM_FOLDER_VIEW_SELECT_LISTONLY }, - { E_POPUP_ITEM, "40.emfv.02", N_("_Move to Folder..."), emfv_popup_move, NULL, "mail-move", EM_POPUP_SELECT_MANY|EM_FOLDER_VIEW_SELECT_LISTONLY }, - { E_POPUP_ITEM, "40.emfv.03", N_("_Copy to Folder..."), emfv_popup_copy, NULL, "mail-copy", EM_POPUP_SELECT_MANY|EM_FOLDER_VIEW_SELECT_LISTONLY }, - - { E_POPUP_BAR, "50.emfv", NULL, NULL, NULL, NULL }, - { E_POPUP_ITEM, "50.emfv.00", N_("Mar_k as Read"), emfv_popup_mark_read, NULL, "mail-mark-read", EM_POPUP_SELECT_MARK_READ|EM_FOLDER_VIEW_SELECT_LISTONLY }, - { E_POPUP_ITEM, "50.emfv.01", N_("Mark as _Unread"), emfv_popup_mark_unread, NULL, "mail-mark-unread", EM_POPUP_SELECT_MARK_UNREAD|EM_FOLDER_VIEW_SELECT_LISTONLY }, - { E_POPUP_ITEM, "50.emfv.02", N_("Mark as _Important"), emfv_popup_mark_important, NULL, "mail-mark-important", EM_POPUP_SELECT_MARK_IMPORTANT|EM_FOLDER_VIEW_SELECT_LISTONLY }, - { E_POPUP_ITEM, "50.emfv.03", N_("Mark as Un_important"), emfv_popup_mark_unimportant, NULL, NULL, EM_POPUP_SELECT_MARK_UNIMPORTANT|EM_FOLDER_VIEW_SELECT_LISTONLY }, - { E_POPUP_ITEM, "50.emfv.04", N_("Mark as _Junk"), emfv_popup_mark_junk, NULL, "mail-mark-junk", EM_POPUP_SELECT_MANY|EM_FOLDER_VIEW_SELECT_LISTONLY|EM_POPUP_SELECT_JUNK }, - { E_POPUP_ITEM, "50.emfv.05", N_("Mark as _Not Junk"), emfv_popup_mark_nojunk, NULL, "mail-mark-notjunk", EM_POPUP_SELECT_MANY|EM_FOLDER_VIEW_SELECT_LISTONLY|EM_POPUP_SELECT_NOT_JUNK }, - { E_POPUP_ITEM, "50.emfv.06", N_("Mark for Follo_w Up..."), emfv_popup_flag_followup, NULL, "stock_mail-flag-for-followup", EM_POPUP_SELECT_FLAG_FOLLOWUP|EM_FOLDER_VIEW_SELECT_LISTONLY }, - - { E_POPUP_SUBMENU, "60.label.00", N_("_Label"), NULL, NULL, NULL, EM_POPUP_SELECT_MANY|EM_FOLDER_VIEW_SELECT_LISTONLY }, - { E_POPUP_ITEM, "60.label.00/00.label", N_("_None"), emfv_popup_label_clear, NULL, NULL, EM_POPUP_SELECT_MANY|EM_FOLDER_VIEW_SELECT_LISTONLY }, - { E_POPUP_BAR, "60.label.00/00.label.00", NULL, NULL, NULL, NULL }, - { E_POPUP_BAR, "60.label.00/01.label", NULL, NULL, NULL, NULL }, - { E_POPUP_ITEM, "60.label.00/01.label.00", N_("_New Label"), emfv_popup_label_new, NULL, NULL, EM_POPUP_SELECT_MANY|EM_FOLDER_VIEW_SELECT_LISTONLY }, - - { E_POPUP_BAR, "70.emfv.06", NULL, NULL, NULL, NULL }, - - { E_POPUP_ITEM, "70.emfv.07", N_("Fla_g Completed"), emfv_popup_flag_completed, NULL, "stock_mail-flag-for-followup-done", EM_POPUP_SELECT_FLAG_COMPLETED|EM_FOLDER_VIEW_SELECT_LISTONLY }, - { E_POPUP_ITEM, "70.emfv.08", N_("Cl_ear Flag"), emfv_popup_flag_clear, NULL, NULL, EM_POPUP_SELECT_FLAG_CLEAR|EM_FOLDER_VIEW_SELECT_LISTONLY }, - - { E_POPUP_BAR, "90.filter", NULL, NULL, NULL, NULL }, - { E_POPUP_SUBMENU, "90.filter.00", N_("Crea_te Rule From Message"), NULL, NULL, NULL, EM_POPUP_SELECT_ONE|EM_FOLDER_VIEW_SELECT_LISTONLY }, - /* Translators: The following strings are used while creating a new search folder, to specify what parameter the search folder would be based on. */ - { E_POPUP_ITEM, "90.filter.00/00.00", N_("Search Folder based on _Subject"), emfv_popup_vfolder_subject, NULL, NULL, EM_POPUP_SELECT_ONE|EM_FOLDER_VIEW_SELECT_LISTONLY }, - { E_POPUP_ITEM, "90.filter.00/00.01", N_("Search Folder based on Se_nder"), emfv_popup_vfolder_sender, NULL, NULL, EM_POPUP_SELECT_ONE|EM_FOLDER_VIEW_SELECT_LISTONLY }, - { E_POPUP_ITEM, "90.filter.00/00.02", N_("Search Folder based on _Recipients"), emfv_popup_vfolder_recipients, NULL, NULL, EM_POPUP_SELECT_ONE|EM_FOLDER_VIEW_SELECT_LISTONLY }, - { E_POPUP_ITEM, "90.filter.00/00.03", N_("Search Folder based on Mailing _List"), - emfv_popup_vfolder_mlist, NULL, NULL, EM_POPUP_SELECT_ONE|EM_POPUP_SELECT_MAILING_LIST|EM_FOLDER_VIEW_SELECT_LISTONLY }, - - { E_POPUP_BAR, "90.filter.00/10", NULL, NULL, NULL, NULL }, - /* Translators: The following strings are used while creating a new message filter, to specify what parameter the filter would be based on. */ - { E_POPUP_ITEM, "90.filter.00/10.00", N_("Filter based on Sub_ject"), emfv_popup_filter_subject, NULL, NULL, EM_POPUP_SELECT_ONE|EM_FOLDER_VIEW_SELECT_LISTONLY }, - { E_POPUP_ITEM, "90.filter.00/10.01", N_("Filter based on Sen_der"), emfv_popup_filter_sender, NULL, NULL, EM_POPUP_SELECT_ONE|EM_FOLDER_VIEW_SELECT_LISTONLY }, - { E_POPUP_ITEM, "90.filter.00/10.02", N_("Filter based on Re_cipients"), emfv_popup_filter_recipients, NULL, NULL, EM_POPUP_SELECT_ONE|EM_FOLDER_VIEW_SELECT_LISTONLY }, - { E_POPUP_ITEM, "90.filter.00/10.03", N_("Filter based on _Mailing List"), - emfv_popup_filter_mlist, NULL, NULL, EM_POPUP_SELECT_ONE|EM_POPUP_SELECT_MAILING_LIST|EM_FOLDER_VIEW_SELECT_LISTONLY }, -}; - -static enum _e_popup_t -emfv_popup_labels_get_state_for_tag (EMFolderView *emfv, GPtrArray *uids, const char *label_tag) -{ - enum _e_popup_t state = 0; - int i; - gboolean exists = FALSE, not_exists = FALSE; - - g_return_val_if_fail (emfv != 0, state); - g_return_val_if_fail (label_tag != NULL, state); - - for (i = 0; i < uids->len && (!exists || !not_exists); i++) { - if (camel_folder_get_message_user_flag (emfv->folder, uids->pdata[i], label_tag)) - exists = TRUE; - else { - const char *label = e_util_labels_get_new_tag (camel_folder_get_message_user_tag (emfv->folder, uids->pdata[i], "label")); - - /* backward compatibility... */ - if (label && !strcmp (label, label_tag)) - exists = TRUE; - else - not_exists = TRUE; - } - } - - if (exists && not_exists) - state = E_POPUP_INCONSISTENT; - else if (exists) - state = E_POPUP_ACTIVE; - - return state; -} - -static void -emfv_popup_labels_free(EPopup *ep, GSList *l, void *data) -{ - while (l) { - GSList *n = l->next; - EPopupItem *item = l->data; - - g_free(item->path); - g_free(item); - - g_slist_free_1(l); - l = n; - } -} - -static void -emfv_popup_items_free(EPopup *ep, GSList *items, void *data) -{ - g_slist_free(items); -} - -static void -emfv_popup(EMFolderView *emfv, GdkEvent *event, int on_display) -{ - GSList *menus = NULL, *l, *label_list = NULL; - GtkMenu *menu; - EMPopup *emp; - EMPopupTargetSelect *target; - int i; - - /** @HookPoint-EMPopup: Message List Context Menu - * @Id: org.gnome.evolution.mail.folderview.popup.select - * @Type: EMPopup - * @Target: EMPopupTargetSelect - * - * This is the context menu shown on the message list or over a message. - */ - emp = em_popup_new("org.gnome.evolution.mail.folderview.popup"); - target = em_folder_view_get_popup_target(emfv, emp, on_display); - - for (i=0;i<sizeof(emfv_popup_items)/sizeof(emfv_popup_items[0]);i++) - menus = g_slist_prepend(menus, &emfv_popup_items[i]); - - e_popup_add_items((EPopup *)emp, menus, NULL, emfv_popup_items_free, emfv); - - i = 1; - if (!on_display) { - GPtrArray *uids = message_list_get_selected (emfv->list); - - for (l = mail_config_get_labels (); l; l = l->next) { - EPopupItem *item; - EUtilLabel *label = l->data; - GdkPixmap *pixmap; - GdkColor colour; - GdkGC *gc; - - item = g_malloc0(sizeof(*item)); - item->type = E_POPUP_TOGGLE | emfv_popup_labels_get_state_for_tag (emfv, uids, label->tag); - item->path = g_strdup_printf("60.label.00/00.label.%02d", i++); - item->label = label->name; - item->activate = emfv_popup_label_set; - item->user_data = label->tag; - - item->visible = EM_POPUP_SELECT_MANY|EM_FOLDER_VIEW_SELECT_LISTONLY; - - gdk_color_parse (label->colour, &colour); - gdk_colormap_alloc_color(gdk_colormap_get_system(), &colour, FALSE, TRUE); - - pixmap = gdk_pixmap_new(((GtkWidget *)emfv)->window, 16, 16, -1); - gc = gdk_gc_new(((GtkWidget *)emfv)->window); - gdk_gc_set_foreground(gc, &colour); - gdk_draw_rectangle(pixmap, gc, TRUE, 0, 0, 16, 16); - g_object_unref(gc); - - item->image = gtk_image_new_from_pixmap(pixmap, NULL); - gtk_widget_show(item->image); - - label_list = g_slist_prepend(label_list, item); - } - - message_list_free_uids (emfv->list, uids); - } - - e_popup_add_items((EPopup *)emp, label_list, NULL, emfv_popup_labels_free, emfv); - - menu = e_popup_create_menu_once((EPopup *)emp, (EPopupTarget *)target, 0); - - if (event == NULL || event->type == GDK_KEY_PRESS) { - /* FIXME: menu pos function */ - gtk_menu_popup(menu, NULL, NULL, NULL, NULL, 0, event ? event->key.time : gtk_get_current_event_time()); - } else { - gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event->button.button, event->button.time); - } -} - /* ********************************************************************** */ /* Bonobo menu's */ @@ -1520,57 +337,6 @@ from(BonoboUIComponent *uid, void *data, const char *path) \ to(NULL, NULL, data); \ } -EMFV_MAP_CALLBACK(emfv_add_sender_addressbook, emfv_popup_add_sender) -EMFV_MAP_CALLBACK(emfv_message_apply_filters, emfv_popup_apply_filters) -EMFV_MAP_CALLBACK(emfv_message_filter_junk, emfv_popup_filter_junk) -EMFV_MAP_CALLBACK(emfv_message_copy, emfv_popup_copy) -EMFV_MAP_CALLBACK(emfv_message_move, emfv_popup_move) -EMFV_MAP_CALLBACK(emfv_message_forward, emfv_popup_forward) -EMFV_MAP_CALLBACK(emfv_message_reply_all, emfv_popup_reply_all) -EMFV_MAP_CALLBACK(emfv_message_reply_list, emfv_popup_reply_list) -EMFV_MAP_CALLBACK(emfv_message_reply_sender, emfv_popup_reply_sender) -EMFV_MAP_CALLBACK(emfv_message_mark_read, emfv_popup_mark_read) -EMFV_MAP_CALLBACK(emfv_message_mark_unread, emfv_popup_mark_unread) -EMFV_MAP_CALLBACK(emfv_message_mark_important, emfv_popup_mark_important) -EMFV_MAP_CALLBACK(emfv_message_mark_unimportant, emfv_popup_mark_unimportant) -EMFV_MAP_CALLBACK(emfv_message_mark_junk, emfv_popup_mark_junk) -EMFV_MAP_CALLBACK(emfv_message_mark_nojunk, emfv_popup_mark_nojunk) -EMFV_MAP_CALLBACK(emfv_message_delete, emfv_popup_delete) -EMFV_MAP_CALLBACK(emfv_message_undelete, emfv_popup_undelete) -EMFV_MAP_CALLBACK(emfv_message_followup_flag, emfv_popup_flag_followup) -EMFV_MAP_CALLBACK(emfv_message_followup_clear, emfv_popup_flag_clear) -EMFV_MAP_CALLBACK(emfv_message_followup_completed, emfv_popup_flag_completed) -EMFV_MAP_CALLBACK(emfv_message_open, emfv_popup_open) -EMFV_MAP_CALLBACK(emfv_message_edit, emfv_popup_edit) -EMFV_MAP_CALLBACK(emfv_message_saveas, emfv_popup_saveas) -EMFV_MAP_CALLBACK(emfv_print_message, emfv_popup_print) -EMFV_MAP_CALLBACK(emfv_message_source, emfv_popup_source) - -static void -emfv_empty_trash(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderView *emfv = data; - - em_utils_empty_trash (gtk_widget_get_toplevel ((GtkWidget *) emfv)); -} - -static void -prepare_offline(void *key, void *value, void *data) -{ - CamelService *service = key; - - if (CAMEL_IS_DISCO_STORE(service) - || CAMEL_IS_OFFLINE_STORE(service)) { - mail_store_prepare_offline((CamelStore *)service); - } -} - -static void -emfv_prepare_offline(BonoboUIComponent *uid, void *data, const char *path) -{ - mail_component_stores_foreach(mail_component_peek(), prepare_offline, NULL); -} - static void emfv_edit_cut(BonoboUIComponent *uid, void *data, const char *path) { @@ -1602,346 +368,6 @@ emfv_edit_paste(BonoboUIComponent *uid, void *data, const char *path) } static void -emfv_select_all_text(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderView *emfv = data; - gboolean selected; - - gtk_html_select_all (((EMFormatHTML *)emfv->preview)->html); - selected = gtk_html_command (((EMFormatHTML *)emfv->preview)->html, "is-selection-active"); - bonobo_ui_component_set_prop(emfv->uic, "/commands/EditCopy", "sensitive", selected?"1":"0", NULL); - -} - -static void -emfv_mail_next(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderView *emfv = data; - - e_profile_event_emit("goto.next", "", 0); - - message_list_select(emfv->list, MESSAGE_LIST_SELECT_NEXT, 0, 0); -} - -static void -emfv_mail_next_flagged(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderView *emfv = data; - - message_list_select(emfv->list, MESSAGE_LIST_SELECT_NEXT|MESSAGE_LIST_SELECT_WRAP, CAMEL_MESSAGE_FLAGGED, CAMEL_MESSAGE_FLAGGED); -} - -static void -emfv_mail_next_unread(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderView *emfv = data; - - gtk_widget_grab_focus((GtkWidget *) emfv->list); - message_list_select(emfv->list, MESSAGE_LIST_SELECT_NEXT|MESSAGE_LIST_SELECT_WRAP, 0, CAMEL_MESSAGE_SEEN); -} - -static void -emfv_mail_next_thread(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderView *emfv = data; - - message_list_select_next_thread(emfv->list); -} - -static void -emfv_mail_previous(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderView *emfv = data; - - message_list_select(emfv->list, MESSAGE_LIST_SELECT_PREVIOUS, 0, 0); -} - -static void -emfv_mail_previous_flagged(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderView *emfv = data; - - message_list_select(emfv->list, MESSAGE_LIST_SELECT_PREVIOUS|MESSAGE_LIST_SELECT_WRAP, CAMEL_MESSAGE_FLAGGED, CAMEL_MESSAGE_FLAGGED); -} - -static void -emfv_mail_previous_unread(BonoboUIComponent *uid, void *data, const char *path) -{ - EMFolderView *emfv = data; - - gtk_widget_grab_focus((GtkWidget *) emfv->list); - message_list_select(emfv->list, MESSAGE_LIST_SELECT_PREVIOUS|MESSAGE_LIST_SELECT_WRAP, 0, CAMEL_MESSAGE_SEEN); -} - -static void -emfv_message_forward_attached (BonoboUIComponent *uic, void *data, const char *path) -{ - EMFolderView *emfv = data; - GPtrArray *uids; - - if (!em_utils_check_user_can_send_mail ((GtkWidget *) emfv)) - return; - - uids = message_list_get_selected (emfv->list); - em_utils_forward_attached (emfv->folder, uids, emfv->folder_uri); -} - -static void -emfv_message_forward_inline (BonoboUIComponent *uic, void *data, const char *path) -{ - EMFolderView *emfv = data; - GPtrArray *uids; - - if (!em_utils_check_user_can_send_mail ((GtkWidget *) emfv)) - return; - - uids = message_list_get_selected (emfv->list); - em_utils_forward_inline (emfv->folder, uids, emfv->folder_uri); -} - -static void -emfv_message_forward_quoted (BonoboUIComponent *uic, void *data, const char *path) -{ - EMFolderView *emfv = data; - GPtrArray *uids; - - if (!em_utils_check_user_can_send_mail ((GtkWidget *) emfv)) - return; - - uids = message_list_get_selected (emfv->list); - em_utils_forward_quoted (emfv->folder, uids, emfv->folder_uri); -} - -static void -emfv_message_redirect (BonoboUIComponent *uic, void *data, const char *path) -{ - EMFolderView *emfv = data; - - if (emfv->list->cursor_uid == NULL) - return; - - if (!em_utils_check_user_can_send_mail ((GtkWidget *) emfv)) - return; - - em_utils_redirect_message_by_uid (emfv->folder, emfv->list->cursor_uid); -} - -static void -emfv_message_post_reply (BonoboUIComponent *uic, void *data, const char *path) -{ - EMFolderView *emfv = data; - - if (emfv->list->cursor_uid == NULL) - return; - - if (!em_utils_check_user_can_send_mail ((GtkWidget *) emfv)) - return; - - em_utils_post_reply_to_message_by_uid (emfv->folder, emfv->list->cursor_uid); -} - -static gboolean -html_contains_nonwhitespace (const char *html, gint len) -{ - const char *p; - gunichar c = 0; - - if (!html || len<=0) - return FALSE; - - p = html; - - while (p && p - html < len) { - c = g_utf8_get_char (p); - if (!c) - break; - - if (c == '<') { - /* skip until next '>' */ - while (c = g_utf8_get_char (p), c && c != '>' && p - html < len) - p = g_utf8_next_char (p); - if (!c) - break; - }else if (c == '&') { - /* sequence ' ' is a space */ - if (g_ascii_strncasecmp (p, " ", 6) == 0) - p = p + 5; - else - break; - }else if (!g_unichar_isspace (c)) { - break; - } - - p = g_utf8_next_char (p); - } - - return p - html < len - 1 && c != 0; -} - -static void -emfv_message_reply(EMFolderView *emfv, int mode) -{ - char *html = NULL; - gint len; - - if (emfv->list->cursor_uid == NULL) - return; - - if (!em_utils_check_user_can_send_mail ((GtkWidget *) emfv)) - return; - - if (gtk_html_command(((EMFormatHTML *)emfv->preview)->html, "is-selection-active") - && (html = gtk_html_get_selection_html (((EMFormatHTML *)emfv->preview)->html, &len)) - && len && html[0] && html_contains_nonwhitespace (html, len)) { - CamelMimeMessage *msg, *src; - struct _camel_header_raw *header; - - src = (CamelMimeMessage *)((EMFormat *)emfv->preview)->message; - msg = camel_mime_message_new(); - - /* need to strip content- headers */ - header = ((CamelMimePart *)src)->headers; - while (header) { - if (g_ascii_strncasecmp(header->name, "content-", 8) != 0) - camel_medium_add_header((CamelMedium *)msg, header->name, header->value); - header = header->next; - } - camel_mime_part_set_encoding((CamelMimePart *)msg, CAMEL_TRANSFER_ENCODING_8BIT); - camel_mime_part_set_content((CamelMimePart *)msg, - html, len, "text/html"); - em_utils_reply_to_message (emfv->folder, emfv->list->cursor_uid, msg, mode, NULL); - camel_object_unref(msg); - } else { - em_utils_reply_to_message (emfv->folder, emfv->list->cursor_uid, NULL, mode, (EMFormat *)emfv->preview); - } - - g_free (html); -} - -static void -emfv_message_search(BonoboUIComponent *uic, void *data, const char *path) -{ - EMFolderView *emfv = data; - - if (!emfv->list_active) /* We are in new mail window */ - em_format_html_display_search(emfv->preview); - else { - /* We are in top level. Just grab focus to Search Bar */ - gtk_widget_grab_focus (((ESearchBar *)((EMFolderBrowser *) emfv)->search)->entry); - gtk_option_menu_set_history (GTK_OPTION_MENU (((ESearchBar *)((EMFolderBrowser *) emfv)->search)->scopeoption), 3); - } -} - -static void -emfv_print_preview_message(BonoboUIComponent *uic, void *data, const char *path) -{ - EMFolderView *emfv = data; - - em_folder_view_print(emfv, GTK_PRINT_OPERATION_ACTION_PREVIEW); -} - -static void -emfv_text_zoom_in(BonoboUIComponent *uic, void *data, const char *path) -{ - EMFolderView *emfv = data; - - if (emfv->preview) - em_format_html_display_zoom_in(emfv->preview); -} - -static void -emfv_text_zoom_out(BonoboUIComponent *uic, void *data, const char *path) -{ - EMFolderView *emfv = data; - - if (emfv->preview) - em_format_html_display_zoom_out(emfv->preview); -} - -static void -emfv_text_zoom_reset(BonoboUIComponent *uic, void *data, const char *path) -{ - EMFolderView *emfv = data; - - if (emfv->preview) - em_format_html_display_zoom_reset(emfv->preview); -} - -/* ********************************************************************** */ - -struct _filter_data { - const char *source; - char *uri; - int type; -}; - -static void -filter_data_free (struct _filter_data *fdata) -{ - g_free (fdata->uri); - g_free (fdata); -} - -static void -filter_type_got_message (CamelFolder *folder, const char *uid, CamelMimeMessage *msg, void *user_data) -{ - struct _filter_data *data = user_data; - - if (msg) - filter_gui_add_from_message (msg, data->source, data->type); - - filter_data_free (data); -} - -static void -filter_type_uid (CamelFolder *folder, const char *uid, const char *source, int type) -{ - struct _filter_data *data; - - data = g_malloc0 (sizeof (*data)); - data->type = type; - data->source = source; - - mail_get_message (folder, uid, filter_type_got_message, data, mail_msg_unordered_push); -} - -static void -filter_type_current (EMFolderView *emfv, int type) -{ - const char *source; - GPtrArray *uids; - - if (em_utils_folder_is_sent (emfv->folder, emfv->folder_uri) - || em_utils_folder_is_outbox (emfv->folder, emfv->folder_uri)) - source = FILTER_SOURCE_OUTGOING; - else - source = FILTER_SOURCE_INCOMING; - - uids = message_list_get_selected (emfv->list); - - if (uids->len == 1) - filter_type_uid (emfv->folder, (char *) uids->pdata[0], source, type); - - em_utils_uids_free (uids); -} - -EMFV_MAP_CALLBACK(emfv_tools_filter_subject, emfv_popup_filter_subject) -EMFV_MAP_CALLBACK(emfv_tools_filter_sender, emfv_popup_filter_sender) -EMFV_MAP_CALLBACK(emfv_tools_filter_recipient, emfv_popup_filter_recipients) -EMFV_MAP_CALLBACK(emfv_tools_filter_mlist, emfv_popup_filter_mlist) - -static void -vfolder_type_got_message (CamelFolder *folder, const char *uid, CamelMimeMessage *msg, void *user_data) -{ - struct _filter_data *data = user_data; - - if (msg) - vfolder_gui_add_from_message (msg, data->type, data->uri); - - filter_data_free (data); -} - -static void emp_uri_popup_vfolder_sender(EPopup *ep, EPopupItem *pitem, void *data) { EMFolderView *emfv = data; @@ -1997,273 +423,28 @@ emp_uri_popup_vfolder_recipient(EPopup *ep, EPopupItem *pitem, void *data) camel_url_free(url); } -static void -vfolder_type_uid (CamelFolder *folder, const char *uid, const char *uri, int type) -{ - struct _filter_data *data; - - data = g_malloc0 (sizeof (*data)); - data->type = type; - data->uri = g_strdup (uri); - - mail_get_message (folder, uid, vfolder_type_got_message, data, mail_msg_unordered_push); -} - -static void -vfolder_type_current (EMFolderView *emfv, int type) -{ - GPtrArray *uids; - - uids = message_list_get_selected (emfv->list); - - if (uids->len == 1) { - /* ensures vfolder is running */ - vfolder_load_storage (); - - vfolder_type_uid (emfv->folder, (char *) uids->pdata[0], emfv->folder_uri, type); - } - - em_utils_uids_free (uids); -} - -EMFV_MAP_CALLBACK(emfv_tools_vfolder_subject, emfv_popup_vfolder_subject) -EMFV_MAP_CALLBACK(emfv_tools_vfolder_sender, emfv_popup_vfolder_sender) -EMFV_MAP_CALLBACK(emfv_tools_vfolder_recipient, emfv_popup_vfolder_recipients) -EMFV_MAP_CALLBACK(emfv_tools_vfolder_mlist, emfv_popup_vfolder_mlist) - /* ********************************************************************** */ static BonoboUIVerb emfv_message_verbs[] = { - BONOBO_UI_UNSAFE_VERB ("EmptyTrash", emfv_empty_trash), - BONOBO_UI_UNSAFE_VERB ("PrepareForOffline", emfv_prepare_offline), BONOBO_UI_UNSAFE_VERB ("EditCut", emfv_edit_cut), BONOBO_UI_UNSAFE_VERB ("EditCopy", emfv_edit_copy), BONOBO_UI_UNSAFE_VERB ("EditPaste", emfv_edit_paste), - BONOBO_UI_UNSAFE_VERB ("SelectAllText", emfv_select_all_text), - - BONOBO_UI_UNSAFE_VERB ("MailNext", emfv_mail_next), - BONOBO_UI_UNSAFE_VERB ("MailNextFlagged", emfv_mail_next_flagged), - BONOBO_UI_UNSAFE_VERB ("MailNextUnread", emfv_mail_next_unread), - BONOBO_UI_UNSAFE_VERB ("MailNextThread", emfv_mail_next_thread), - BONOBO_UI_UNSAFE_VERB ("MailPrevious", emfv_mail_previous), - BONOBO_UI_UNSAFE_VERB ("MailPreviousFlagged", emfv_mail_previous_flagged), - BONOBO_UI_UNSAFE_VERB ("MailPreviousUnread", emfv_mail_previous_unread), - - BONOBO_UI_UNSAFE_VERB ("AddSenderToAddressbook", emfv_add_sender_addressbook), - - BONOBO_UI_UNSAFE_VERB ("MessageApplyFilters", emfv_message_apply_filters), - BONOBO_UI_UNSAFE_VERB ("MessageFilterJunk", emfv_message_filter_junk), - BONOBO_UI_UNSAFE_VERB ("MessageCopy", emfv_message_copy), - BONOBO_UI_UNSAFE_VERB ("MessageDelete", emfv_message_delete), - BONOBO_UI_UNSAFE_VERB ("MessageDeleteKey", emfv_message_delete), - BONOBO_UI_UNSAFE_VERB ("MessageForward", emfv_message_forward), - BONOBO_UI_UNSAFE_VERB ("MessageForwardAttached", emfv_message_forward_attached), - BONOBO_UI_UNSAFE_VERB ("MessageForwardInline", emfv_message_forward_inline), - BONOBO_UI_UNSAFE_VERB ("MessageForwardQuoted", emfv_message_forward_quoted), - BONOBO_UI_UNSAFE_VERB ("MessageRedirect", emfv_message_redirect), - BONOBO_UI_UNSAFE_VERB ("MessageMarkAsRead", emfv_message_mark_read), - BONOBO_UI_UNSAFE_VERB ("MessageMarkAsUnRead", emfv_message_mark_unread), - BONOBO_UI_UNSAFE_VERB ("MessageMarkAsImportant", emfv_message_mark_important), - BONOBO_UI_UNSAFE_VERB ("MessageMarkAsUnimportant", emfv_message_mark_unimportant), - BONOBO_UI_UNSAFE_VERB ("MessageMarkAsJunk", emfv_message_mark_junk), - BONOBO_UI_UNSAFE_VERB ("MessageMarkAsNotJunk", emfv_message_mark_nojunk), - BONOBO_UI_UNSAFE_VERB ("MessageFollowUpFlag", emfv_message_followup_flag), - BONOBO_UI_UNSAFE_VERB ("MessageFollowUpComplete", emfv_message_followup_completed), - BONOBO_UI_UNSAFE_VERB ("MessageFollowUpClear", emfv_message_followup_clear), - BONOBO_UI_UNSAFE_VERB ("MessageMove", emfv_message_move), - BONOBO_UI_UNSAFE_VERB ("MessageOpen", emfv_message_open), - BONOBO_UI_UNSAFE_VERB ("MessagePostReply", emfv_message_post_reply), - BONOBO_UI_UNSAFE_VERB ("MessageReplyAll", emfv_message_reply_all), - BONOBO_UI_UNSAFE_VERB ("MessageReplyList", emfv_message_reply_list), - BONOBO_UI_UNSAFE_VERB ("MessageReplySender", emfv_message_reply_sender), - BONOBO_UI_UNSAFE_VERB ("MessageEdit", emfv_message_edit), - BONOBO_UI_UNSAFE_VERB ("MessageSaveAs", emfv_message_saveas), - BONOBO_UI_UNSAFE_VERB ("MessageSearch", emfv_message_search), - BONOBO_UI_UNSAFE_VERB ("MessageUndelete", emfv_message_undelete), - - BONOBO_UI_UNSAFE_VERB ("PrintMessage", emfv_print_message), - BONOBO_UI_UNSAFE_VERB ("PrintPreviewMessage", emfv_print_preview_message), - - BONOBO_UI_UNSAFE_VERB ("TextZoomIn", emfv_text_zoom_in), - BONOBO_UI_UNSAFE_VERB ("TextZoomOut", emfv_text_zoom_out), - BONOBO_UI_UNSAFE_VERB ("TextZoomReset", emfv_text_zoom_reset), - - BONOBO_UI_UNSAFE_VERB ("ViewSource", emfv_message_source), - - BONOBO_UI_UNSAFE_VERB ("MailCompose", emfv_mail_compose), - - /* TODO: This stuff should just be 1 item that runs a wizard */ - BONOBO_UI_UNSAFE_VERB ("ToolsFilterMailingList", emfv_tools_filter_mlist), - BONOBO_UI_UNSAFE_VERB ("ToolsFilterRecipient", emfv_tools_filter_recipient), - BONOBO_UI_UNSAFE_VERB ("ToolsFilterSender", emfv_tools_filter_sender), - BONOBO_UI_UNSAFE_VERB ("ToolsFilterSubject", emfv_tools_filter_subject), - BONOBO_UI_UNSAFE_VERB ("ToolsVFolderMailingList", emfv_tools_vfolder_mlist), - BONOBO_UI_UNSAFE_VERB ("ToolsVFolderRecipient", emfv_tools_vfolder_recipient), - BONOBO_UI_UNSAFE_VERB ("ToolsVFolderSender", emfv_tools_vfolder_sender), - BONOBO_UI_UNSAFE_VERB ("ToolsVFolderSubject", emfv_tools_vfolder_subject), - - BONOBO_UI_UNSAFE_VERB ("ViewLoadImages", emfv_view_load_images), - /* ViewHeaders stuff is a radio */ - /* CaretMode is a toggle */ - - BONOBO_UI_VERB_END -}; -static EPixmap emfv_message_pixmaps[] = { - - E_PIXMAP ("/commands/EditCopy", "edit-copy", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/EditCut", "edit-cut", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/EditPaste", "edit-paste", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/MailCompose", "mail-message-new", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/MessageApplyFilters", "stock_mail-filters-apply", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/MessageCopy", "mail-copy", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/MessageDelete", "user-trash", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/MessageFilterJunk", "mail-mark-junk", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/MessageFollowUpFlag", "stock_mail-flag-for-followup", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/MessageForward", "mail-forward", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/MessageMarkAsImportant", "mail-mark-important", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/MessageMarkAsJunk", "mail-mark-junk", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/MessageMarkAsNotJunk", "mail-mark-notjunk", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/MessageMarkAsRead", "mail-mark-read", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/MessageMarkAsUnRead", "mail-mark-unread", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/MessageMove", "mail-move", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/MessageReplyAll", "mail-reply-all", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/MessageReplySender", "mail-reply-sender", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/MessageSaveAs", "document-save-as", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/MessageSearch", "edit-find", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/PrintMessage", "document-print", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/PrintPreviewMessage", "document-print-preview", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/TextZoomIn", "zoom-in", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/TextZoomOut", "zoom-out", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/TextZoomReset", "zoom-original", E_ICON_SIZE_MENU), - E_PIXMAP ("/commands/ViewLoadImages", "image-x-generic", E_ICON_SIZE_MENU), - - E_PIXMAP ("/menu/MessagePlaceholder/Message/MessageNavigation/GoTo", "go-jump", E_ICON_SIZE_MENU), - - E_PIXMAP ("/Toolbar/MailMessageToolbar/MessageReplySender", "mail-reply-sender", E_ICON_SIZE_LARGE_TOOLBAR), - E_PIXMAP ("/Toolbar/MailMessageToolbar/MessageReplyAll", "mail-reply-all", E_ICON_SIZE_LARGE_TOOLBAR), - E_PIXMAP ("/Toolbar/MailMessageToolbar/MessageForward", "mail-forward", E_ICON_SIZE_LARGE_TOOLBAR), - E_PIXMAP ("/Toolbar/MailMessageToolbar/PrintMessage", "document-print", E_ICON_SIZE_LARGE_TOOLBAR), - E_PIXMAP ("/Toolbar/MailMessageToolbar/MessageMove", "mail-move", E_ICON_SIZE_LARGE_TOOLBAR), - E_PIXMAP ("/Toolbar/MailMessageToolbar/MessageCopy", "mail-copy", E_ICON_SIZE_LARGE_TOOLBAR), - E_PIXMAP ("/Toolbar/MailMessageToolbar/MessageDelete", "edit-delete", E_ICON_SIZE_LARGE_TOOLBAR), - E_PIXMAP ("/Toolbar/MailMessageToolbar/MessageMarkAsJunk", "mail-mark-junk", E_ICON_SIZE_LARGE_TOOLBAR), - E_PIXMAP ("/Toolbar/MailMessageToolbar/MessageMarkAsNotJunk", "mail-mark-notjunk", E_ICON_SIZE_LARGE_TOOLBAR), - E_PIXMAP ("/Toolbar/MailNextButtons/MailNext", "go-next", E_ICON_SIZE_LARGE_TOOLBAR), - E_PIXMAP ("/Toolbar/MailNextButtons/MailPrevious", "go-previous", E_ICON_SIZE_LARGE_TOOLBAR), - - E_PIXMAP_END -}; - - -static void -emfv_enable_menus(EMFolderView *emfv) -{ - guint32 disable_mask; - GString *name; - GSList *l; - - if (emfv->uic == NULL) - return; - - { - if (emfv->menu && emfv->folder) { - EMMenuTargetSelect *t; - - t = em_menu_target_new_select(emfv->menu, emfv->folder, emfv->folder_uri, message_list_get_selected(emfv->list)); - t->target.widget = GTK_WIDGET (emfv); - e_menu_update_target((EMenu *)emfv->menu, t); - } - } - - if (emfv->folder) { - EMPopup *emp = em_popup_new("dummy"); - EMPopupTargetSelect *t; - - t = em_folder_view_get_popup_target(emfv, emp, FALSE); - disable_mask = t->target.mask; - e_popup_target_free((EPopup *)emp, t); - g_object_unref(emp); - } else { - disable_mask = ~0; - } - - name = g_string_new(""); - for (l = emfv->enable_map; l; l = l->next) { - EMFolderViewEnable *map = l->data; - int i; - - for (i=0;map[i].name;i++) { - int state = (map[i].mask & disable_mask) == 0; - - g_string_printf(name, "/commands/%s", map[i].name); - bonobo_ui_component_set_prop(emfv->uic, name->str, "sensitive", state?"1":"0", NULL); - } - } - - g_string_free(name, TRUE); -} - -static void -emfv_view_mode(BonoboUIComponent *uic, const char *path, Bonobo_UIComponent_EventType type, const char *state, void *data) -{ - EMFolderView *emfv = data; - int i; - - if (type != Bonobo_UIComponent_STATE_CHANGED) - return; - - /* TODO: I don't like this stuff much, is there any way we can move listening for such events - elsehwere? Probably not I guess, unless there's a EMFolderViewContainer for bonobo usage - of a folder view */ - - i = state[0] != '0'; +// BONOBO_UI_UNSAFE_VERB ("SelectAllText", emfv_select_all_text), - em_format_set_mode((EMFormat *)emfv->preview, i); +// BONOBO_UI_UNSAFE_VERB ("MessageDelete", emfv_message_delete), +// BONOBO_UI_UNSAFE_VERB ("MessageDeleteKey", emfv_message_delete), +// BONOBO_UI_UNSAFE_VERB ("MessageOpen", emfv_message_open), +// BONOBO_UI_UNSAFE_VERB ("MessageSearch", emfv_message_search), - if (EM_FOLDER_VIEW_GET_CLASS (emfv)->update_message_style) { - GConfClient *gconf = mail_config_get_gconf_client (); +// BONOBO_UI_UNSAFE_VERB ("ViewSource", emfv_message_source), - gconf_client_set_int (gconf, "/apps/evolution/mail/display/message_style", i, NULL); - } -} - -static void -emfv_caret_mode(BonoboUIComponent *uic, const char *path, Bonobo_UIComponent_EventType type, const char *state, void *data) -{ - EMFolderView *emfv = data; - - if (type != Bonobo_UIComponent_STATE_CHANGED) - return; - - em_format_html_display_set_caret_mode(emfv->preview, state[0] != '0'); - - gconf_client_set_bool(mail_config_get_gconf_client(), "/apps/evolution/mail/display/caret_mode", state[0] != '0', NULL); -} - -static void -emfv_charset_changed(BonoboUIComponent *uic, const char *path, Bonobo_UIComponent_EventType type, const char *state, void *data) -{ - EMFolderView *emfv = data; - - if (type != Bonobo_UIComponent_STATE_CHANGED) - return; - - /* menu items begin with "Charset-" = 8 characters */ - if (state[0] != '0' && strlen(path) > 8) { - path += 8; - /* default charset used in mail view */ - if (!strcmp(path, _("Default"))) - path = NULL; - - em_format_set_charset((EMFormat *)emfv->preview, path); - } -} + BONOBO_UI_VERB_END +}; static void emfv_activate(EMFolderView *emfv, BonoboUIComponent *uic, int act) { - struct _EMFolderViewPrivate *p = emfv->priv; if (act) { em_format_mode_t style; @@ -2276,27 +457,25 @@ emfv_activate(EMFolderView *emfv, BonoboUIComponent *uic, int act) bonobo_ui_util_set_ui(uic, PREFIX, (char *)l->data, emfv->ui_app_name, NULL); bonobo_ui_component_add_verb_list_with_data(uic, emfv_message_verbs, emfv); - e_pixmaps_update(uic, emfv_message_pixmaps); - /* must do plugin menu's after main ones because of bonobo bustedness */ if (emfv->menu) e_menu_activate((EMenu *)emfv->menu, uic, act); - state = emfv->preview->caret_mode; - bonobo_ui_component_set_prop(uic, "/commands/CaretMode", "state", state?"1":"0", NULL); - bonobo_ui_component_add_listener(uic, "CaretMode", emfv_caret_mode, emfv); +// state = emfv->preview->caret_mode; +// bonobo_ui_component_set_prop(uic, "/commands/CaretMode", "state", state?"1":"0", NULL); +// bonobo_ui_component_add_listener(uic, "CaretMode", emfv_caret_mode, emfv); - style = ((EMFormat *)emfv->preview)->mode?EM_FORMAT_ALLHEADERS:EM_FORMAT_NORMAL; - if (style) - bonobo_ui_component_set_prop(uic, "/commands/ViewFullHeaders", "state", "1", NULL); - bonobo_ui_component_add_listener(uic, "ViewFullHeaders", emfv_view_mode, emfv); - em_format_set_mode((EMFormat *)emfv->preview, style); +// style = ((EMFormat *)emfv->preview)->mode?EM_FORMAT_ALLHEADERS:EM_FORMAT_NORMAL; +// if (style) +// bonobo_ui_component_set_prop(uic, "/commands/ViewFullHeaders", "state", "1", NULL); +// bonobo_ui_component_add_listener(uic, "ViewFullHeaders", emfv_view_mode, emfv); +// em_format_set_mode((EMFormat *)emfv->preview, style); if (emfv->folder) bonobo_ui_component_set_prop(uic, "/commands/MessageEdit", "sensitive", "0", NULL); - /* default charset used in mail view */ - e_charset_picker_bonobo_ui_populate (uic, "/menu/View", _("Default"), emfv_charset_changed, emfv); +// /* default charset used in mail view */ +// e_charset_picker_bonobo_ui_populate (uic, "/menu/View", _("Default"), emfv_charset_changed, emfv); emfv_enable_menus(emfv); if (emfv->statusbar_active) @@ -2315,16 +494,6 @@ emfv_activate(EMFolderView *emfv, BonoboUIComponent *uic, int act) for (v = &emfv_message_verbs[0]; v->cname; v++) bonobo_ui_component_remove_verb(uic, v->cname); - if (p->view_instance) { - g_object_unref(p->view_instance); - p->view_instance = NULL; - } - - if (p->view_menus) { - g_object_unref(p->view_menus); - p->view_menus = NULL; - } - if (emfv->folder) mail_sync_folder(emfv->folder, NULL, NULL); @@ -2332,37 +501,6 @@ emfv_activate(EMFolderView *emfv, BonoboUIComponent *uic, int act) } } -int -em_folder_view_print (EMFolderView *emfv, GtkPrintOperationAction action) -{ - EMFormatHTMLPrint *efhp; - GPtrArray *uids; - - if (emfv->folder == NULL) - return 0; - - uids = message_list_get_selected (emfv->list); - if (uids->len != 1) - goto exit; - - efhp = em_format_html_print_new ( - (EMFormatHTML *) emfv->preview, action); - em_format_set_session ( - (EMFormat *) efhp, - ((EMFormat *) emfv->preview)->session); - em_format_merge_handler ((EMFormat *) efhp, - (EMFormat *) emfv->preview); - - em_format_html_print_message ( - efhp, emfv->folder, uids->pdata[0]); - g_object_unref (efhp); - -exit: - message_list_free_uids (emfv->list, uids); - - return 0; -} - EMPopupTargetSelect * em_folder_view_get_popup_target(EMFolderView *emfv, EMPopup *emp, int on_display) { @@ -2405,18 +543,6 @@ em_folder_view_get_popup_target(EMFolderView *emfv, EMPopup *emp, int on_display } void -em_folder_view_set_statusbar (EMFolderView *emfv, gboolean statusbar) -{ - g_return_if_fail (emfv); - - emfv->statusbar_active = statusbar; - - if (statusbar && emfv->uic) - bonobo_ui_component_set_translate (emfv->uic, "/", - "<status><item name=\"main\"/></status>", NULL); -} - -void em_folder_view_set_hide_deleted(EMFolderView *emfv, gboolean status) { if (emfv->folder && (emfv->folder->folder_flags & CAMEL_FOLDER_IS_TRASH)) @@ -2465,6 +591,7 @@ emfv_list_done_message_selected(CamelFolder *folder, const char *uid, CamelMimeM EMFolderView *emfv = data; EMEvent *eme; EMEventTargetMessage *target; + EShell *shell; if (emfv->preview == NULL) { emfv->priv->nomarkseen = FALSE; @@ -2476,7 +603,8 @@ emfv_list_done_message_selected(CamelFolder *folder, const char *uid, CamelMimeM e_profile_event_emit("goto.loaded", emfv->displayed_uid, 0); - mail_indicate_new_mail (FALSE); + shell = e_shell_module_get_shell (mail_shell_module); + e_shell_event (shell, "mail-icon", "evolution-mail"); /** @Event: message.reading * @Title: Viewing a message @@ -2596,100 +724,6 @@ emfv_message_selected_timeout(void *data) return FALSE; } -static void -emfv_list_message_selected(MessageList *ml, const char *uid, EMFolderView *emfv) -{ - e_profile_event_emit("goto.listuid", uid, 0); - - if (emfv->preview_active) { - if (emfv->priv->selected_id != 0) - g_source_remove(emfv->priv->selected_id); - - emfv->priv->selected_id = g_timeout_add(100, emfv_message_selected_timeout, emfv); - - g_free(emfv->priv->selected_uid); - emfv->priv->selected_uid = g_strdup(uid); - } - - emfv_enable_menus(emfv); - - g_signal_emit(emfv, signals[EMFV_CHANGED], 0); -} - -static void -emfv_list_built(MessageList *ml, EMFolderView *emfv) -{ - if (!emfv->priv->destroyed) { - emfv_enable_menus(emfv); - g_signal_emit(emfv, signals[EMFV_LOADED], 0); - } -} - -static void -emfv_list_double_click(ETree *tree, gint row, ETreePath path, gint col, GdkEvent *event, EMFolderView *emfv) -{ - /* Ignore double-clicks on columns that handle thier own state */ - if (MESSAGE_LIST_COLUMN_IS_ACTIVE (col)) - return; - - em_folder_view_open_selected(emfv); -} - -static int -emfv_list_right_click(ETree *tree, gint row, ETreePath path, gint col, GdkEvent *event, EMFolderView *emfv) -{ - emfv_popup(emfv, event, FALSE); - - return TRUE; -} - -static int -emfv_list_key_press(ETree *tree, int row, ETreePath path, int col, GdkEvent *ev, EMFolderView *emfv) -{ - GPtrArray *uids; - int i; - guint32 flags; - - if ((ev->key.state & GDK_CONTROL_MASK) != 0) - return FALSE; - - switch (ev->key.keyval) { - case GDK_Return: - case GDK_KP_Enter: - case GDK_ISO_Enter: - em_folder_view_open_selected(emfv); - break; -#ifdef HAVE_XFREE - case XF86XK_Reply: - emfv_message_reply(emfv, REPLY_MODE_ALL); - break; - case XF86XK_MailForward: - uids = message_list_get_selected(emfv->list); - em_utils_forward_messages (emfv->folder, uids, emfv->folder_uri); - break; -#endif /* HAVE_XFREE */ - case '!': - uids = message_list_get_selected(emfv->list); - - camel_folder_freeze(emfv->folder); - for (i = 0; i < uids->len; i++) { - flags = camel_folder_get_message_flags(emfv->folder, uids->pdata[i]) ^ CAMEL_MESSAGE_FLAGGED; - if (flags & CAMEL_MESSAGE_FLAGGED) - flags &= ~CAMEL_MESSAGE_DELETED; - camel_folder_set_message_flags(emfv->folder, uids->pdata[i], - CAMEL_MESSAGE_FLAGGED|CAMEL_MESSAGE_DELETED, flags); - } - camel_folder_thaw(emfv->folder); - - message_list_free_uids(emfv->list, uids); - break; - default: - return FALSE; - } - - return TRUE; -} - static gboolean emfv_popup_menu (GtkWidget *widget) { @@ -2711,41 +745,13 @@ emfv_popup_menu (GtkWidget *widget) } static void -emfv_list_selection_change(ETree *tree, EMFolderView *emfv) -{ - /* we can't just listen to the message-list message selected thing, since we dont get them - in all cases. blah */ - g_signal_emit(emfv, signals[EMFV_CHANGED], 0); -} - -static void -emfv_format_link_clicked(EMFormatHTMLDisplay *efhd, const char *uri, EMFolderView *emfv) -{ - if (!strncmp (uri, "##", 2)) - return; - - if (!g_ascii_strncasecmp (uri, "mailto:", 7)) { - em_utils_compose_new_message_with_mailto (uri, emfv->folder_uri); - } else if (*uri == '#') { - gtk_html_jump_to_anchor (((EMFormatHTML *) efhd)->html, uri + 1); - } else if (!g_ascii_strncasecmp (uri, "thismessage:", 12)) { - /* ignore */ - } else if (!g_ascii_strncasecmp (uri, "cid:", 4)) { - /* ignore */ - } else { - /* FIXME Pass a parent window. */ - e_show_uri (NULL, uri); - } -} - -static void emp_uri_popup_link_copy(EPopup *ep, EPopupItem *pitem, void *data) { EMFolderView *emfv = data; struct _EMFolderViewPrivate *p = emfv->priv; g_free(p->selection_uri); - p->selection_uri = g_strdup(pitem->user_data); + p->selection_uri = em_utils_url_unescape_amp(pitem->user_data); gtk_selection_owner_set(p->invisible, GDK_SELECTION_PRIMARY, gtk_get_current_event_time()); gtk_selection_owner_set(p->invisible, GDK_SELECTION_CLIPBOARD, gtk_get_current_event_time()); @@ -2976,43 +982,17 @@ emfv_set_seen(EMFolderView *emfv, const char *uid) /* keep these two tables in sync */ enum { - EMFV_ANIMATE_IMAGES = 1, - EMFV_CHARSET, - EMFV_CITATION_COLOUR, - EMFV_CITATION_MARK, - EMFV_CARET_MODE, - EMFV_MESSAGE_STYLE, - EMFV_MARK_SEEN, - EMFV_MARK_SEEN_TIMEOUT, - EMFV_LOAD_HTTP, + EMFV_CHARSET = 1, EMFV_HEADERS, - EMFV_SHOW_PREVIEW, EMFV_SHOW_DELETED, - EMFV_THREAD_LIST, - EMFV_PANED_SIZE, - EMFV_SENDER_PHOTO, - EMFV_PHOTO_LOCAL, EMFV_SETTINGS /* last, for loop count */ }; /* IF these get too long, update key field */ static const char * const emfv_display_keys[] = { - "animate_images", "charset", - "citation_colour", - "mark_citations", - "caret_mode", - "message_style", - "mark_seen", - "mark_seen_timeout", - "load_http_images", "headers", - "show_preview", "show_deleted", - "thread_list", - "paned_size", - "sender_photo", - "photo_local", }; static GHashTable *emfv_setting_key; @@ -3032,49 +1012,9 @@ emfv_setting_notify(GConfClient *gconf, guint cnxn_id, GConfEntry *entry, EMFold g_return_if_fail (tkey != NULL); switch(GPOINTER_TO_INT(g_hash_table_lookup(emfv_setting_key, tkey+1))) { - case EMFV_ANIMATE_IMAGES: - em_format_html_display_set_animate(emfv->preview, gconf_value_get_bool (value)); - break; case EMFV_CHARSET: em_format_set_default_charset((EMFormat *)emfv->preview, gconf_value_get_string (value)); break; - case EMFV_CITATION_COLOUR: { - const char *s; - GdkColor colour; - guint32 rgb; - - s = gconf_value_get_string (value); - gdk_color_parse(s?s:"#737373", &colour); - rgb = ((colour.red & 0xff00) << 8) | (colour.green & 0xff00) | ((colour.blue & 0xff00) >> 8); - em_format_html_set_mark_citations((EMFormatHTML *)emfv->preview, - ((EMFormatHTML *)emfv->preview)->mark_citations, rgb); - break; } - case EMFV_CITATION_MARK: - em_format_html_set_mark_citations((EMFormatHTML *)emfv->preview, - gconf_value_get_bool (value), - ((EMFormatHTML *)emfv->preview)->citation_colour); - break; - case EMFV_CARET_MODE: - em_format_html_display_set_caret_mode(emfv->preview, gconf_value_get_bool (value)); - break; - case EMFV_MESSAGE_STYLE: - if (EM_FOLDER_VIEW_GET_CLASS (emfv)->update_message_style) { - int style = gconf_value_get_int (value); - - if (style < EM_FORMAT_NORMAL || style > EM_FORMAT_SOURCE) - style = EM_FORMAT_NORMAL; - em_format_set_mode((EMFormat *)emfv->preview, style); - } - break; - case EMFV_MARK_SEEN: - emfv->mark_seen = gconf_value_get_bool (value); - break; - case EMFV_MARK_SEEN_TIMEOUT: - emfv->mark_seen_timeout = gconf_value_get_int (value); - break; - case EMFV_LOAD_HTTP: - em_format_html_set_load_http((EMFormatHTML *)emfv->preview, gconf_value_get_int(value)); - break; case EMFV_HEADERS: { GSList *header_config_list, *p; EMFormat *emf = (EMFormat *)emfv->preview; @@ -3099,45 +1039,6 @@ emfv_setting_notify(GConfClient *gconf, guint cnxn_id, GConfEntry *entry, EMFold if (emf->message) em_format_redraw(emf); break; } - case EMFV_SENDER_PHOTO: { - EMFormat *emf = (EMFormat *)emfv->preview; - - emf->show_photo = gconf_value_get_bool (value); - if (emf->message) - em_format_redraw(emf); - - break; } - case EMFV_PHOTO_LOCAL: { - EMFormat *emf = (EMFormat *)emfv->preview; - - emf->photo_local = gconf_value_get_bool (value); - - break; } - case EMFV_SHOW_PREVIEW: { - gboolean state_gconf, state_camel; - char *ret; - - /* If emfv->folder hasn't been initialized, do nothing */ - if (!emfv->folder) - return; - - state_gconf = gconf_value_get_bool (value); - if (state_gconf == FALSE) - emfv_enable_menus (emfv); - - if ((ret = camel_object_meta_get (emfv->folder, "evolution:show_preview"))) { - state_camel = (ret[0] != '0'); - g_free (ret); - if (state_gconf == state_camel) - return; - } - - if (camel_object_meta_set (emfv->folder, "evolution:show_preview", state_gconf ? "1" : "0")) - camel_object_state_write (emfv->folder); - if (emfv->list_active) - em_folder_browser_show_preview ((EMFolderBrowser *)emfv, state_gconf); - bonobo_ui_component_set_prop (emfv->uic, "/commands/ViewPreview", "state", state_gconf ? "1" : "0", NULL); - break; } case EMFV_SHOW_DELETED: { gboolean state; @@ -3148,143 +1049,5 @@ emfv_setting_notify(GConfClient *gconf, guint cnxn_id, GConfEntry *entry, EMFold if (emfv->uic) bonobo_ui_component_set_prop (emfv->uic, "/commands/HideDeleted", "state", state ? "0" : "1", NULL); break; } - case EMFV_THREAD_LIST: { - gboolean state_gconf, state_camel; - char *ret; - - /* If emfv->folder or emfv->list hasn't been initialized, do nothing */ - if (!emfv->folder || !emfv->list) - return; - - state_gconf = gconf_value_get_bool (value); - if ((ret = camel_object_meta_get (emfv->folder, "evolution:thread_list"))) { - state_camel = (ret[0] != '0'); - g_free (ret); - if (state_gconf == state_camel) - return; - } - - if (camel_object_meta_set (emfv->folder, "evolution:thread_list", state_gconf ? "1" : "0")) - camel_object_state_write (emfv->folder); - message_list_set_threaded (emfv->list, state_gconf); - bonobo_ui_component_set_prop (emfv->uic, "/commands/ViewThreaded", "state", state_gconf ? "1" : "0", NULL); - break; } - case EMFV_PANED_SIZE: { - EMFolderBrowser *emfb = (EMFolderBrowser *)emfv; - int paned_size; - - if (!emfv->list_active || !emfb->vpane || !emfv->preview_active) - return; - - paned_size = gconf_value_get_int (value); - if (paned_size == gtk_paned_get_position (GTK_PANED (emfb->vpane))) - return; - - gtk_paned_set_position (GTK_PANED (emfb->vpane), paned_size); - break; } - } -} - -static void -emfv_setting_setup(EMFolderView *emfv) -{ - GConfClient *gconf = gconf_client_get_default(); - GConfEntry *entry; - GError *err = NULL; - int i; - char key[64]; - - if (emfv_setting_key == NULL) { - emfv_setting_key = g_hash_table_new(g_str_hash, g_str_equal); - for (i=1;i<EMFV_SETTINGS;i++) - g_hash_table_insert(emfv_setting_key, (void *)emfv_display_keys[i-1], GINT_TO_POINTER(i)); - } - - gconf_client_add_dir(gconf, "/apps/evolution/mail/display", GCONF_CLIENT_PRELOAD_NONE, NULL); - - for (i=1;err == NULL && i<EMFV_SETTINGS;i++) { - sprintf(key, "/apps/evolution/mail/display/%s", emfv_display_keys[i-1]); - entry = gconf_client_get_entry(gconf, key, NULL, TRUE, &err); - if (entry) { - emfv_setting_notify(gconf, 0, entry, emfv); - gconf_entry_free(entry); - } - } - - if (err) { - g_warning("Could not load display settings: %s", err->message); - g_error_free(err); - } - - emfv->priv->setting_notify_id = gconf_client_notify_add(gconf, "/apps/evolution/mail/display", - (GConfClientNotifyFunc)emfv_setting_notify, - emfv, NULL, NULL); - g_object_unref(gconf); -} - -static void -emfv_on_url (EMFolderView *emfv, const char *uri, const char *nice_uri) -{ - if (emfv->statusbar_active) { - if (emfv->uic) { - bonobo_ui_component_set_status (emfv->uic, nice_uri, NULL); - /* Make sure the node keeps existing if nice_url == NULL */ - if (!nice_uri) - bonobo_ui_component_set_translate ( - emfv->uic, "/", "<status><item name=\"main\"/></status>", NULL); - } } } - -static void -emfv_on_url_cb (GObject *emitter, const char *url, EMFolderView *emfv) -{ - char *nice_url = NULL; - - if (url) { - if (strncmp (url, "mailto:", 7) == 0) { - CamelInternetAddress *cia = camel_internet_address_new(); - CamelURL *curl; - char *addr; - - curl = camel_url_new(url, NULL); - camel_address_decode((CamelAddress *)cia, curl->path); - addr = camel_address_format((CamelAddress *)cia); - nice_url = g_strdup_printf (_("Click to mail %s"), addr&&addr[0]?addr:(url + 7)); - g_free(addr); - camel_url_free(curl); - camel_object_unref(cia); - } else if (strncmp (url, "callto:", 7) == 0 || strncmp (url, "h323:", 5) == 0 || strncmp (url, "sip:", 4) == 0) { - CamelInternetAddress *cia = camel_internet_address_new(); - CamelURL *curl; - char *addr; - - curl = camel_url_new(url, NULL); - camel_address_decode((CamelAddress *)cia, curl->path); - addr = camel_address_format((CamelAddress *)cia); - nice_url = g_strdup_printf (_("Click to call %s"), addr&&addr[0]?addr:(url + 7)); - g_free(addr); - camel_url_free(curl); - camel_object_unref(cia); - } else if (!strncmp (url, "##", 2)) { - nice_url = g_strdup (_("Click to hide/unhide addresses")); - } else - nice_url = g_strdup_printf (_("Click to open %s"), url); - } - - g_signal_emit (emfv, signals[EMFV_ON_URL], 0, url, nice_url); - - g_free (nice_url); -} - -static gboolean -emfv_on_html_button_released_cb (GtkHTML *html, GdkEventButton *button, EMFolderView *emfv) -{ - gboolean selected; - - selected = gtk_html_command (html, "is-selection-active"); - bonobo_ui_component_set_prop(emfv->uic, "/commands/EditCopy", "sensitive", selected?"1":"0", NULL); - - return FALSE; -} - diff --git a/mail/em-folder-view.h b/mail/em-folder-view.h index 42ef20d296..02d6583c0b 100644 --- a/mail/em-folder-view.h +++ b/mail/em-folder-view.h @@ -25,6 +25,7 @@ #include <gtk/gtk.h> #include "mail/em-popup.h" +#include "message-list.h" /* Standard GObject macros */ #define EM_TYPE_FOLDER_VIEW \ @@ -47,7 +48,6 @@ G_BEGIN_DECLS -struct _MessageList; struct _EMFormatHTMLDisplay; struct _CamelFolder; struct _CamelMedium; @@ -80,7 +80,7 @@ struct _EMFolderView { struct _EMFolderViewPrivate *priv; - struct _MessageList *list; + MessageList *list; struct _EMFormatHTMLDisplay *preview; @@ -140,6 +140,9 @@ GtkWidget *em_folder_view_new(void); #define em_folder_view_set_folder_uri(emfv, uri) EM_FOLDER_VIEW_GET_CLASS (emfv)->set_folder_uri((emfv), (uri)) #define em_folder_view_set_message(emfv, uid, nomarkseen) EM_FOLDER_VIEW_GET_CLASS (emfv)->set_message((emfv), (uid), (nomarkseen)) +void em_folder_view_select_next_message(EMFolderView *emfv, int count, gboolean always_can_previous); +void em_folder_view_message_reply(EMFolderView *emfv, int mode); + EMPopupTargetSelect *em_folder_view_get_popup_target(EMFolderView *emfv, EMPopup *emp, int on_display); int em_folder_view_mark_selected(EMFolderView *emfv, guint32 mask, guint32 set); diff --git a/mail/em-format-html-display.c b/mail/em-format-html-display.c index 789705879d..6faa6ae803 100644 --- a/mail/em-format-html-display.c +++ b/mail/em-format-html-display.c @@ -40,17 +40,11 @@ #include <gtkhtml/gtkhtml.h> #include <gtkhtml/gtkhtml-embedded.h> -#include <gtkhtml/gtkhtml-search.h> #include <glade/glade.h> #include <glib/gi18n.h> -#include <bonobo/bonobo-control-frame.h> -#include <bonobo/bonobo-stream-memory.h> -#include <bonobo/bonobo-widget.h> -#include <bonobo-activation/bonobo-activation-mime.h> - #include <camel/camel-stream.h> #include <camel/camel-stream-filter.h> #include <camel/camel-stream-mem.h> @@ -69,7 +63,6 @@ #include <e-util/e-util-private.h> #include <libedataserver/e-msgport.h> -#include <e-util/e-gui-utils.h> #include <e-util/e-dialog-utils.h> #include <e-util/e-icon-factory.h> @@ -80,13 +73,12 @@ #include "mail-config.h" +#include "e-mail-display.h" #include "e-mail-attachment-bar.h" #include "em-format-html-display.h" -#include "e-searching-tokenizer.h" #include "em-icon-stream.h" #include "em-utils.h" #include "em-popup.h" -#include "e-icon-entry.h" #include "widgets/misc/e-attachment-button.h" #include "widgets/misc/e-attachment-view.h" @@ -102,28 +94,53 @@ #define d(x) -struct _EMFormatHTMLDisplayPrivate { - /* For the interactive search dialogue */ - /* TODO: Should this be more subtle, like the mozilla one? */ - GtkHBox *search_dialog; - GtkWidget *search_entry; - GtkWidget *search_entry_box; - GtkWidget *search_matches_label; - GtkWidget *search_case_check; - char *search_text; - int search_wrap; /* are we doing a wrap search */ - gboolean search_active; /* if the search is active */ +#define EM_FORMAT_HTML_DISPLAY_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), EM_TYPE_FORMAT_HTML_DISPLAY, EMFormatHTMLDisplayPrivate)) +struct _EMFormatHTMLDisplayPrivate { GtkWidget *attachment_view; /* weak reference */ }; -static int efhd_html_button_press_event (GtkWidget *widget, GdkEventButton *event, EMFormatHTMLDisplay *efh); -static void efhd_html_link_clicked (GtkHTML *html, const char *url, EMFormatHTMLDisplay *efhd); -static void efhd_html_on_url (GtkHTML *html, const char *url, EMFormatHTMLDisplay *efhd); +struct _smime_pobject { + EMFormatHTMLPObject object; + + int signature; + CamelCipherValidity *valid; + GtkWidget *widget; +}; + +/* TODO: move the dialogue elsehwere */ +/* FIXME: also in em-format-html.c */ +static const struct { + const char *icon, *shortdesc, *description; +} smime_sign_table[5] = { + { "stock_signature-bad", N_("Unsigned"), N_("This message is not signed. There is no guarantee that this message is authentic.") }, + { "stock_signature-ok", N_("Valid signature"), N_("This message is signed and is valid meaning that it is very likely that this message is authentic.") }, + { "stock_signature-bad", N_("Invalid signature"), N_("The signature of this message cannot be verified, it may have been altered in transit.") }, + { "stock_signature", N_("Valid signature, but cannot verify sender"), N_("This message is signed with a valid signature, but the sender of the message cannot be verified.") }, + { "stock_signature-bad", N_("Signature exists, but need public key"), N_("This message is signed with a signature, but there is no corresponding public key.") }, + +}; + +static const struct { + const char *icon, *shortdesc, *description; +} smime_encrypt_table[4] = { + { "stock_lock-broken", N_("Unencrypted"), N_("This message is not encrypted. Its content may be viewed in transit across the Internet.") }, + { "stock_lock-ok", N_("Encrypted, weak"), N_("This message is encrypted, but with a weak encryption algorithm. It would be difficult, but not impossible for an outsider to view the content of this message in a practical amount of time.") }, + { "stock_lock-ok", N_("Encrypted"), N_("This message is encrypted. It would be difficult for an outsider to view the content of this message.") }, + { "stock_lock-ok", N_("Encrypted, strong"), N_("This message is encrypted, with a strong encryption algorithm. It would be very difficult for an outsider to view the content of this message in a practical amount of time.") }, +}; + +static const char *smime_sign_colour[5] = { + "", " bgcolor=\"#88bb88\"", " bgcolor=\"#bb8888\"", " bgcolor=\"#e8d122\"","" +}; static void efhd_attachment_frame(EMFormat *emf, CamelStream *stream, EMFormatPURI *puri); static gboolean efhd_attachment_image(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject); static void efhd_message_add_bar(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info); +static gboolean efhd_attachment_button (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject); +static gboolean efhd_attachment_optional (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *object); struct _attach_puri { EMFormatPURI puri; @@ -136,7 +153,6 @@ struct _attach_puri { GtkWidget *forward, *down; /* currently no way to correlate this data to the frame :( */ GtkHTML *frame; - CamelStream *output; unsigned int shown:1; /* Embedded Frame */ @@ -160,794 +176,14 @@ struct _attach_puri { }; -static void efhd_iframe_created(GtkHTML *html, GtkHTML *iframe, EMFormatHTMLDisplay *efh); -/*static void efhd_url_requested(GtkHTML *html, const char *url, GtkHTMLStream *handle, EMFormatHTMLDisplay *efh); - static gboolean efhd_object_requested(GtkHTML *html, GtkHTMLEmbedded *eb, EMFormatHTMLDisplay *efh);*/ - static void efhd_message_prefix(EMFormat *emf, CamelStream *stream, CamelMimePart *part, EMFormatHandler *info); -static const EMFormatHandler *efhd_find_handler(EMFormat *emf, const char *mime_type); -static void efhd_format_clone(EMFormat *, CamelFolder *folder, const char *, CamelMimeMessage *msg, EMFormat *); -static void efhd_format_error(EMFormat *emf, CamelStream *stream, const char *txt); -static void efhd_format_source(EMFormat *, CamelStream *, CamelMimePart *); -static void efhd_format_attachment(EMFormat *, CamelStream *, CamelMimePart *, const char *, const EMFormatHandler *); -static void efhd_format_optional(EMFormat *, CamelStream *, CamelMimePart *, CamelStream *); -static void efhd_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, CamelCipherValidity *valid); -static void efhd_complete(EMFormat *); - -static gboolean efhd_bonobo_object(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject); -static gboolean efhd_use_component(const char *mime_type); static void efhd_builtin_init(EMFormatHTMLDisplayClass *efhc); -enum { - EFHD_LINK_CLICKED, - EFHD_POPUP_EVENT, - EFHD_ON_URL, - EFHD_LAST_SIGNAL, -}; - -static guint efhd_signals[EFHD_LAST_SIGNAL] = { 0 }; - -/* EMFormatHandler's for bonobo objects */ -static GHashTable *efhd_bonobo_handlers; -static EMFormatHTMLClass *efhd_parent; -static EMFormatClass *efhd_format_class; - -static void -efhd_gtkhtml_realise(GtkHTML *html, EMFormatHTMLDisplay *efhd) -{ - GtkStyle *style; - - /* FIXME: does this have to be re-done every time we draw? */ - - /* My favorite thing to do... muck around with colors so we respect people's stupid themes. - However, we only do this if we are rendering to the screen -- we ignore the theme - when we are printing. */ - style = gtk_widget_get_style((GtkWidget *)html); - if (style) { - int state = GTK_WIDGET_STATE(html); - gushort r, g, b; - - r = style->fg[state].red >> 8; - g = style->fg[state].green >> 8; - b = style->fg[state].blue >> 8; - - efhd->formathtml.header_colour = ((r<<16) | (g<< 8) | b) & 0xffffff; - - r = style->bg[state].red >> 8; - g = style->bg[state].green >> 8; - b = style->bg[state].blue >> 8; - - efhd->formathtml.body_colour = ((r<<16) | (g<< 8) | b) & 0xffffff; - - r = style->dark[state].red >> 8; - g = style->dark[state].green >> 8; - b = style->dark[state].blue >> 8; - - efhd->formathtml.frame_colour = ((r<<16) | (g<< 8) | b) & 0xffffff; - - r = style->base[GTK_STATE_NORMAL].red >> 8; - g = style->base[GTK_STATE_NORMAL].green >> 8; - b = style->base[GTK_STATE_NORMAL].blue >> 8; - - efhd->formathtml.content_colour = ((r<<16) | (g<< 8) | b) & 0xffffff; - - r = style->text[state].red >> 8; - g = style->text[state].green >> 8; - b = style->text[state].blue >> 8; - - efhd->formathtml.text_colour = ((r<<16) | (g<< 8) | b) & 0xffffff; -#undef DARKER - } -} - -static void -efhd_gtkhtml_style_set(GtkHTML *html, GtkStyle *old, EMFormatHTMLDisplay *efhd) -{ - efhd_gtkhtml_realise(html, efhd); - em_format_redraw((EMFormat *)efhd); -} - -static void -efhd_init(GObject *o) -{ - EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *)o; -#define efh ((EMFormatHTML *)efhd) - - efhd->priv = g_malloc0(sizeof(*efhd->priv)); - - efhd->search_tok = (ESearchingTokenizer *)e_searching_tokenizer_new(); - gtk_html_set_tokenizer (efh->html, (HTMLTokenizer *)efhd->search_tok); - - g_signal_connect(efh->html, "realize", G_CALLBACK(efhd_gtkhtml_realise), o); - g_signal_connect(efh->html, "style-set", G_CALLBACK(efhd_gtkhtml_style_set), o); - /* we want to convert url's etc */ - efh->text_html_flags |= CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS | CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES; -#undef efh - - efhd->nobar = getenv("EVOLUTION_NO_BAR") != NULL; -} - -static void -efhd_finalise(GObject *o) -{ - EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *)o; - - /* check pending stuff */ - - g_free(efhd->priv->search_text); - g_free(efhd->priv); - - ((GObjectClass *)efhd_parent)->finalize(o); -} - -static gboolean -efhd_bool_accumulator(GSignalInvocationHint *ihint, GValue *out, const GValue *in, void *data) -{ - gboolean val = g_value_get_boolean(in); - - g_value_set_boolean(out, val); - - return !val; -} - -static void -efhd_class_init(GObjectClass *klass) -{ - ((EMFormatClass *)klass)->find_handler = efhd_find_handler; - ((EMFormatClass *)klass)->format_clone = efhd_format_clone; - ((EMFormatClass *)klass)->format_error = efhd_format_error; - ((EMFormatClass *)klass)->format_source = efhd_format_source; - ((EMFormatClass *)klass)->format_attachment = efhd_format_attachment; - ((EMFormatClass *)klass)->format_optional = efhd_format_optional; - ((EMFormatClass *)klass)->format_secure = efhd_format_secure; - ((EMFormatClass *)klass)->complete = efhd_complete; - - klass->finalize = efhd_finalise; - - efhd_signals[EFHD_LINK_CLICKED] = - g_signal_new("link_clicked", - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET(EMFormatHTMLDisplayClass, link_clicked), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - - efhd_signals[EFHD_POPUP_EVENT] = - g_signal_new("popup_event", - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET(EMFormatHTMLDisplayClass, popup_event), - efhd_bool_accumulator, NULL, - e_marshal_BOOLEAN__BOXED_POINTER_POINTER, - G_TYPE_BOOLEAN, 3, - GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE, - G_TYPE_POINTER, G_TYPE_POINTER); - - efhd_signals[EFHD_ON_URL] = - g_signal_new("on_url", - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET(EMFormatHTMLDisplayClass, on_url), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - - efhd_builtin_init((EMFormatHTMLDisplayClass *)klass); -} - -GType -em_format_html_display_get_type(void) -{ - static GType type = 0; - - if (type == 0) { - static const GTypeInfo info = { - sizeof(EMFormatHTMLDisplayClass), - NULL, NULL, - (GClassInitFunc)efhd_class_init, - NULL, NULL, - sizeof(EMFormatHTMLDisplay), 0, - (GInstanceInitFunc)efhd_init - }; - efhd_parent = g_type_class_ref(em_format_html_get_type()); - efhd_format_class = g_type_class_ref(em_format_get_type()); - type = g_type_register_static(em_format_html_get_type(), "EMFormatHTMLDisplay", &info, 0); - - efhd_bonobo_handlers = g_hash_table_new(g_str_hash, g_str_equal); - } - - return type; -} - -static gboolean -efhd_scroll_event(GtkWidget *w, GdkEventScroll *event, EMFormatHTMLDisplay *efhd) -{ - if(event->state & GDK_CONTROL_MASK) - { - if(event->direction == GDK_SCROLL_UP) - { - gtk_html_zoom_in (efhd->formathtml.html); - } - else if(event->direction == GDK_SCROLL_DOWN) - { - gtk_html_zoom_out (efhd->formathtml.html); - } - return TRUE; - } - return FALSE; -} - -EMFormatHTMLDisplay *em_format_html_display_new(void) -{ - EMFormatHTMLDisplay *efhd; - - efhd = g_object_new(em_format_html_display_get_type(), 0); - - g_signal_connect(efhd->formathtml.html, "iframe_created", G_CALLBACK(efhd_iframe_created), efhd); - g_signal_connect(efhd->formathtml.html, "link_clicked", G_CALLBACK(efhd_html_link_clicked), efhd); - g_signal_connect(efhd->formathtml.html, "on_url", G_CALLBACK(efhd_html_on_url), efhd); - g_signal_connect(efhd->formathtml.html, "button_press_event", G_CALLBACK(efhd_html_button_press_event), efhd); - g_signal_connect(efhd->formathtml.html,"scroll_event", G_CALLBACK(efhd_scroll_event), efhd); - - return efhd; -} - -void em_format_html_display_goto_anchor(EMFormatHTMLDisplay *efhd, const char *name) -{ - printf("FIXME: go to anchor '%s'\n", name); -} - -void em_format_html_display_set_animate(EMFormatHTMLDisplay *efhd, gboolean state) -{ - efhd->animate = state; - gtk_html_set_animate(((EMFormatHTML *)efhd)->html, state); -} - -void em_format_html_display_set_caret_mode(EMFormatHTMLDisplay *efhd, gboolean state) -{ - efhd->caret_mode = state; - gtk_html_set_caret_mode(((EMFormatHTML *)efhd)->html, state); -} - -void -em_format_html_display_set_search(EMFormatHTMLDisplay *efhd, int type, GSList *strings) -{ - switch(type&3) { - case EM_FORMAT_HTML_DISPLAY_SEARCH_PRIMARY: - e_searching_tokenizer_set_primary_case_sensitivity(efhd->search_tok, (type&EM_FORMAT_HTML_DISPLAY_SEARCH_ICASE) == 0); - e_searching_tokenizer_set_primary_search_string(efhd->search_tok, NULL); - while (strings) { - e_searching_tokenizer_add_primary_search_string(efhd->search_tok, strings->data); - strings = strings->next; - } - break; - case EM_FORMAT_HTML_DISPLAY_SEARCH_SECONDARY: - default: - e_searching_tokenizer_set_secondary_case_sensitivity(efhd->search_tok, (type&EM_FORMAT_HTML_DISPLAY_SEARCH_ICASE) == 0); - e_searching_tokenizer_set_secondary_search_string(efhd->search_tok, NULL); - while (strings) { - e_searching_tokenizer_add_secondary_search_string(efhd->search_tok, strings->data); - strings = strings->next; - } - break; - } - - d(printf("redrawing with search\n")); - em_format_redraw((EMFormat *)efhd); -} - -static void -efhd_update_matches(EMFormatHTMLDisplay *efhd) -{ - struct _EMFormatHTMLDisplayPrivate *p = efhd->priv; - char *str; - /* message-search popup match count string */ - char *fmt = _("Matches: %d"); - - if (p->search_dialog) { - str = alloca(strlen(fmt)+32); - sprintf(str, fmt, e_searching_tokenizer_match_count(efhd->search_tok)); - gtk_label_set_text((GtkLabel *)p->search_matches_label, str); - } - gtk_widget_show((GtkWidget *)p->search_matches_label); - -} - -static void -efhd_update_search(EMFormatHTMLDisplay *efhd) -{ - struct _EMFormatHTMLDisplayPrivate *p = efhd->priv; - GSList *words = NULL; - int flags = 0; - - if (!gtk_toggle_button_get_active((GtkToggleButton *)p->search_case_check)) - flags = EM_FORMAT_HTML_DISPLAY_SEARCH_ICASE | EM_FORMAT_HTML_DISPLAY_SEARCH_PRIMARY; - else - flags = EM_FORMAT_HTML_DISPLAY_SEARCH_PRIMARY; - - if (p->search_text) - words = g_slist_append(words, p->search_text); - - em_format_html_display_set_search(efhd, flags, words); - g_slist_free(words); -} - -static void -efhd_search_response(GtkWidget *w, EMFormatHTMLDisplay *efhd) -{ - struct _EMFormatHTMLDisplayPrivate *p = efhd->priv; - - char *txt = g_strdup(gtk_entry_get_text((GtkEntry *)p->search_entry)); - - g_strstrip(txt); - if (p->search_text && strcmp(p->search_text, txt) == 0 && !p->search_wrap) { - gtk_html_engine_search_set_forward (((EMFormatHTML *)efhd)->html, TRUE); - if (!gtk_html_engine_search_next(((EMFormatHTML *)efhd)->html)) - p->search_wrap = TRUE; - g_free(txt); - } else { - g_free(p->search_text); - p->search_text = txt; - if (!p->search_wrap) - efhd_update_search(efhd); - p->search_wrap = FALSE; - gtk_html_engine_search(((EMFormatHTML *)efhd)->html, txt, - gtk_toggle_button_get_active((GtkToggleButton *)p->search_case_check), - TRUE, FALSE); - } -} - - -static void -efhd_search_response_back (GtkWidget *w, EMFormatHTMLDisplay *efhd) -{ - struct _EMFormatHTMLDisplayPrivate *p = efhd->priv; - - char *txt = g_strdup(gtk_entry_get_text((GtkEntry *)p->search_entry)); - - g_strstrip(txt); - if (p->search_text && strcmp(p->search_text, txt) == 0 && !p->search_wrap) { - gtk_html_engine_search_set_forward (((EMFormatHTML *)efhd)->html, FALSE); - if (!gtk_html_engine_search_next(((EMFormatHTML *)efhd)->html)) - p->search_wrap = TRUE; - g_free(txt); - } else { - g_free(p->search_text); - p->search_text = txt; - if (!p->search_wrap) - efhd_update_search(efhd); - p->search_wrap = FALSE; - gtk_html_engine_search(((EMFormatHTML *)efhd)->html, txt, - gtk_toggle_button_get_active((GtkToggleButton *)p->search_case_check), - FALSE, FALSE); - } -} - - -static void -efhd_search_destroy(GtkWidget *w, EMFormatHTMLDisplay *efhd) -{ - struct _EMFormatHTMLDisplayPrivate *p = efhd->priv; - g_free(p->search_text); - p->search_text = NULL; - gtk_widget_hide((GtkWidget *)p->search_dialog); - em_format_html_display_set_search(efhd, EM_FORMAT_HTML_DISPLAY_SEARCH_PRIMARY, NULL); - p->search_active = FALSE; -} - -static void -efhd_search_case_toggled(GtkWidget *w, EMFormatHTMLDisplay *efhd) -{ - struct _EMFormatHTMLDisplayPrivate *p = efhd->priv; - - g_free(p->search_text); - p->search_text = NULL; - efhd_search_response(w, efhd); -} - -static gboolean -efhd_key_pressed (GtkWidget *w, GdkEventKey *event, EMFormatHTMLDisplay *efhd) -{ - if (event->keyval == GDK_Escape){ - efhd_search_destroy (w, efhd); - return TRUE; - } - return FALSE; -} - -static void -clear_button_clicked_cb (GtkWidget *widget, gpointer dummy, EMFormatHTMLDisplay *efhd) -{ - struct _EMFormatHTMLDisplayPrivate *p = efhd->priv; - - gtk_entry_set_text (GTK_ENTRY (p->search_entry), ""); - - g_signal_emit_by_name (p->search_entry, "activate", efhd); -} - -/* Controlls the visibility of icon_entry's visibility */ -static void -icon_entry_changed_cb (GtkWidget *widget, GtkWidget *clear_button) -{ - const char *text = gtk_entry_get_text (GTK_ENTRY (widget)); - - if (text && *text) - gtk_widget_show (clear_button); - else - gtk_widget_hide (clear_button); -} - -GtkWidget * -em_format_html_get_search_dialog (EMFormatHTMLDisplay *efhd) -{ - struct _EMFormatHTMLDisplayPrivate *p = efhd->priv; - GtkWidget *hbox2, *button3, *button2, *label1; - GtkWidget *icon_entry, *clear_button; - - p->search_entry_box = gtk_hbox_new (FALSE, 0); - - label1 = gtk_label_new_with_mnemonic (_("Fin_d:")); - gtk_widget_show (label1); - gtk_box_pack_start ((GtkBox *)(p->search_entry_box), label1, FALSE, FALSE, 5); - - /* Icon entry */ - icon_entry = e_icon_entry_new (); - p->search_entry = e_icon_entry_get_entry (E_ICON_ENTRY (icon_entry)); - gtk_label_set_mnemonic_widget (GTK_LABEL (label1), p->search_entry); - gtk_widget_show (p->search_entry); - clear_button = e_icon_entry_create_button ("gtk-clear"); - e_icon_entry_pack_widget (E_ICON_ENTRY (icon_entry), clear_button, FALSE); - gtk_widget_show_all (icon_entry); - gtk_widget_hide (clear_button); - - g_signal_connect (G_OBJECT (clear_button), "button-press-event", (GCallback) clear_button_clicked_cb, efhd); - g_signal_connect (G_OBJECT (p->search_entry), "changed", (GCallback) icon_entry_changed_cb, clear_button); - - gtk_box_pack_start ((GtkBox *)(p->search_entry_box), icon_entry, FALSE, FALSE, 0); -// gtk_box_pack_start ((GtkBox *)(p->search_entry_box), icon_entry, TRUE, TRUE, 0); - - hbox2 = gtk_hbox_new (FALSE, 0); - gtk_box_pack_start ((GtkBox *)(hbox2), p->search_entry_box, FALSE, FALSE, 5); -// gtk_box_pack_start ((GtkBox *)(hbox2), p->search_entry_box, TRUE, TRUE, 5); - - button3 = gtk_button_new_with_mnemonic (_("_Previous")); - gtk_button_set_image (GTK_BUTTON (button3), GTK_WIDGET(gtk_image_new_from_stock(GTK_STOCK_GO_BACK, GTK_ICON_SIZE_BUTTON))); - gtk_widget_show (button3); - gtk_box_pack_start (GTK_BOX (hbox2), button3, FALSE, FALSE, 5); - - button2 = gtk_button_new_with_mnemonic (_("_Next")); - gtk_button_set_image (GTK_BUTTON (button2), gtk_image_new_from_stock(GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_BUTTON)); - gtk_widget_show (button2); - gtk_box_pack_start (GTK_BOX (hbox2), button2, FALSE, FALSE, 5); - - p->search_case_check = gtk_check_button_new_with_mnemonic (_("M_atch case")); - gtk_widget_show (p->search_case_check); - gtk_box_pack_start (GTK_BOX (hbox2), p->search_case_check, FALSE, FALSE, 0); - - p->search_matches_label = gtk_label_new (""); - gtk_widget_show (p->search_matches_label); - gtk_box_pack_start (GTK_BOX (hbox2), p->search_matches_label, TRUE, TRUE, 0); - p->search_dialog = GTK_HBOX (hbox2); - - p->search_wrap = FALSE; - - g_signal_connect (p->search_entry, "activate", G_CALLBACK(efhd_search_response), efhd); - g_signal_connect (p->search_entry, "key-press-event", G_CALLBACK(efhd_key_pressed), efhd); - g_signal_connect (p->search_case_check, "toggled", G_CALLBACK(efhd_search_case_toggled), efhd); - g_signal_connect (button2, "clicked", G_CALLBACK(efhd_search_response), efhd); - g_signal_connect (button3, "clicked", G_CALLBACK(efhd_search_response_back), efhd); - - p->search_active = FALSE; - - efhd_update_matches(efhd); - - return (GtkWidget *)p->search_dialog; - -} - -static void -set_focus_cb (GtkWidget *window, GtkWidget *widget, EMFormatHTMLDisplay *efhd) -{ - struct _EMFormatHTMLDisplayPrivate *p = efhd->priv; - GtkWidget *sbar = GTK_WIDGET (p->search_dialog); - - while (widget != NULL && widget != sbar) { - widget = widget->parent; - } - - if (widget != sbar) - efhd_search_destroy(widget, efhd); -} - -/** - * em_format_html_display_search: - * @efhd: - * - * Run an interactive search dialogue. - **/ -void -em_format_html_display_search(EMFormatHTMLDisplay *efhd) -{ - struct _EMFormatHTMLDisplayPrivate *p = efhd->priv; - - if (p->search_dialog){ - GtkWidget *toplevel; - - gtk_widget_show (GTK_WIDGET (p->search_dialog)); - gtk_widget_grab_focus (p->search_entry); - gtk_widget_show (p->search_entry_box); - - p->search_active = TRUE; - - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (p->search_dialog)); - - g_signal_connect (toplevel, "set-focus", - G_CALLBACK (set_focus_cb), efhd); - } - -} -/** - * em_format_html_display_search_with: - * @efhd: - * - * Run an interactive search dialogue. - **/ -void -em_format_html_display_search_with (EMFormatHTMLDisplay *efhd, char *word) -{ - struct _EMFormatHTMLDisplayPrivate *p = efhd->priv; - - if (p->search_dialog){ - gtk_widget_show (GTK_WIDGET (p->search_dialog)); - p->search_active = TRUE; - - /* Set the query */ - gtk_entry_set_text (GTK_ENTRY (p->search_entry), word); - gtk_widget_hide (p->search_entry_box); - - /* Trigger the search */ - g_signal_emit_by_name (p->search_entry, "activate", efhd); - } -} - -void -em_format_html_display_search_close (EMFormatHTMLDisplay *efhd) -{ - struct _EMFormatHTMLDisplayPrivate *p = efhd->priv; - - if (p->search_dialog && p->search_active) - efhd_search_destroy(GTK_WIDGET (p->search_dialog), efhd); -} - -void -em_format_html_display_cut (EMFormatHTMLDisplay *efhd) -{ - gtk_html_cut (((EMFormatHTML *) efhd)->html); -} - -void -em_format_html_display_copy (EMFormatHTMLDisplay *efhd) -{ - gtk_html_copy (((EMFormatHTML *) efhd)->html); -} - -void -em_format_html_display_paste (EMFormatHTMLDisplay *efhd) -{ - gtk_html_paste (((EMFormatHTML *) efhd)->html, FALSE); -} - -void -em_format_html_display_zoom_in (EMFormatHTMLDisplay *efhd) -{ - gtk_html_zoom_in (((EMFormatHTML *) efhd)->html); -} - -void -em_format_html_display_zoom_out (EMFormatHTMLDisplay *efhd) -{ - gtk_html_zoom_out (((EMFormatHTML *) efhd)->html); -} - -void -em_format_html_display_zoom_reset (EMFormatHTMLDisplay *efhd) -{ - gtk_html_zoom_reset (((EMFormatHTML *) efhd)->html); -} - -/* ********************************************************************** */ - -static void -efhd_iframe_created(GtkHTML *html, GtkHTML *iframe, EMFormatHTMLDisplay *efh) -{ - d(printf("Iframe created %p ... \n", iframe)); - - g_signal_connect(iframe, "button_press_event", G_CALLBACK (efhd_html_button_press_event), efh); - - return; -} - -static void -efhd_get_uri_puri (GtkWidget *html, GdkEventButton *event, EMFormatHTMLDisplay *efhd, char **uri, EMFormatPURI **puri) -{ - char *url, *img_url; - - g_return_if_fail (html != NULL); - g_return_if_fail (GTK_IS_HTML (html)); - g_return_if_fail (efhd != NULL); - - if (event) { - url = gtk_html_get_url_at (GTK_HTML (html), event->x, event->y); - img_url = gtk_html_get_image_src_at (GTK_HTML (html), event->x, event->y); - } else { - url = gtk_html_get_cursor_url (GTK_HTML (html)); - img_url = gtk_html_get_cursor_image_src (GTK_HTML (html)); - } - - if (img_url) { - if (!(strstr (img_url, "://") || g_ascii_strncasecmp (img_url, "cid:", 4) == 0)) { - char *u = g_strconcat ("file://", img_url, NULL); - g_free (img_url); - img_url = u; - } - } - - if (puri) { - if (url) - *puri = em_format_find_puri ((EMFormat *)efhd, url); - - if (!*puri && img_url) - *puri = em_format_find_puri ((EMFormat *)efhd, img_url); - } - - if (uri) { - *uri = NULL; - if (img_url && g_ascii_strncasecmp (img_url, "cid:", 4) != 0) { - if (url) - *uri = g_strdup_printf ("%s\n%s", url, img_url); - else { - *uri = img_url; - img_url = NULL; - } - } else { - *uri = url; - url = NULL; - } - } - - g_free (url); - g_free (img_url); -} - -static int -efhd_html_button_press_event (GtkWidget *widget, GdkEventButton *event, EMFormatHTMLDisplay *efhd) -{ - char *uri = NULL; - EMFormatPURI *puri = NULL; - gboolean res = FALSE; - - if (event->button != 3) - return FALSE; - - d(printf("popup button pressed\n")); - - efhd_get_uri_puri (widget, event, efhd, &uri, &puri); - - if (uri && !strncmp (uri, "##", 2)) { - g_free (uri); - return TRUE; - } - - g_signal_emit((GtkObject *)efhd, efhd_signals[EFHD_POPUP_EVENT], 0, event, uri, puri?puri->part:NULL, &res); - - g_free (uri); - - return res; -} - -gboolean -em_format_html_display_popup_menu (EMFormatHTMLDisplay *efhd) -{ - GtkHTML *html; - char *uri = NULL; - EMFormatPURI *puri = NULL; - gboolean res = FALSE; - - html = efhd->formathtml.html; - - efhd_get_uri_puri (GTK_WIDGET (html), NULL, efhd, &uri, &puri); - - g_signal_emit ((GtkObject *)efhd, efhd_signals[EFHD_POPUP_EVENT], 0, NULL, uri, puri?puri->part:NULL, &res); - - g_free (uri); - - return res; -} - -static void -efhd_html_link_clicked (GtkHTML *html, const char *url, EMFormatHTMLDisplay *efhd) -{ - d(printf("link clicked event '%s'\n", url)); - if (url && !strncmp(url, "##", 2)) { - if (!strcmp (url, "##TO##")) - if (!(((EMFormatHTML *) efhd)->header_wrap_flags & EM_FORMAT_HTML_HEADER_TO)) - ((EMFormatHTML *) efhd)->header_wrap_flags |= EM_FORMAT_HTML_HEADER_TO; - else - ((EMFormatHTML *) efhd)->header_wrap_flags &= ~EM_FORMAT_HTML_HEADER_TO; - else if (!strcmp (url, "##CC##")) - if (!(((EMFormatHTML *) efhd)->header_wrap_flags & EM_FORMAT_HTML_HEADER_CC)) - ((EMFormatHTML *) efhd)->header_wrap_flags |= EM_FORMAT_HTML_HEADER_CC; - else - ((EMFormatHTML *) efhd)->header_wrap_flags &= ~EM_FORMAT_HTML_HEADER_CC; - else if (!strcmp (url, "##BCC##")) { - if (!(((EMFormatHTML *) efhd)->header_wrap_flags & EM_FORMAT_HTML_HEADER_BCC)) - ((EMFormatHTML *) efhd)->header_wrap_flags |= EM_FORMAT_HTML_HEADER_BCC; - else - ((EMFormatHTML *) efhd)->header_wrap_flags &= ~EM_FORMAT_HTML_HEADER_BCC; - } - em_format_redraw((EMFormat *)efhd); - } else - g_signal_emit((GObject *)efhd, efhd_signals[EFHD_LINK_CLICKED], 0, url); -} - -static void -efhd_html_on_url (GtkHTML *html, const char *url, EMFormatHTMLDisplay *efhd) -{ - d(printf("on_url event '%s'\n", url)); - - g_signal_emit((GObject *)efhd, efhd_signals[EFHD_ON_URL], 0, url); -} +static gpointer parent_class; static void -efhd_complete(EMFormat *emf) -{ - EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *)emf; - - if (efhd->priv->search_dialog && efhd->priv->search_active) - efhd_update_matches(efhd); -} - -/* ********************************************************************** */ - -/* TODO: move the dialogue elsehwere */ -/* FIXME: also in em-format-html.c */ -static const struct { - const char *icon, *shortdesc, *description; -} smime_sign_table[5] = { - { "stock_signature-bad", N_("Unsigned"), N_("This message is not signed. There is no guarantee that this message is authentic.") }, - { "stock_signature-ok", N_("Valid signature"), N_("This message is signed and is valid meaning that it is very likely that this message is authentic.") }, - { "stock_signature-bad", N_("Invalid signature"), N_("The signature of this message cannot be verified, it may have been altered in transit.") }, - { "stock_signature", N_("Valid signature, but cannot verify sender"), N_("This message is signed with a valid signature, but the sender of the message cannot be verified.") }, - { "stock_signature-bad", N_("Signature exists, but need public key"), N_("This message is signed with a signature, but there is no corresponding public key.") }, - -}; - -static const struct { - const char *icon, *shortdesc, *description; -} smime_encrypt_table[4] = { - { "stock_lock-broken", N_("Unencrypted"), N_("This message is not encrypted. Its content may be viewed in transit across the Internet.") }, - { "stock_lock-ok", N_("Encrypted, weak"), N_("This message is encrypted, but with a weak encryption algorithm. It would be difficult, but not impossible for an outsider to view the content of this message in a practical amount of time.") }, - { "stock_lock-ok", N_("Encrypted"), N_("This message is encrypted. It would be difficult for an outsider to view the content of this message.") }, - { "stock_lock-ok", N_("Encrypted, strong"), N_("This message is encrypted, with a strong encryption algorithm. It would be very difficult for an outsider to view the content of this message in a practical amount of time.") }, -}; - -static const char *smime_sign_colour[5] = { - "", " bgcolor=\"#88bb88\"", " bgcolor=\"#bb8888\"", " bgcolor=\"#e8d122\"","" -}; - -struct _smime_pobject { - EMFormatHTMLPObject object; - - int signature; - CamelCipherValidity *valid; - GtkWidget *widget; -}; - -static void -efhd_xpkcs7mime_free(EMFormatHTMLPObject *o) +efhd_xpkcs7mime_free (EMFormatHTMLPObject *o) { struct _smime_pobject *po = (struct _smime_pobject *)o; @@ -957,21 +193,18 @@ efhd_xpkcs7mime_free(EMFormatHTMLPObject *o) } static void -efhd_xpkcs7mime_info_response(GtkWidget *w, guint button, struct _smime_pobject *po) +efhd_xpkcs7mime_info_response (GtkWidget *widget, + guint button, + struct _smime_pobject *po) { - gtk_widget_destroy(w); + gtk_widget_destroy (widget); po->widget = NULL; } #ifdef HAVE_NSS static void -efhd_xpkcs7mime_viewcert_foad(GtkWidget *w, guint button, struct _smime_pobject *po) -{ - gtk_widget_destroy(w); -} - -static void -efhd_xpkcs7mime_viewcert_clicked(GtkWidget *button, struct _smime_pobject *po) +efhd_xpkcs7mime_viewcert_clicked (GtkWidget *button, + struct _smime_pobject *po) { CamelCipherCertInfo *info = g_object_get_data((GObject *)button, "e-cert-info"); ECertDB *db = e_cert_db_peek(); @@ -988,7 +221,7 @@ efhd_xpkcs7mime_viewcert_clicked(GtkWidget *button, struct _smime_pobject *po) /* oddly enough certificate_viewer_show doesn't ... */ gtk_widget_show(w); - g_signal_connect(w, "response", G_CALLBACK(efhd_xpkcs7mime_viewcert_foad), po); + g_signal_connect(w, "response", G_CALLBACK(gtk_widget_destroy), NULL); if (w && po->widget) gtk_window_set_transient_for((GtkWindow *)w, (GtkWindow *)po->widget); @@ -1001,7 +234,9 @@ efhd_xpkcs7mime_viewcert_clicked(GtkWidget *button, struct _smime_pobject *po) #endif static void -efhd_xpkcs7mime_add_cert_table(GtkWidget *vbox, CamelDList *certlist, struct _smime_pobject *po) +efhd_xpkcs7mime_add_cert_table (GtkWidget *vbox, + CamelDList *certlist, + struct _smime_pobject *po) { CamelCipherCertInfo *info = (CamelCipherCertInfo *)certlist->head; GtkTable *table = (GtkTable *)gtk_table_new(camel_dlist_length(certlist), 2, FALSE); @@ -1060,7 +295,8 @@ efhd_xpkcs7mime_add_cert_table(GtkWidget *vbox, CamelDList *certlist, struct _sm } static void -efhd_xpkcs7mime_validity_clicked(GtkWidget *button, EMFormatHTMLPObject *pobject) +efhd_xpkcs7mime_validity_clicked (GtkWidget *button, + EMFormatHTMLPObject *pobject) { struct _smime_pobject *po = (struct _smime_pobject *)pobject; GladeXML *xml; @@ -1071,10 +307,9 @@ efhd_xpkcs7mime_validity_clicked(GtkWidget *button, EMFormatHTMLPObject *pobject /* FIXME: window raise? */ return; - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - "mail-dialogs.glade", - NULL); - xml = glade_xml_new(gladefile, "message_security_dialog", NULL); + gladefile = g_build_filename ( + EVOLUTION_GLADEDIR, "mail-dialogs.glade", NULL); + xml = glade_xml_new (gladefile, "message_security_dialog", NULL); g_free (gladefile); po->widget = glade_xml_get_widget(xml, "message_security_dialog"); @@ -1150,9 +385,12 @@ efhd_xpkcs7mime_validity_clicked(GtkWidget *button, EMFormatHTMLPObject *pobject } static gboolean -efhd_xpkcs7mime_button(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject) +efhd_xpkcs7mime_button (EMFormatHTML *efh, + GtkHTMLEmbedded *eb, + EMFormatHTMLPObject *pobject) { - GtkWidget *icon, *button; + GtkWidget *container; + GtkWidget *widget; struct _smime_pobject *po = (struct _smime_pobject *)pobject; const char *icon_name; @@ -1162,25 +400,171 @@ efhd_xpkcs7mime_button(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObje else icon_name = smime_encrypt_table[po->valid->encrypt.status].icon; - icon = gtk_image_new_from_icon_name ( - icon_name, GTK_ICON_SIZE_LARGE_TOOLBAR); - gtk_widget_show(icon); + container = GTK_WIDGET (eb); - button = gtk_button_new(); - g_signal_connect(button, "clicked", G_CALLBACK(efhd_xpkcs7mime_validity_clicked), pobject); + widget = gtk_button_new (); + g_signal_connect ( + widget, "clicked", + G_CALLBACK (efhd_xpkcs7mime_validity_clicked), pobject); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); - gtk_container_add((GtkContainer *)button, icon); - gtk_widget_show(button); - gtk_container_add((GtkContainer *)eb, button); + container = widget; + + widget = gtk_image_new_from_icon_name ( + icon_name, GTK_ICON_SIZE_LARGE_TOOLBAR); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); return TRUE; } static void -efhd_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, CamelCipherValidity *valid) +efhd_format_clone (EMFormat *emf, + CamelFolder *folder, + const gchar *uid, + CamelMimeMessage *msg, + EMFormat *src) { - /* Note: We call EMFormatClass directly, not EMFormatHTML, our parent */ - efhd_format_class->format_secure(emf, stream, part, valid); + if (emf != src) + EM_FORMAT_HTML (emf)->header_wrap_flags = 0; + + /* Chain up to parent's format_clone() method. */ + EM_FORMAT_CLASS (parent_class)-> + format_clone (emf, folder, uid, msg, src); +} + +static void +efhd_format_attachment (EMFormat *emf, + CamelStream *stream, + CamelMimePart *part, + const gchar *mime_type, + const EMFormatHandler *handle) +{ + char *classid, *text, *html; + struct _attach_puri *info; + + classid = g_strdup_printf ("attachment%s", emf->part_id->str); + info = (struct _attach_puri *) em_format_add_puri ( + emf, sizeof (*info), classid, part, efhd_attachment_frame); + em_format_html_add_pobject ( + EM_FORMAT_HTML (emf), sizeof (EMFormatHTMLPObject), + classid, part, efhd_attachment_button); + info->handle = handle; + info->shown = em_format_is_inline ( + emf, info->puri.part_id, info->puri.part, handle); + info->snoop_mime_type = emf->snoop_mime_type; + info->attachment = e_attachment_new (); + e_attachment_set_mime_part (info->attachment, info->puri.part); + + if (emf->valid) { + info->sign = emf->valid->sign.status; + info->encrypt = emf->valid->encrypt.status; + } + + camel_stream_write_string ( + stream, EM_FORMAT_HTML_VPAD + "<table cellspacing=0 cellpadding=0><tr><td>" + "<table width=10 cellspacing=0 cellpadding=0>" + "<tr><td></td></tr></table></td>"); + + camel_stream_printf ( + stream, "<td><object classid=\"%s\"></object></td>", classid); + + camel_stream_write_string ( + stream, "<td><table width=3 cellspacing=0 cellpadding=0>" + "<tr><td></td></tr></table></td><td><font size=-1>"); + + /* output some info about it */ + /* FIXME: should we look up mime_type from object again? */ + text = em_format_describe_part (part, mime_type); + html = camel_text_to_html ( + text, EM_FORMAT_HTML (emf)->text_html_flags & + CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0); + camel_stream_write_string (stream, html); + g_free (html); + g_free (text); + + camel_stream_write_string ( + stream, "</font></td></tr><tr></table>\n" + EM_FORMAT_HTML_VPAD); + + if (handle && info->shown) + handle->handler (emf, stream, part, handle); + + g_free (classid); +} + +static void +efhd_format_optional (EMFormat *emf, + CamelStream *fstream, + CamelMimePart *part, + CamelStream *mstream) +{ + char *classid, *html; + struct _attach_puri *info; + CamelStream *stream; + + if (CAMEL_IS_STREAM_FILTER (fstream) && ((CamelStreamFilter *) fstream)->source) + stream = ((CamelStreamFilter *) fstream)->source; + else + stream = fstream; + + classid = g_strdup_printf ("optional%s", emf->part_id->str); + info = (struct _attach_puri *) em_format_add_puri ( + emf, sizeof (*info), classid, part, efhd_attachment_frame); + em_format_html_add_pobject ( + EM_FORMAT_HTML (emf), sizeof (EMFormatHTMLPObject), + classid, part, efhd_attachment_optional); + info->handle = em_format_find_handler (emf, "text/plain"); + info->shown = FALSE; + info->snoop_mime_type = "text/plain"; + info->attachment = e_attachment_new (); + e_attachment_set_mime_part (info->attachment, info->puri.part); + info->mstream = (CamelStreamMem *) mstream; + if (emf->valid) { + info->sign = emf->valid->sign.status; + info->encrypt = emf->valid->encrypt.status; + } + + camel_stream_write_string ( + stream, EM_FORMAT_HTML_VPAD + "<table cellspacing=0 cellpadding=0><tr><td>" + "<h3><font size=-1 color=red>"); + + html = camel_text_to_html ( + _("Evolution cannot render this email as it is too " + "large to process. You can view it unformatted or " + "with an external text editor."), + EM_FORMAT_HTML (emf)->text_html_flags & + CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0); + camel_stream_write_string (stream, html); + camel_stream_write_string ( + stream, "</font></h3></td></tr></table>\n"); + camel_stream_write_string ( + stream, "<table cellspacing=0 cellpadding=0><tr>"); + camel_stream_printf ( + stream, "<td><object classid=\"%s\"></object>" + "</td></tr></table>", classid); + + g_free(html); + + camel_stream_write_string ( + stream, EM_FORMAT_HTML_VPAD); + + g_free (classid); +} + +static void +efhd_format_secure (EMFormat *emf, + CamelStream *stream, + CamelMimePart *part, + CamelCipherValidity *valid) +{ + EMFormatClass *format_class; + + format_class = g_type_class_peek (EM_TYPE_FORMAT); + format_class->format_secure (emf, stream, part, valid); if (emf->valid == valid && (valid->encrypt.status != CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE @@ -1188,24 +572,45 @@ efhd_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, Came char *classid; struct _smime_pobject *pobj; - camel_stream_printf (stream, "<table border=0 width=\"100%%\" cellpadding=3 cellspacing=0%s><tr>", - smime_sign_colour[valid->sign.status]); - - classid = g_strdup_printf("smime:///em-format-html/%s/icon/signed", emf->part_id->str); - pobj = (struct _smime_pobject *)em_format_html_add_pobject((EMFormatHTML *)emf, sizeof(*pobj), classid, part, efhd_xpkcs7mime_button); + camel_stream_printf ( + stream, "<table border=0 width=\"100%%\" " + "cellpadding=3 cellspacing=0%s><tr>", + smime_sign_colour[valid->sign.status]); + + classid = g_strdup_printf ( + "smime:///em-format-html/%s/icon/signed", + emf->part_id->str); + pobj = (struct _smime_pobject *) em_format_html_add_pobject ( + EM_FORMAT_HTML (emf), sizeof (*pobj), + classid, part, efhd_xpkcs7mime_button); pobj->valid = camel_cipher_validity_clone(valid); pobj->object.free = efhd_xpkcs7mime_free; - camel_stream_printf(stream, "<td valign=center><object classid=\"%s\"></object></td><td width=100%% valign=center>", classid); - g_free(classid); + camel_stream_printf ( + stream, "<td valign=center><object classid=\"%s\">" + "</object></td><td width=100%% valign=center>", + classid); + g_free (classid); + if (valid->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE) { - camel_stream_printf (stream, "%s", _(smime_sign_table[valid->sign.status].shortdesc)); + const gchar *desc; + gint status; + + status = valid->sign.status; + desc = smime_sign_table[status].shortdesc; + camel_stream_printf (stream, "%s", gettext (desc)); } if (valid->encrypt.status != CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE) { + const gchar *desc; + gint status; + if (valid->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE) { camel_stream_printf (stream, "<br>"); } - camel_stream_printf (stream, "%s", _(smime_encrypt_table[valid->encrypt.status].shortdesc)); + + status = valid->encrypt.status; + desc = smime_encrypt_table[status].shortdesc; + camel_stream_printf (stream, "%s", gettext (desc)); } camel_stream_printf(stream, "</td></tr></table>"); @@ -1213,6 +618,80 @@ efhd_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, Came } static void +efhd_class_init (EMFormatHTMLDisplayClass *class) +{ + EMFormatClass *format_class; + EMFormatHTMLClass *format_html_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMFormatHTMLDisplayPrivate)); + + format_class = EM_FORMAT_CLASS (class); + format_class->format_clone = efhd_format_clone; + format_class->format_attachment = efhd_format_attachment; + format_class->format_optional = efhd_format_optional; + format_class->format_secure = efhd_format_secure; + + format_html_class = EM_FORMAT_HTML_CLASS (class); + format_html_class->html_widget_type = E_TYPE_MAIL_DISPLAY; + + efhd_builtin_init (class); +} + +static void +efhd_init (EMFormatHTMLDisplay *efhd) +{ + GtkHTML *html; + + html = EM_FORMAT_HTML (efhd)->html; + + efhd->priv = EM_FORMAT_HTML_DISPLAY_GET_PRIVATE (efhd); + + e_mail_display_set_formatter ( + E_MAIL_DISPLAY (html), EM_FORMAT_HTML (efhd)); + + /* we want to convert url's etc */ + EM_FORMAT_HTML (efhd)->text_html_flags |= + CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS | + CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES; +} + +GType +em_format_html_display_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMFormatHTMLDisplayClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) efhd_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMFormatHTMLDisplay), + 0, /* n_preallocs */ + (GInstanceInitFunc) efhd_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + EM_TYPE_FORMAT_HTML, "EMFormatHTMLDisplay", + &type_info, 0); + } + + return type; +} + +EMFormatHTMLDisplay * +em_format_html_display_new (void) +{ + return g_object_new (EM_TYPE_FORMAT_HTML_DISPLAY, NULL); +} + +/* ********************************************************************** */ + +static void efhd_image(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFormatHandler *handle) { char *classid; @@ -1263,7 +742,7 @@ static EMFormatHandler type_builtin_table[] = { { "image/pjpeg", (EMFormatFunc)efhd_image }, { "x-evolution/message/prefix", (EMFormatFunc)efhd_message_prefix }, - { "x-evolution/message/post-header", (EMFormatFunc)efhd_message_add_bar } + { "x-evolution/message/post-header", (EMFormatFunc)efhd_message_add_bar }, }; static void @@ -1275,48 +754,6 @@ efhd_builtin_init(EMFormatHTMLDisplayClass *efhc) em_format_class_add_handler((EMFormatClass *)efhc, &type_builtin_table[i]); } -/* ********************************************************************** */ -static void -efhd_bonobo_unknown(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info) -{ - char *classid; - - classid = g_strdup_printf("bonobo-unknown:///em-format-html-display/%s", emf->part_id->str); - em_format_html_add_pobject((EMFormatHTML *)emf, sizeof(EMFormatHTMLPObject), classid, part, efhd_bonobo_object); - camel_stream_printf(stream, "<object classid=\"%s\" type=\"%s\"></object><br>\n", classid, info->mime_type); - g_free(classid); -} - - /* ********************************************************************** */ -static const EMFormatHandler *efhd_find_handler(EMFormat *emf, const char *mime_type) -{ - const EMFormatHandler *handle; - - if ( (handle = ((EMFormatClass *)efhd_parent)->find_handler(emf, mime_type)) == NULL - && efhd_use_component(mime_type) - && (handle = g_hash_table_lookup(efhd_bonobo_handlers, mime_type)) == NULL) { - - EMFormatHandler *h = g_malloc0(sizeof(*h)); - - h->mime_type = g_strdup(mime_type); - h->handler = efhd_bonobo_unknown; - h->flags = EM_FORMAT_HANDLER_INLINE_DISPOSITION; - g_hash_table_insert(efhd_bonobo_handlers, h->mime_type, h); - - handle = h; - } - - return handle; -} - -static void efhd_format_clone(EMFormat *emf, CamelFolder *folder, const char *uid, CamelMimeMessage *msg, EMFormat *src) -{ - if (emf != src) - ((EMFormatHTML *) emf)->header_wrap_flags = 0; - - ((EMFormatClass *)efhd_parent)->format_clone(emf, folder, uid, msg, src); -} - static void efhd_write_image(EMFormat *emf, CamelStream *stream, EMFormatPURI *puri) { @@ -1328,7 +765,8 @@ efhd_write_image(EMFormat *emf, CamelStream *stream, EMFormatPURI *puri) camel_stream_close(stream); } -static void efhd_message_prefix(EMFormat *emf, CamelStream *stream, CamelMimePart *part, EMFormatHandler *info) +static void +efhd_message_prefix(EMFormat *emf, CamelStream *stream, CamelMimePart *part, EMFormatHandler *info) { const char *flag, *comp, *due; time_t date; @@ -1387,17 +825,6 @@ static void efhd_message_prefix(EMFormat *emf, CamelStream *stream, CamelMimePar camel_stream_printf(stream, "</td></tr></table>"); } -/* TODO: if these aren't going to do anything should remove */ -static void efhd_format_error(EMFormat *emf, CamelStream *stream, const char *txt) -{ - ((EMFormatClass *)efhd_parent)->format_error(emf, stream, txt); -} - -static void efhd_format_source(EMFormat *emf, CamelStream *stream, CamelMimePart *part) -{ - ((EMFormatClass *)efhd_parent)->format_source(emf, stream, part); -} - /* ********************************************************************** */ /* Checks on the widget whether it can be processed, based on the state of EMFormatHTML. @@ -1825,187 +1252,35 @@ efhd_attachment_button(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObje return TRUE; } -/* not used currently */ -/* frame source callback */ static void -efhd_attachment_frame(EMFormat *emf, CamelStream *stream, EMFormatPURI *puri) +efhd_attachment_frame (EMFormat *emf, + CamelStream *stream, + EMFormatPURI *puri) { struct _attach_puri *info = (struct _attach_puri *)puri; - if (info->shown) { - d(printf("writing to frame content, handler is '%s'\n", info->handle->mime_type)); - info->handle->handler(emf, stream, info->puri.part, info->handle); - camel_stream_close(stream); - } else { - /* FIXME: this is leaked if the object is closed without showing it - NB: need a virtual puri_free method? */ - info->output = stream; - camel_object_ref(stream); - } -} + if (info->shown) + info->handle->handler ( + emf, stream, info->puri.part, info->handle); -static gboolean -efhd_bonobo_object(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject) -{ - CamelDataWrapper *wrapper; - Bonobo_ServerInfo *component; - GtkWidget *embedded; - Bonobo_PersistStream persist; - CORBA_Environment ev; - CamelStreamMem *cstream; - BonoboStream *bstream; - BonoboControlFrame *control_frame; - Bonobo_PropertyBag prop_bag; - - component = bonobo_activation_get_default_component_for_mime_type (eb->type); - if (component == NULL) - return FALSE; - - embedded = bonobo_widget_new_control(component->iid, NULL); - CORBA_free(component); - if (embedded == NULL) - return FALSE; - - CORBA_exception_init(&ev); - - control_frame = bonobo_widget_get_control_frame((BonoboWidget *)embedded); - prop_bag = bonobo_control_frame_get_control_property_bag(control_frame, NULL); - if (prop_bag != CORBA_OBJECT_NIL) { - /* - * Now we can take care of business. Currently, the only control - * that needs something passed to it through a property bag is - * the iTip control, and it needs only the From email address, - * but perhaps in the future we can generalize this section of code - * to pass a bunch of useful things to all embedded controls. - */ - const CamelInternetAddress *from; - char *from_address; - - from = camel_mime_message_get_from((CamelMimeMessage *)((EMFormat *)efh)->message); - from_address = camel_address_encode((CamelAddress *)from); - bonobo_property_bag_client_set_value_string(prop_bag, "from_address", from_address, &ev); - g_free(from_address); - - Bonobo_Unknown_unref(prop_bag, &ev); - } - - persist = (Bonobo_PersistStream)Bonobo_Unknown_queryInterface(bonobo_widget_get_objref((BonoboWidget *)embedded), - "IDL:Bonobo/PersistStream:1.0", &ev); - if (persist == CORBA_OBJECT_NIL) { - g_object_ref_sink(embedded); - CORBA_exception_free(&ev); - return FALSE; - } - - /* Write the data to a CamelStreamMem... */ - cstream = (CamelStreamMem *)camel_stream_mem_new(); - wrapper = camel_medium_get_content_object((CamelMedium *)pobject->part); - if (FALSE && !g_ascii_strncasecmp (eb->type, "text/", 5)) { - /* do charset conversion, etc */ - d(printf("performing charset conversion for %s component\n", eb->type)); - em_format_format_text((EMFormat *)efh, (CamelStream *)cstream, wrapper); - } else { - camel_data_wrapper_decode_to_stream (wrapper, (CamelStream *) cstream); - } - - /* ...convert the CamelStreamMem to a BonoboStreamMem... */ - bstream = bonobo_stream_mem_create((char *)cstream->buffer->data, cstream->buffer->len, TRUE, FALSE); - camel_object_unref(cstream); - - /* ...and hydrate the PersistStream from the BonoboStream. */ - Bonobo_PersistStream_load(persist, - bonobo_object_corba_objref(BONOBO_OBJECT (bstream)), - eb->type, &ev); - bonobo_object_unref(BONOBO_OBJECT (bstream)); - Bonobo_Unknown_unref(persist, &ev); - CORBA_Object_release(persist, &ev); - - if (ev._major != CORBA_NO_EXCEPTION) { - g_object_ref_sink(embedded); - CORBA_exception_free(&ev); - return FALSE; - } - CORBA_exception_free(&ev); - - gtk_widget_show(embedded); - gtk_container_add(GTK_CONTAINER (eb), embedded); - - return TRUE; -} - -static gboolean -efhd_check_server_prop(Bonobo_ServerInfo *component, const char *propname, const char *value) -{ - CORBA_sequence_CORBA_string stringv; - Bonobo_ActivationProperty *prop; - int i; - - prop = bonobo_server_info_prop_find(component, propname); - if (!prop || prop->v._d != Bonobo_ACTIVATION_P_STRINGV) - return FALSE; - - stringv = prop->v._u.value_stringv; - for (i = 0; i < stringv._length; i++) { - if (!g_ascii_strcasecmp(value, stringv._buffer[i])) - return TRUE; - } - - return FALSE; -} - -static gboolean -efhd_use_component(const char *mime_type) -{ - GList *components, *iter; - Bonobo_ServerInfo *component = NULL; - - /* should this cache it? */ - - if (g_ascii_strcasecmp(mime_type, "text/x-vcard") != 0 - && g_ascii_strcasecmp(mime_type, "text/calendar") != 0) { - const char **mime_types; - int i; - - mime_types = mail_config_get_allowable_mime_types(); - for (i = 0; mime_types[i]; i++) { - if (!g_ascii_strcasecmp(mime_types[i], mime_type)) - goto type_ok; - } - return FALSE; - } -type_ok: - components = bonobo_activation_get_all_components_for_mime_type (mime_type); - for (iter = components; iter; iter = iter->next) { - Bonobo_ServerInfo *comp = iter->data; - - comp = iter->data; - if (efhd_check_server_prop(comp, "repo_ids", "IDL:Bonobo/PersistStream:1.0") - && efhd_check_server_prop(comp, "bonobo:supported_mime_types", mime_type)) { - component = comp; - break; - } - } - - /* FIXME: How should I free the Bonobo_ServerInfo's ? */ - g_list_foreach (components, (GFunc)CORBA_free, NULL); - g_list_free (components); - - return component != NULL; + camel_stream_close (stream); } static void efhd_bar_resize (EMFormatHTML *efh, GtkAllocation *event) { - EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *) efh; + EMFormatHTMLDisplayPrivate *priv; GtkWidget *widget; gint width; + priv = EM_FORMAT_HTML_DISPLAY_GET_PRIVATE (efh); + widget = GTK_WIDGET (efh->html); width = widget->allocation.width - 12; if (width > 0) { - widget = efhd->priv->attachment_view; + widget = priv->attachment_view; gtk_widget_set_size_request (widget, width, -1); } } @@ -2015,12 +1290,14 @@ efhd_add_bar (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject) { - EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *) efh; + EMFormatHTMLDisplayPrivate *priv; GtkWidget *widget; + priv = EM_FORMAT_HTML_DISPLAY_GET_PRIVATE (efh); + widget = e_mail_attachment_bar_new (); gtk_container_add (GTK_CONTAINER (eb), widget); - efhd->priv->attachment_view = widget; + priv->attachment_view = widget; gtk_widget_hide (widget); g_signal_connect_swapped ( @@ -2039,7 +1316,7 @@ efhd_message_add_bar (EMFormat *emf, const char *classid = "attachment-bar"; em_format_html_add_pobject ( - (EMFormatHTML *) emf, + EM_FORMAT_HTML (emf), sizeof (EMFormatHTMLPObject), classid, part, efhd_add_bar); @@ -2048,71 +1325,6 @@ efhd_message_add_bar (EMFormat *emf, } static void -efhd_format_attachment(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const char *mime_type, const EMFormatHandler *handle) -{ - char *classid, *text, *html; - struct _attach_puri *info; - - classid = g_strdup_printf ("attachment%s", emf->part_id->str); - info = (struct _attach_puri *)em_format_add_puri ( - emf, sizeof (*info), classid, part, efhd_attachment_frame); - em_format_html_add_pobject ( - (EMFormatHTML *) emf, sizeof (EMFormatHTMLPObject), - classid, part, efhd_attachment_button); - info->handle = handle; - info->shown = em_format_is_inline ( - emf, info->puri.part_id, info->puri.part, handle); - info->snoop_mime_type = emf->snoop_mime_type; - info->attachment = e_attachment_new (); - e_attachment_set_mime_part (info->attachment, info->puri.part); - - if (emf->valid) { - info->sign = emf->valid->sign.status; - info->encrypt = emf->valid->encrypt.status; - } - - camel_stream_write_string ( - stream, EM_FORMAT_HTML_VPAD - "<table cellspacing=0 cellpadding=0><tr><td>" - "<table width=10 cellspacing=0 cellpadding=0>" - "<tr><td></td></tr></table></td>"); - - camel_stream_printf ( - stream, "<td><object classid=\"%s\"></object></td>", classid); - - camel_stream_write_string ( - stream, "<td><table width=3 cellspacing=0 cellpadding=0>" - "<tr><td></td></tr></table></td><td><font size=-1>"); - - /* output some info about it */ - /* FIXME: should we look up mime_type from object again? */ - text = em_format_describe_part (part, mime_type); - html = camel_text_to_html ( - text, ((EMFormatHTML *)emf)->text_html_flags & - CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0); - camel_stream_write_string (stream, html); - g_free (html); - g_free (text); - - camel_stream_write_string ( - stream, "</font></td></tr><tr></table>\n" - EM_FORMAT_HTML_VPAD); - - if (handle) { - if (info->shown) - handle->handler(emf, stream, part, handle); - } else if (efhd_use_component(mime_type)) { - g_free(classid); /* messy */ - - classid = g_strdup_printf("bonobo-unknown:///em-format-html-display/%s", emf->part_id->str); - em_format_html_add_pobject((EMFormatHTML *)emf, sizeof(EMFormatHTMLPObject), classid, part, efhd_bonobo_object); - camel_stream_printf(stream, "<object classid=\"%s\" type=\"%s\"></object><br>>\n", classid, mime_type); - } - - g_free(classid); -} - -static void efhd_optional_button_show (GtkWidget *widget, GtkWidget *w) { GtkWidget *label = g_object_get_data (G_OBJECT (widget), "text-label"); @@ -2225,50 +1437,3 @@ efhd_attachment_optional(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPOb return TRUE; } -static void -efhd_format_optional(EMFormat *emf, CamelStream *fstream, CamelMimePart *part, CamelStream *mstream) -{ - char *classid, *html; - struct _attach_puri *info; - CamelStream *stream; - - if (CAMEL_IS_STREAM_FILTER (fstream) && ((CamelStreamFilter *) fstream)->source) - stream = ((CamelStreamFilter *) fstream)->source; - else - stream = fstream; - - classid = g_strdup_printf("optional%s", emf->part_id->str); - info = (struct _attach_puri *)em_format_add_puri(emf, sizeof(*info), classid, part, efhd_attachment_frame); - em_format_html_add_pobject((EMFormatHTML *)emf, sizeof(EMFormatHTMLPObject), classid, part, efhd_attachment_optional); - info->handle = em_format_find_handler(emf, "text/plain"); - info->shown = FALSE; - info->snoop_mime_type = "text/plain"; - info->attachment = e_attachment_new (); - e_attachment_set_mime_part (info->attachment, info->puri.part); - info->mstream = (CamelStreamMem *)mstream; - if (emf->valid) { - info->sign = emf->valid->sign.status; - info->encrypt = emf->valid->encrypt.status; - } - - camel_stream_write_string(stream, - EM_FORMAT_HTML_VPAD - "<table cellspacing=0 cellpadding=0><tr><td><h3><font size=-1 color=red>"); - - html = camel_text_to_html(_("Evolution cannot render this email as it is too large to process. You can view it unformatted or with an external text editor."), ((EMFormatHTML *)emf)->text_html_flags & CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0); - camel_stream_write_string(stream, html); - camel_stream_write_string(stream, - "</font></h3></td></tr></table>\n"); - camel_stream_write_string(stream, - "<table cellspacing=0 cellpadding=0>" - "<tr>"); - camel_stream_printf(stream, "<td><object classid=\"%s\"></object></td></tr></table>", classid); - - g_free(html); - - camel_stream_write_string(stream, -/* "</font></h2></td></tr></table>\n" */ - EM_FORMAT_HTML_VPAD); - - g_free(classid); -} diff --git a/mail/em-format-html-display.h b/mail/em-format-html-display.h index 10a379d7f6..7554053e37 100644 --- a/mail/em-format-html-display.h +++ b/mail/em-format-html-display.h @@ -53,72 +53,20 @@ typedef struct _EMFormatHTMLDisplayClass EMFormatHTMLDisplayClass; typedef struct _EMFormatHTMLDisplayPrivate EMFormatHTMLDisplayPrivate; struct _EMFormatHTMLDisplay { - EMFormatHTML formathtml; - + EMFormatHTML parent; EMFormatHTMLDisplayPrivate *priv; struct _ESearchingTokenizer *search_tok; - - unsigned int animate:1; - unsigned int caret_mode:1; - unsigned int nobar:1; }; -#define EM_FORMAT_HTML_DISPLAY_SEARCH_PRIMARY (0) -#define EM_FORMAT_HTML_DISPLAY_SEARCH_SECONDARY (1) -#define EM_FORMAT_HTML_DISPLAY_SEARCH_ICASE (1<<8) - struct _EMFormatHTMLDisplayClass { - EMFormatHTMLClass formathtml_class; - - /* a link clicked normally */ - void (*link_clicked)(EMFormatHTMLDisplay *efhd, const char *uri); - /* a part or a link button pressed event */ - int (*popup_event)(EMFormatHTMLDisplay *efhd, GdkEventButton *event, const char *uri, struct _CamelMimePart *part); - /* the mouse is over a link */ - void (*on_url)(EMFormatHTMLDisplay *efhd, const char *uri); + EMFormatHTMLClass parent_class; }; GType em_format_html_display_get_type (void); EMFormatHTMLDisplay * em_format_html_display_new (void); -void em_format_html_display_goto_anchor - (EMFormatHTMLDisplay *efhd, - const char *name); - -void em_format_html_display_set_animate - (EMFormatHTMLDisplay *efhd, - gboolean state); -void em_format_html_display_set_caret_mode - (EMFormatHTMLDisplay *efhd, - gboolean state); - -void em_format_html_display_set_search - (EMFormatHTMLDisplay *efhd, - int type, - GSList *strings); -void em_format_html_display_search (EMFormatHTMLDisplay *efhd); -void em_format_html_display_search_with - (EMFormatHTMLDisplay *efhd, - char *word); -void em_format_html_display_search_close - (EMFormatHTMLDisplay *efhd); - -GtkWidget * em_format_html_get_search_dialog(EMFormatHTMLDisplay *efhd); - -void em_format_html_display_cut (EMFormatHTMLDisplay *efhd); -void em_format_html_display_copy (EMFormatHTMLDisplay *efhd); -void em_format_html_display_paste (EMFormatHTMLDisplay *efhd); - -void em_format_html_display_zoom_in (EMFormatHTMLDisplay *efhd); -void em_format_html_display_zoom_out (EMFormatHTMLDisplay *efhd); -void em_format_html_display_zoom_reset - (EMFormatHTMLDisplay *efhd); - -gboolean em_format_html_display_popup_menu - (EMFormatHTMLDisplay *efhd); - G_END_DECLS #endif /* EM_FORMAT_HTML_DISPLAY_H */ diff --git a/mail/em-format-html-print.c b/mail/em-format-html-print.c index 985828d2af..137711dbb7 100644 --- a/mail/em-format-html-print.c +++ b/mail/em-format-html-print.c @@ -38,22 +38,27 @@ static gpointer parent_class = NULL; static void -efhp_finalize (GObject *o) +efhp_finalize (GObject *object) { - EMFormatHTMLPrint *efhp = (EMFormatHTMLPrint *)o; + EMFormatHTMLPrint *efhp = (EMFormatHTMLPrint *)object; gtk_widget_destroy (efhp->window); if (efhp->source != NULL) g_object_unref (efhp->source); - ((GObjectClass *) parent_class)->finalize (o); + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); } static void -efhp_class_init (GObjectClass *class) +efhp_class_init (EMFormatHTMLPrintClass *class) { + GObjectClass *object_class; + parent_class = g_type_class_peek_parent (class); - class->finalize = efhp_finalize; + + object_class = G_OBJECT_CLASS (class); + object_class->finalize = efhp_finalize; } static void @@ -93,7 +98,7 @@ em_format_html_print_get_type (void) }; type = g_type_register_static ( - em_format_html_get_type (), "EMFormatHTMLPrint", + EM_TYPE_FORMAT_HTML, "EMFormatHTMLPrint", &type_info, 0); } @@ -101,7 +106,8 @@ em_format_html_print_get_type (void) } EMFormatHTMLPrint * -em_format_html_print_new (EMFormatHTML *source, GtkPrintOperationAction action) +em_format_html_print_new (EMFormatHTML *source, + GtkPrintOperationAction action) { EMFormatHTMLPrint *efhp; @@ -210,9 +216,7 @@ emfhp_got_message (CamelFolder *folder, const char *uid, return; } - if (efhp->source != NULL) - ((EMFormatHTML *)efhp)->load_http = - efhp->source->load_http_now; + em_format_html_load_images (EM_FORMAT_HTML (efhp)); g_signal_connect ( efhp, "complete", G_CALLBACK (emfhp_complete), efhp); diff --git a/mail/em-format-html.c b/mail/em-format-html.c index 23926f8ed6..fae1566876 100644 --- a/mail/em-format-html.c +++ b/mail/em-format-html.c @@ -48,7 +48,6 @@ #include "e-util/e-util.h" #include <gtkhtml/gtkhtml.h> -#include <gtkhtml/gtkhtml-embedded.h> #include <gtkhtml/gtkhtml-stream.h> #include <glib/gi18n.h> @@ -74,7 +73,6 @@ #include <libedataserver/e-msgport.h> -#include "mail-component.h" #include "mail-config.h" #include "mail-mt.h" @@ -84,6 +82,10 @@ #define d(x) +#define EM_FORMAT_HTML_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), EM_TYPE_FORMAT_HTML, EMFormatHTMLPrivate)) + #define EFM_MESSAGE_START_ANAME "evolution#message#start" #define EFH_MESSAGE_START "<A name=\"" EFM_MESSAGE_START_ANAME "\"></A>" @@ -104,6 +106,27 @@ struct _EMFormatHTMLPrivate { EDList pending_jobs; GMutex *lock; + + GdkColor colors[EM_FORMAT_HTML_NUM_COLOR_TYPES]; + MailConfigHTTPMode image_loading_policy; + + guint load_images_now : 1; + guint only_local_photos : 1; + guint show_sender_photo : 1; +}; + +enum { + PROP_0, + PROP_BODY_COLOR, + PROP_CITATION_COLOR, + PROP_CONTENT_COLOR, + PROP_FRAME_COLOR, + PROP_HEADER_COLOR, + PROP_IMAGE_LOADING_POLICY, + PROP_MARK_CITATIONS, + PROP_ONLY_LOCAL_PHOTOS, + PROP_SHOW_SENDER_PHOTO, + PROP_TEXT_COLOR }; static void efh_url_requested(GtkHTML *html, const char *url, GtkHTMLStream *handle, EMFormatHTML *efh); @@ -112,67 +135,243 @@ static void efh_gtkhtml_destroy(GtkHTML *html, EMFormatHTML *efh); static void efh_format_message(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info); -static void efh_format_clone(EMFormat *emf, CamelFolder *folder, const char *uid, CamelMimeMessage *msg, EMFormat *emfsource); -static void efh_format_error(EMFormat *emf, CamelStream *stream, const char *txt); -static void efh_format_source(EMFormat *, CamelStream *, CamelMimePart *); -static void efh_format_attachment(EMFormat *, CamelStream *, CamelMimePart *, const char *, const EMFormatHandler *); static void efh_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, CamelCipherValidity *valid); -static gboolean efh_busy(EMFormat *); static void efh_builtin_init(EMFormatHTMLClass *efhc); static void efh_write_image(EMFormat *emf, CamelStream *stream, EMFormatPURI *puri); -static EMFormatClass *efh_parent; +static gpointer parent_class; static CamelDataCache *emfh_http_cache; #define EMFH_HTTP_CACHE_PATH "http" +/* Sigh, this is so we have a cancellable, async rendering thread */ +struct _format_msg { + MailMsg base; + + EMFormatHTML *format; + EMFormat *format_source; + EMHTMLStream *estream; + CamelFolder *folder; + char *uid; + CamelMimeMessage *message; +}; + +static gchar * +efh_format_desc (struct _format_msg *m) +{ + return g_strdup(_("Formatting message")); +} + static void -efh_free_cache(struct _EMFormatHTMLCache *efhc) +efh_format_exec (struct _format_msg *m) { - if (efhc->textmp) - camel_object_unref(efhc->textmp); - g_free(efhc); + struct _EMFormatHTMLJob *job; + struct _EMFormatPURITree *puri_level; + int cancelled = FALSE; + CamelURL *base; + + if (m->format->html == NULL) + return; + + camel_stream_printf ( + (CamelStream *)m->estream, + "<!doctype html public \"-//W3C//DTD HTML 4.0 TRANSITIONAL//EN\">\n<html>\n" + "<head>\n<meta name=\"generator\" content=\"Evolution Mail Component\">\n</head>\n" + "<body bgcolor =\"#%06x\" text=\"#%06x\" marginwidth=6 marginheight=6>\n", + e_color_to_value ( + &m->format->priv->colors[ + EM_FORMAT_HTML_COLOR_BODY]), + e_color_to_value ( + &m->format->priv->colors[ + EM_FORMAT_HTML_COLOR_HEADER])); + + /* <insert top-header stuff here> */ + + if (((EMFormat *)m->format)->mode == EM_FORMAT_SOURCE) { + em_format_format_source((EMFormat *)m->format, (CamelStream *)m->estream, (CamelMimePart *)m->message); + } else { + const EMFormatHandler *handle; + + handle = em_format_find_handler((EMFormat *)m->format, "x-evolution/message/prefix"); + if (handle) + handle->handler((EMFormat *)m->format, (CamelStream *)m->estream, (CamelMimePart *)m->message, handle); + handle = em_format_find_handler((EMFormat *)m->format, "x-evolution/message/rfc822"); + if (handle) + handle->handler((EMFormat *)m->format, (CamelStream *)m->estream, (CamelMimePart *)m->message, handle); + } + + camel_stream_flush((CamelStream *)m->estream); + + puri_level = ((EMFormat *)m->format)->pending_uri_level; + base = ((EMFormat *)m->format)->base; + + do { + /* now dispatch any added tasks ... */ + g_mutex_lock(m->format->priv->lock); + while ((job = (struct _EMFormatHTMLJob *)e_dlist_remhead(&m->format->priv->pending_jobs))) { + g_mutex_unlock(m->format->priv->lock); + + /* This is an implicit check to see if the gtkhtml has been destroyed */ + if (!cancelled) + cancelled = m->format->html == NULL; + + /* Now do an explicit check for user cancellation */ + if (!cancelled) + cancelled = camel_operation_cancel_check(NULL); + + /* call jobs even if cancelled, so they can clean up resources */ + ((EMFormat *)m->format)->pending_uri_level = job->puri_level; + if (job->base) + ((EMFormat *)m->format)->base = job->base; + job->callback(job, cancelled); + ((EMFormat *)m->format)->base = base; + + /* clean up the job */ + camel_object_unref(job->stream); + if (job->base) + camel_url_free(job->base); + g_free(job); + + g_mutex_lock(m->format->priv->lock); + } + g_mutex_unlock(m->format->priv->lock); + + if (m->estream) { + /* Closing this base stream can queue more jobs, so we need + to check the list again after we've finished */ + d(printf("out of jobs, closing root stream\n")); + camel_stream_write_string((CamelStream *)m->estream, "</body>\n</html>\n"); + camel_stream_close((CamelStream *)m->estream); + camel_object_unref(m->estream); + m->estream = NULL; + } + + /* e_dlist_empty is atomic and doesn't need locking */ + } while (!e_dlist_empty(&m->format->priv->pending_jobs)); + + d(printf("out of jobs, done\n")); + + ((EMFormat *)m->format)->pending_uri_level = puri_level; } static void -efh_init(GObject *o) +efh_format_done (struct _format_msg *m) { - EMFormatHTML *efh = (EMFormatHTML *)o; + d(printf("formatting finished\n")); - efh->priv = g_malloc0(sizeof(*efh->priv)); + m->format->priv->format_id = -1; + m->format->priv->load_images_now = FALSE; + m->format->state = EM_FORMAT_HTML_STATE_NONE; + g_signal_emit_by_name(m->format, "complete"); +} - e_dlist_init(&efh->pending_object_list); - e_dlist_init(&efh->priv->pending_jobs); - efh->priv->lock = g_mutex_new(); - efh->priv->format_id = -1; - efh->priv->text_inline_parts = g_hash_table_new_full ( - g_str_hash, g_str_equal, - (GDestroyNotify) NULL, - (GDestroyNotify) efh_free_cache); +static void +efh_format_free (struct _format_msg *m) +{ + d(printf("formatter freed\n")); + g_object_unref(m->format); + if (m->estream) { + camel_stream_close((CamelStream *)m->estream); + camel_object_unref(m->estream); + } + if (m->folder) + camel_object_unref(m->folder); + g_free(m->uid); + if (m->message) + camel_object_unref(m->message); + if (m->format_source) + g_object_unref(m->format_source); +} - efh->html = (GtkHTML *)gtk_html_new(); - gtk_html_set_blocking(efh->html, FALSE); - gtk_html_set_caret_first_focus_anchor (efh->html, EFM_MESSAGE_START_ANAME); - g_object_ref_sink(efh->html); - - gtk_html_set_default_content_type(efh->html, "text/html; charset=utf-8"); - gtk_html_set_editable(efh->html, FALSE); - - g_signal_connect(efh->html, "destroy", G_CALLBACK(efh_gtkhtml_destroy), efh); - g_signal_connect(efh->html, "url_requested", G_CALLBACK(efh_url_requested), efh); - g_signal_connect(efh->html, "object_requested", G_CALLBACK(efh_object_requested), efh); - - efh->body_colour = 0xeeeeee; - efh->header_colour = 0xeeeeee; - efh->text_colour = 0; - efh->frame_colour = 0x3f3f3f; - efh->content_colour = 0xffffff; - efh->text_html_flags = CAMEL_MIME_FILTER_TOHTML_CONVERT_NL | CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES - | CAMEL_MIME_FILTER_TOHTML_MARK_CITATION; - efh->show_icon = TRUE; - efh->state = EM_FORMAT_HTML_STATE_NONE; +static MailMsgInfo efh_format_info = { + sizeof (struct _format_msg), + (MailMsgDescFunc) efh_format_desc, + (MailMsgExecFunc) efh_format_exec, + (MailMsgDoneFunc) efh_format_done, + (MailMsgFreeFunc) efh_format_free +}; + +static gboolean +efh_format_timeout(struct _format_msg *m) +{ + GtkHTMLStream *hstream; + EMFormatHTML *efh = m->format; + struct _EMFormatHTMLPrivate *p = efh->priv; + + if (m->format->html == NULL) { + mail_msg_unref(m); + return FALSE; + } + + d(printf("timeout called ...\n")); + if (p->format_id != -1) { + d(printf(" still waiting for cancellation to take effect, waiting ...\n")); + return TRUE; + } + + g_return_val_if_fail (e_dlist_empty(&p->pending_jobs), FALSE); + + d(printf(" ready to go, firing off format thread\n")); + + /* call super-class to kick it off */ + EM_FORMAT_CLASS (parent_class)->format_clone ( + EM_FORMAT (efh), m->folder, m->uid, + m->message, m->format_source); + em_format_html_clear_pobject(m->format); + + /* FIXME: method off EMFormat? */ + if (((EMFormat *)efh)->valid) { + camel_cipher_validity_free(((EMFormat *)efh)->valid); + ((EMFormat *)efh)->valid = NULL; + ((EMFormat *)efh)->valid_parent = NULL; + } + + if (m->message == NULL) { + hstream = gtk_html_begin(efh->html); + gtk_html_stream_close(hstream, GTK_HTML_STREAM_OK); + mail_msg_unref(m); + p->last_part = NULL; + } else { + efh->state = EM_FORMAT_HTML_STATE_RENDERING; + + if (p->last_part != m->message) { + hstream = gtk_html_begin (efh->html); + gtk_html_stream_printf (hstream, "<h5>%s</h5>", _("Formatting Message...")); + gtk_html_stream_close (hstream, GTK_HTML_STREAM_OK); + } + + hstream = NULL; + m->estream = (EMHTMLStream *)em_html_stream_new(efh->html, hstream); + + if (p->last_part == m->message) { + em_html_stream_set_flags (m->estream, + GTK_HTML_BEGIN_KEEP_SCROLL | GTK_HTML_BEGIN_KEEP_IMAGES + | GTK_HTML_BEGIN_BLOCK_UPDATES | GTK_HTML_BEGIN_BLOCK_IMAGES); + } else { + /* clear cache of inline-scanned text parts */ + g_hash_table_remove_all(p->text_inline_parts); + + p->last_part = m->message; + } + + efh->priv->format_id = m->base.seq; + mail_msg_unordered_push (m); + } + + efh->priv->format_timeout_id = 0; + efh->priv->format_timeout_msg = NULL; + + return FALSE; +} + +static void +efh_free_cache(struct _EMFormatHTMLCache *efhc) +{ + if (efhc->textmp) + camel_object_unref(efhc->textmp); + g_free(efhc); } static void @@ -189,8 +388,8 @@ efh_gtkhtml_destroy(GtkHTML *html, EMFormatHTML *efh) if (efh->priv->format_id != -1) mail_msg_cancel(efh->priv->format_id); - if (efh->html) { - g_object_unref(efh->html); + if (efh->html != NULL) { + g_object_unref (efh->html); efh->html = NULL; } } @@ -207,124 +406,722 @@ efh_insert_cache(EMFormatHTML *efh, const char *partid) return efhc; } +static void +efh_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_BODY_COLOR: + em_format_html_set_color ( + EM_FORMAT_HTML (object), + EM_FORMAT_HTML_COLOR_BODY, + g_value_get_boxed (value)); + return; + + case PROP_CITATION_COLOR: + em_format_html_set_color ( + EM_FORMAT_HTML (object), + EM_FORMAT_HTML_COLOR_CITATION, + g_value_get_boxed (value)); + return; + + case PROP_CONTENT_COLOR: + em_format_html_set_color ( + EM_FORMAT_HTML (object), + EM_FORMAT_HTML_COLOR_CONTENT, + g_value_get_boxed (value)); + return; + + case PROP_FRAME_COLOR: + em_format_html_set_color ( + EM_FORMAT_HTML (object), + EM_FORMAT_HTML_COLOR_FRAME, + g_value_get_boxed (value)); + return; + + case PROP_HEADER_COLOR: + em_format_html_set_color ( + EM_FORMAT_HTML (object), + EM_FORMAT_HTML_COLOR_HEADER, + g_value_get_boxed (value)); + return; + + case PROP_IMAGE_LOADING_POLICY: + em_format_html_set_image_loading_policy ( + EM_FORMAT_HTML (object), + g_value_get_int (value)); + return; + + case PROP_MARK_CITATIONS: + em_format_html_set_mark_citations ( + EM_FORMAT_HTML (object), + g_value_get_boolean (value)); + return; + + case PROP_ONLY_LOCAL_PHOTOS: + em_format_html_set_only_local_photos ( + EM_FORMAT_HTML (object), + g_value_get_boolean (value)); + return; + + case PROP_SHOW_SENDER_PHOTO: + em_format_html_set_show_sender_photo ( + EM_FORMAT_HTML (object), + g_value_get_boolean (value)); + return; + + case PROP_TEXT_COLOR: + em_format_html_set_color ( + EM_FORMAT_HTML (object), + EM_FORMAT_HTML_COLOR_TEXT, + g_value_get_boxed (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} static void -efh_finalise(GObject *o) +efh_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { - EMFormatHTML *efh = (EMFormatHTML *)o; + GdkColor color; + + switch (property_id) { + case PROP_BODY_COLOR: + em_format_html_get_color ( + EM_FORMAT_HTML (object), + EM_FORMAT_HTML_COLOR_BODY, + &color); + g_value_set_boxed (value, &color); + return; + + case PROP_CITATION_COLOR: + em_format_html_get_color ( + EM_FORMAT_HTML (object), + EM_FORMAT_HTML_COLOR_CITATION, + &color); + g_value_set_boxed (value, &color); + return; + + case PROP_CONTENT_COLOR: + em_format_html_get_color ( + EM_FORMAT_HTML (object), + EM_FORMAT_HTML_COLOR_CONTENT, + &color); + g_value_set_boxed (value, &color); + return; + + case PROP_FRAME_COLOR: + em_format_html_get_color ( + EM_FORMAT_HTML (object), + EM_FORMAT_HTML_COLOR_FRAME, + &color); + g_value_set_boxed (value, &color); + return; + + case PROP_HEADER_COLOR: + em_format_html_get_color ( + EM_FORMAT_HTML (object), + EM_FORMAT_HTML_COLOR_HEADER, + &color); + g_value_set_boxed (value, &color); + return; + + case PROP_IMAGE_LOADING_POLICY: + g_value_set_int ( + value, + em_format_html_get_image_loading_policy ( + EM_FORMAT_HTML (object))); + return; + + case PROP_MARK_CITATIONS: + g_value_set_boolean ( + value, em_format_html_get_mark_citations ( + EM_FORMAT_HTML (object))); + return; + + case PROP_ONLY_LOCAL_PHOTOS: + g_value_set_boolean ( + value, em_format_html_get_only_local_photos ( + EM_FORMAT_HTML (object))); + return; + + case PROP_SHOW_SENDER_PHOTO: + g_value_set_boolean ( + value, em_format_html_get_show_sender_photo ( + EM_FORMAT_HTML (object))); + return; + + case PROP_TEXT_COLOR: + em_format_html_get_color ( + EM_FORMAT_HTML (object), + EM_FORMAT_HTML_COLOR_TEXT, + &color); + g_value_set_boxed (value, &color); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +efh_finalize (GObject *object) +{ + EMFormatHTML *efh = EM_FORMAT_HTML (object); /* FIXME: check for leaked stuff */ - em_format_html_clear_pobject(efh); + em_format_html_clear_pobject (efh); + efh_gtkhtml_destroy (efh->html, efh); + + g_hash_table_destroy (efh->priv->text_inline_parts); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +efh_format_clone (EMFormat *emf, + CamelFolder *folder, + const gchar *uid, + CamelMimeMessage *msg, + EMFormat *emfsource) +{ + EMFormatHTML *efh = EM_FORMAT_HTML (emf); + struct _format_msg *m; + + /* How to sub-class ? Might need to adjust api ... */ + + if (efh->html == NULL) + return; + + d(printf("efh_format called\n")); + if (efh->priv->format_timeout_id != 0) { + d(printf(" timeout for last still active, removing ...\n")); + g_source_remove(efh->priv->format_timeout_id); + efh->priv->format_timeout_id = 0; + mail_msg_unref(efh->priv->format_timeout_msg); + efh->priv->format_timeout_msg = NULL; + } + + if (emfsource != NULL) + g_object_ref (emfsource); + + if (folder != NULL) + camel_object_ref (folder); + + if (msg != NULL) + camel_object_ref (msg); + + m = mail_msg_new (&efh_format_info); + m->format = g_object_ref (emf); + m->format_source = emfsource; + m->folder = folder; + m->uid = g_strdup (uid); + m->message = msg; + + if (efh->priv->format_id == -1) { + d(printf(" idle, forcing format\n")); + efh_format_timeout (m); + } else { + d(printf(" still busy, cancelling and queuing wait\n")); + /* cancel and poll for completion */ + mail_msg_cancel (efh->priv->format_id); + efh->priv->format_timeout_msg = m; + efh->priv->format_timeout_id = g_timeout_add ( + 100, (GSourceFunc) efh_format_timeout, m); + } +} + +static void +efh_format_error (EMFormat *emf, + CamelStream *stream, + const gchar *txt) +{ + gchar *html; + + html = camel_text_to_html ( + txt, CAMEL_MIME_FILTER_TOHTML_CONVERT_NL | + CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0); + camel_stream_printf ( + stream, "<em><font color=\"red\">%s</font></em><br>", html); + g_free (html); +} + +static void +efh_format_source (EMFormat *emf, + CamelStream *stream, + CamelMimePart *part) +{ + CamelStreamFilter *filtered_stream; + CamelMimeFilter *filter; + CamelDataWrapper *dw = (CamelDataWrapper *) part; + + filtered_stream = camel_stream_filter_new_with_stream (stream); + + filter = camel_mime_filter_tohtml_new ( + CAMEL_MIME_FILTER_TOHTML_CONVERT_NL | + CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES | + CAMEL_MIME_FILTER_TOHTML_PRESERVE_8BIT, 0); + camel_stream_filter_add (filtered_stream, filter); + camel_object_unref (filter); + + camel_stream_write_string (stream, "<table><tr><td><tt>"); + em_format_format_text (emf, (CamelStream *) filtered_stream, dw); + camel_object_unref (filtered_stream); + + camel_stream_write_string(stream, "</tt></td></tr></table>"); +} + +static void +efh_format_attachment (EMFormat *emf, + CamelStream *stream, + CamelMimePart *part, + const gchar *mime_type, + const EMFormatHandler *handle) +{ + char *text, *html; - efh_gtkhtml_destroy(efh->html, efh); + /* we display all inlined attachments only */ - g_hash_table_destroy(efh->priv->text_inline_parts); + /* this could probably be cleaned up ... */ + camel_stream_write_string ( + stream, + "<table border=1 cellspacing=0 cellpadding=0><tr><td>" + "<table width=10 cellspacing=0 cellpadding=0>" + "<tr><td></td></tr></table></td>" + "<td><table width=3 cellspacing=0 cellpadding=0>" + "<tr><td></td></tr></table></td><td><font size=-1>\n"); - g_free(efh->priv); + /* output some info about it */ + text = em_format_describe_part(part, mime_type); + html = camel_text_to_html ( + text, ((EMFormatHTML *)emf)->text_html_flags & + CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0); + camel_stream_write_string (stream, html); + g_free (html); + g_free (text); - ((GObjectClass *)efh_parent)->finalize(o); + camel_stream_write_string (stream, "</font></td></tr><tr></table>"); + + if (handle && em_format_is_inline (emf, emf->part_id->str, part, handle)) + handle->handler (emf, stream, part, handle); } +static gboolean +efh_busy (EMFormat *emf) +{ + EMFormatHTMLPrivate *priv; + + priv = EM_FORMAT_HTML_GET_PRIVATE (emf); + + return (priv->format_id != -1); +} static void -efh_base_init(EMFormatHTMLClass *efhklass) +efh_base_init (EMFormatHTMLClass *class) { - efh_builtin_init(efhklass); + efh_builtin_init (class); } static void -efh_class_init(GObjectClass *klass) +efh_class_init (EMFormatHTMLClass *class) { - ((EMFormatClass *)klass)->format_clone = efh_format_clone; - ((EMFormatClass *)klass)->format_error = efh_format_error; - ((EMFormatClass *)klass)->format_source = efh_format_source; - ((EMFormatClass *)klass)->format_attachment = efh_format_attachment; - ((EMFormatClass *)klass)->format_secure = efh_format_secure; - ((EMFormatClass *)klass)->busy = efh_busy; - - klass->finalize = efh_finalise; + GObjectClass *object_class; + EMFormatClass *format_class; + gchar *pathname; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMFormatHTMLPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = efh_set_property; + object_class->get_property = efh_get_property; + object_class->finalize = efh_finalize; + + format_class = EM_FORMAT_CLASS (class); + format_class->format_clone = efh_format_clone; + format_class->format_error = efh_format_error; + format_class->format_source = efh_format_source; + format_class->format_attachment = efh_format_attachment; + format_class->format_secure = efh_format_secure; + format_class->busy = efh_busy; + + class->html_widget_type = GTK_TYPE_HTML; + + g_object_class_install_property ( + object_class, + PROP_BODY_COLOR, + g_param_spec_boxed ( + "body-color", + "Body Color", + NULL, + GDK_TYPE_COLOR, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_CITATION_COLOR, + g_param_spec_boxed ( + "citation-color", + "Citation Color", + NULL, + GDK_TYPE_COLOR, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_CONTENT_COLOR, + g_param_spec_boxed ( + "content-color", + "Content Color", + NULL, + GDK_TYPE_COLOR, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_FRAME_COLOR, + g_param_spec_boxed ( + "frame-color", + "Frame Color", + NULL, + GDK_TYPE_COLOR, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_HEADER_COLOR, + g_param_spec_boxed ( + "header-color", + "Header Color", + NULL, + GDK_TYPE_COLOR, + G_PARAM_READWRITE)); + + /* FIXME Make this a proper enum property. */ + g_object_class_install_property ( + object_class, + PROP_IMAGE_LOADING_POLICY, + g_param_spec_int ( + "image-loading-policy", + "Image Loading Policy", + NULL, + 0, + G_MAXINT, + MAIL_CONFIG_HTTP_ALWAYS, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_MARK_CITATIONS, + g_param_spec_boolean ( + "mark-citations", + "Mark Citations", + NULL, + TRUE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_ONLY_LOCAL_PHOTOS, + g_param_spec_boolean ( + "only-local-photos", + "Only Local Photos", + NULL, + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_SHOW_SENDER_PHOTO, + g_param_spec_boolean ( + "show-sender-photo", + "Show Sender Photo", + NULL, + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_TEXT_COLOR, + g_param_spec_boxed ( + "text-color", + "Text Color", + NULL, + GDK_TYPE_COLOR, + G_PARAM_READWRITE)); + + /* cache expiry - 2 hour access, 1 day max */ + pathname = g_build_filename ( + e_get_user_data_dir (), "cache", NULL); + emfh_http_cache = camel_data_cache_new (pathname, 0, NULL); + if (emfh_http_cache) { + camel_data_cache_set_expire_age(emfh_http_cache, 24*60*60); + camel_data_cache_set_expire_access(emfh_http_cache, 2*60*60); + } + g_free (pathname); +} + +static void +efh_init (EMFormatHTML *efh, + EMFormatHTMLClass *class) +{ + GtkHTML *html; + GdkColor *color; + + efh->priv = EM_FORMAT_HTML_GET_PRIVATE (efh); + + e_dlist_init(&efh->pending_object_list); + e_dlist_init(&efh->priv->pending_jobs); + efh->priv->lock = g_mutex_new(); + efh->priv->format_id = -1; + efh->priv->text_inline_parts = g_hash_table_new_full ( + g_str_hash, g_str_equal, + (GDestroyNotify) NULL, + (GDestroyNotify) efh_free_cache); + + html = g_object_new (class->html_widget_type, NULL); + efh->html = g_object_ref_sink (html); + + gtk_html_set_blocking (html, FALSE); + gtk_html_set_caret_first_focus_anchor (html, EFM_MESSAGE_START_ANAME); + gtk_html_set_default_content_type (html, "text/html; charset=utf-8"); + gtk_html_set_editable (html, FALSE); + + g_signal_connect ( + html, "url-requested", + G_CALLBACK (efh_url_requested), efh); + g_signal_connect ( + html, "object-requested", + G_CALLBACK (efh_object_requested), efh); + + color = &efh->priv->colors[EM_FORMAT_HTML_COLOR_BODY]; + gdk_color_parse ("#eeeeee", color); + + color = &efh->priv->colors[EM_FORMAT_HTML_COLOR_CONTENT]; + gdk_color_parse ("#ffffff", color); + + color = &efh->priv->colors[EM_FORMAT_HTML_COLOR_FRAME]; + gdk_color_parse ("#3f3f3f", color); + + color = &efh->priv->colors[EM_FORMAT_HTML_COLOR_HEADER]; + gdk_color_parse ("#eeeeee", color); + + color = &efh->priv->colors[EM_FORMAT_HTML_COLOR_TEXT]; + gdk_color_parse ("#000000", color); + + efh->text_html_flags = + CAMEL_MIME_FILTER_TOHTML_CONVERT_NL | + CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES | + CAMEL_MIME_FILTER_TOHTML_MARK_CITATION; + efh->show_icon = TRUE; + efh->state = EM_FORMAT_HTML_STATE_NONE; + + g_signal_connect_swapped ( + efh, "notify::mark-citations", + G_CALLBACK (em_format_redraw), NULL); } GType -em_format_html_get_type(void) +em_format_html_get_type (void) { static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof(EMFormatHTMLClass), - (GBaseInitFunc)efh_base_init, NULL, - (GClassInitFunc)efh_class_init, - NULL, NULL, - sizeof(EMFormatHTML), 0, - (GInstanceInitFunc)efh_init + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMFormatHTMLClass), + (GBaseInitFunc) efh_base_init, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) efh_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMFormatHTML), + 0, /* n_preallocs */ + (GInstanceInitFunc) efh_init, + NULL /* value_table */ }; - const char *base_directory = e_get_user_data_dir (); - char *path; - - /* Trigger creation of mail component. */ - mail_component_peek (); - - efh_parent = g_type_class_ref(em_format_get_type()); - type = g_type_register_static(em_format_get_type(), "EMFormatHTML", &info, 0); - /* cache expiry - 2 hour access, 1 day max */ - path = alloca(strlen(base_directory)+16); - sprintf(path, "%s/cache", base_directory); - emfh_http_cache = camel_data_cache_new(path, 0, NULL); - if (emfh_http_cache) { - camel_data_cache_set_expire_age(emfh_http_cache, 24*60*60); - camel_data_cache_set_expire_access(emfh_http_cache, 2*60*60); - } + type = g_type_register_static ( + em_format_get_type(), "EMFormatHTML", + &type_info, G_TYPE_FLAG_ABSTRACT); } return type; } -EMFormatHTML *em_format_html_new(void) +void +em_format_html_load_images (EMFormatHTML *efh) { - EMFormatHTML *efh; + g_return_if_fail (EM_IS_FORMAT_HTML (efh)); - efh = g_object_new(em_format_html_get_type(), NULL); + if (efh->priv->image_loading_policy == MAIL_CONFIG_HTTP_ALWAYS) + return; - return efh; + /* This will remain set while we're still + * rendering the same message, then it wont be. */ + efh->priv->load_images_now = TRUE; + em_format_redraw (EM_FORMAT (efh)); } -/* force loading of http images */ -void em_format_html_load_http(EMFormatHTML *emfh) +void +em_format_html_get_color (EMFormatHTML *efh, + EMFormatHTMLColorType type, + GdkColor *color) { - if (emfh->load_http == MAIL_CONFIG_HTTP_ALWAYS) - return; + GdkColor *format_color; + + g_return_if_fail (EM_IS_FORMAT_HTML (efh)); + g_return_if_fail (type >= 0); + g_return_if_fail (type < EM_FORMAT_HTML_NUM_COLOR_TYPES); + g_return_if_fail (color != NULL); - /* This will remain set while we're still rendering the same message, then it wont be */ - emfh->load_http_now = TRUE; - d(printf("redrawing with images forced on\n")); - em_format_redraw((EMFormat *)emfh); + format_color = &efh->priv->colors[type]; + + color->red = format_color->red; + color->green = format_color->green; + color->blue = format_color->blue; } void -em_format_html_set_load_http(EMFormatHTML *emfh, int style) +em_format_html_set_color (EMFormatHTML *efh, + EMFormatHTMLColorType type, + const GdkColor *color) { - if (emfh->load_http != style) { - emfh->load_http = style; - em_format_redraw((EMFormat *)emfh); + GdkColor *format_color; + const gchar *property_name; + + g_return_if_fail (EM_IS_FORMAT_HTML (efh)); + g_return_if_fail (type >= 0); + g_return_if_fail (type < EM_FORMAT_HTML_NUM_COLOR_TYPES); + g_return_if_fail (color != NULL); + + format_color = &efh->priv->colors[type]; + + if (gdk_color_equal (color, format_color)) + return; + + format_color->red = color->red; + format_color->green = color->green; + format_color->blue = color->blue; + + switch (type) { + case EM_FORMAT_HTML_COLOR_BODY: + property_name = "body-color"; + break; + case EM_FORMAT_HTML_COLOR_CITATION: + property_name = "citation-color"; + break; + case EM_FORMAT_HTML_COLOR_CONTENT: + property_name = "content-color"; + break; + case EM_FORMAT_HTML_COLOR_FRAME: + property_name = "frame-color"; + break; + case EM_FORMAT_HTML_COLOR_HEADER: + property_name = "header-color"; + break; + case EM_FORMAT_HTML_COLOR_TEXT: + property_name = "text-color"; + break; + default: + g_return_if_reached (); } + + g_object_notify (G_OBJECT (efh), property_name); +} + +MailConfigHTTPMode +em_format_html_get_image_loading_policy (EMFormatHTML *efh) +{ + g_return_val_if_fail (EM_IS_FORMAT_HTML (efh), 0); + + return efh->priv->image_loading_policy; } void -em_format_html_set_mark_citations(EMFormatHTML *emfh, int state, guint32 citation_colour) +em_format_html_set_image_loading_policy (EMFormatHTML *efh, + MailConfigHTTPMode policy) { - if (emfh->mark_citations ^ state || emfh->citation_colour != citation_colour) { - emfh->mark_citations = state; - emfh->citation_colour = citation_colour; + g_return_if_fail (EM_IS_FORMAT_HTML (efh)); - if (state) - emfh->text_html_flags |= CAMEL_MIME_FILTER_TOHTML_MARK_CITATION; - else - emfh->text_html_flags &= ~CAMEL_MIME_FILTER_TOHTML_MARK_CITATION; + if (policy == efh->priv->image_loading_policy) + return; - em_format_redraw((EMFormat *)emfh); - } + efh->priv->image_loading_policy = policy; + + g_object_notify (G_OBJECT (efh), "image-loading-policy"); +} + +gboolean +em_format_html_get_mark_citations (EMFormatHTML *efh) +{ + guint32 flags; + + g_return_val_if_fail (EM_IS_FORMAT_HTML (efh), FALSE); + + flags = efh->text_html_flags; + + return ((flags & CAMEL_MIME_FILTER_TOHTML_MARK_CITATION) != 0); +} + +void +em_format_html_set_mark_citations (EMFormatHTML *efh, + gboolean mark_citations) +{ + g_return_if_fail (EM_IS_FORMAT_HTML (efh)); + + if (mark_citations) + efh->text_html_flags |= + CAMEL_MIME_FILTER_TOHTML_MARK_CITATION; + efh->text_html_flags &= + ~CAMEL_MIME_FILTER_TOHTML_MARK_CITATION; + + g_object_notify (G_OBJECT (efh), "mark-citations"); +} + +gboolean +em_format_html_get_only_local_photos (EMFormatHTML *efh) +{ + g_return_val_if_fail (EM_IS_FORMAT_HTML (efh), FALSE); + + return efh->priv->only_local_photos; +} + +void +em_format_html_set_only_local_photos (EMFormatHTML *efh, + gboolean only_local_photos) +{ + g_return_if_fail (EM_IS_FORMAT_HTML (efh)); + + efh->priv->only_local_photos = only_local_photos; + + g_object_notify (G_OBJECT (efh), "only-local-photos"); +} + +gboolean +em_format_html_get_show_sender_photo (EMFormatHTML *efh) +{ + g_return_val_if_fail (EM_IS_FORMAT_HTML (efh), FALSE); + + return efh->priv->show_sender_photo; +} + +void +em_format_html_set_show_sender_photo (EMFormatHTML *efh, + gboolean show_sender_photo) +{ + g_return_if_fail (EM_IS_FORMAT_HTML (efh)); + + efh->priv->show_sender_photo = show_sender_photo; + + g_object_notify (G_OBJECT (efh), "show-sender-photo"); } CamelMimePart * @@ -482,13 +1279,15 @@ static void emfh_gethttp(struct _EMFormatHTMLJob *job, int cancelled) instream = cistream = camel_data_cache_get(emfh_http_cache, EMFH_HTTP_CACHE_PATH, job->u.uri, NULL); if (instream == NULL) { + MailConfigHTTPMode policy; char *proxy; + policy = em_format_html_get_image_loading_policy (job->format); - if (!(job->format->load_http_now - || job->format->load_http == MAIL_CONFIG_HTTP_ALWAYS - || (job->format->load_http == MAIL_CONFIG_HTTP_SOMETIMES - && em_utils_in_addressbook((CamelInternetAddress *)camel_mime_message_get_from(job->format->format.message), FALSE)))) { + if (!(job->format->priv->load_images_now + || policy == MAIL_CONFIG_HTTP_ALWAYS + || (policy == MAIL_CONFIG_HTTP_SOMETIMES + && em_utils_in_addressbook((CamelInternetAddress *)camel_mime_message_get_from(job->format->parent.message), FALSE)))) { /* TODO: Ideally we would put the http requests into another queue and only send them out if the user selects 'load images', when they do. The problem is how to maintain this state with multiple renderings, and how to adjust the thread dispatch/setup routine to handle it */ @@ -677,7 +1476,11 @@ static const char *smime_sign_colour[4] = { static void efh_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, CamelCipherValidity *valid) { - efh_parent->format_secure(emf, stream, part, valid); + EMFormatClass *format_class; + + format_class = EM_FORMAT_GET_CLASS (emf); + g_return_if_fail (format_class->format_secure != NULL); + format_class->format_secure (emf, stream, part, valid); /* To explain, if the validity is the same, then we are the base validity and now have a combined sign/encrypt validity @@ -731,6 +1534,7 @@ efh_text_plain(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFo CamelContentType *type; const char *format; guint32 flags; + guint32 rgb; int i, count, len; struct _EMFormatHTMLCache *efhc; @@ -787,8 +1591,10 @@ efh_text_plain(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFo camel_content_type_unref(ct); } + rgb = e_color_to_value ( + &efh->priv->colors[EM_FORMAT_HTML_COLOR_CITATION]); filtered_stream = camel_stream_filter_new_with_stream(stream); - html_filter = camel_mime_filter_tohtml_new(flags, efh->citation_colour); + html_filter = camel_mime_filter_tohtml_new(flags, rgb); camel_stream_filter_add(filtered_stream, html_filter); camel_object_unref(html_filter); @@ -804,9 +1610,17 @@ efh_text_plain(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFo type = camel_mime_part_get_content_type(newpart); if (camel_content_type_is (type, "text", "*") && !camel_content_type_is(type, "text", "calendar")) { - camel_stream_printf (stream, - "<div style=\"border: solid #%06x 1px; background-color: #%06x; padding: 10px; color: #%06x;\">\n", - efh->frame_colour & 0xffffff, efh->content_colour & 0xffffff, efh->text_colour & 0xffffff); + camel_stream_printf ( + stream, "<div style=\"border: solid #%06x 1px; background-color: #%06x; padding: 10px; color: #%06x;\">\n", + e_color_to_value ( + &efh->priv->colors[ + EM_FORMAT_HTML_COLOR_FRAME]), + e_color_to_value ( + &efh->priv->colors[ + EM_FORMAT_HTML_COLOR_CONTENT]), + e_color_to_value ( + &efh->priv->colors[ + EM_FORMAT_HTML_COLOR_TEXT])); camel_stream_write_string(stream, "<tt>\n" EFH_MESSAGE_START); em_format_format_text((EMFormat *)efh, (CamelStream *)filtered_stream, (CamelDataWrapper *)newpart); camel_stream_flush((CamelStream *)filtered_stream); @@ -844,9 +1658,17 @@ efh_text_enriched(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, E camel_stream_filter_add(filtered_stream, enriched); camel_object_unref(enriched); - camel_stream_printf (stream, - "<div style=\"border: solid #%06x 1px; background-color: #%06x; padding: 10px; color: #%06x;\">\n" EFH_MESSAGE_START, - efh->frame_colour & 0xffffff, efh->content_colour & 0xffffff, efh->text_colour & 0xffffff); + camel_stream_printf ( + stream, "<div style=\"border: solid #%06x 1px; background-color: #%06x; padding: 10px; color: #%06x;\">\n" EFH_MESSAGE_START, + e_color_to_value ( + &efh->priv->colors[ + EM_FORMAT_HTML_COLOR_FRAME]), + e_color_to_value ( + &efh->priv->colors[ + EM_FORMAT_HTML_COLOR_CONTENT]), + e_color_to_value ( + &efh->priv->colors[ + EM_FORMAT_HTML_COLOR_TEXT])); em_format_format_text((EMFormat *)efh, (CamelStream *)filtered_stream, (CamelDataWrapper *)part); @@ -881,10 +1703,18 @@ efh_text_html(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFor EMFormatPURI *puri; char *cid = NULL; - camel_stream_printf (stream, - "<div style=\"border: solid #%06x 1px; background-color: #%06x; color: #%06x;\">\n" - "<!-- text/html -->\n" EFH_MESSAGE_START, - efh->frame_colour & 0xffffff, efh->content_colour & 0xffffff, efh->text_colour & 0xffffff); + camel_stream_printf ( + stream, "<div style=\"border: solid #%06x 1px; background-color: #%06x; color: #%06x;\">\n" + "<!-- text/html -->\n" EFH_MESSAGE_START, + e_color_to_value ( + &efh->priv->colors[ + EM_FORMAT_HTML_COLOR_FRAME]), + e_color_to_value ( + &efh->priv->colors[ + EM_FORMAT_HTML_COLOR_CONTENT]), + e_color_to_value ( + &efh->priv->colors[ + EM_FORMAT_HTML_COLOR_TEXT])); /* TODO: perhaps we don't need to calculate this anymore now base is handled better */ /* calculate our own location string so add_puri doesn't do it @@ -1021,9 +1851,17 @@ efh_message_deliverystatus(EMFormatHTML *efh, CamelStream *stream, CamelMimePart guint32 rgb = 0x737373; /* Yuck, this is copied from efh_text_plain */ - camel_stream_printf (stream, - "<div style=\"border: solid #%06x 1px; background-color: #%06x; padding: 10px; color: #%06x;\">\n", - efh->frame_colour & 0xffffff, efh->content_colour & 0xffffff, efh->text_colour & 0xffffff); + camel_stream_printf ( + stream, "<div style=\"border: solid #%06x 1px; background-color: #%06x; padding: 10px; color: #%06x;\">\n", + e_color_to_value ( + &efh->priv->colors[ + EM_FORMAT_HTML_COLOR_FRAME]), + e_color_to_value ( + &efh->priv->colors[ + EM_FORMAT_HTML_COLOR_CONTENT]), + e_color_to_value ( + &efh->priv->colors[ + EM_FORMAT_HTML_COLOR_TEXT])); filtered_stream = camel_stream_filter_new_with_stream(stream); html_filter = camel_mime_filter_tohtml_new(efh->text_html_flags, rgb); @@ -1215,284 +2053,17 @@ static EMFormatHandler type_builtin_table[] = { static void efh_builtin_init(EMFormatHTMLClass *efhc) { - int i; - - for (i=0;i<sizeof(type_builtin_table)/sizeof(type_builtin_table[0]);i++) - em_format_class_add_handler((EMFormatClass *)efhc, &type_builtin_table[i]); -} - -/* ********************************************************************** */ + EMFormatClass *efc; + gint ii; -/* Sigh, this is so we have a cancellable, async rendering thread */ -struct _format_msg { - MailMsg base; + efc = (EMFormatClass *) efhc; - EMFormatHTML *format; - EMFormat *format_source; - EMHTMLStream *estream; - CamelFolder *folder; - char *uid; - CamelMimeMessage *message; -}; - -static gchar * -efh_format_desc (struct _format_msg *m) -{ - return g_strdup(_("Formatting message")); + for (ii = 0; ii < G_N_ELEMENTS (type_builtin_table); ii++) + em_format_class_add_handler ( + efc, &type_builtin_table[ii]); } -static void -efh_format_exec (struct _format_msg *m) -{ - struct _EMFormatHTMLJob *job; - struct _EMFormatPURITree *puri_level; - int cancelled = FALSE; - CamelURL *base; - - if (m->format->html == NULL) - return; - - camel_stream_printf((CamelStream *)m->estream, - "<!doctype html public \"-//W3C//DTD HTML 4.0 TRANSITIONAL//EN\">\n<html>\n" - "<head>\n<meta name=\"generator\" content=\"Evolution Mail Component\">\n</head>\n" - "<body bgcolor =\"#%06x\" text=\"#%06x\" marginwidth=6 marginheight=6>\n", - m->format->body_colour & 0xffffff, - m->format->header_colour & 0xffffff); - - /* <insert top-header stuff here> */ - - if (((EMFormat *)m->format)->mode == EM_FORMAT_SOURCE) { - em_format_format_source((EMFormat *)m->format, (CamelStream *)m->estream, (CamelMimePart *)m->message); - } else { - const EMFormatHandler *handle; - - handle = em_format_find_handler((EMFormat *)m->format, "x-evolution/message/prefix"); - if (handle) - handle->handler((EMFormat *)m->format, (CamelStream *)m->estream, (CamelMimePart *)m->message, handle); - handle = em_format_find_handler((EMFormat *)m->format, "x-evolution/message/rfc822"); - if (handle) - handle->handler((EMFormat *)m->format, (CamelStream *)m->estream, (CamelMimePart *)m->message, handle); - handle = em_format_find_handler((EMFormat *)m->format, "x-evolution/message/post-header-closure"); - if (handle && !((EMFormat *)m->format)->print) - handle->handler((EMFormat *)m->format, (CamelStream *)m->estream, (CamelMimePart *)m->message, handle); - - } - - camel_stream_flush((CamelStream *)m->estream); - - puri_level = ((EMFormat *)m->format)->pending_uri_level; - base = ((EMFormat *)m->format)->base; - - do { - /* now dispatch any added tasks ... */ - g_mutex_lock(m->format->priv->lock); - while ((job = (struct _EMFormatHTMLJob *)e_dlist_remhead(&m->format->priv->pending_jobs))) { - g_mutex_unlock(m->format->priv->lock); - - /* This is an implicit check to see if the gtkhtml has been destroyed */ - if (!cancelled) - cancelled = m->format->html == NULL; - - /* Now do an explicit check for user cancellation */ - if (!cancelled) - cancelled = camel_operation_cancel_check(NULL); - - /* call jobs even if cancelled, so they can clean up resources */ - ((EMFormat *)m->format)->pending_uri_level = job->puri_level; - if (job->base) - ((EMFormat *)m->format)->base = job->base; - job->callback(job, cancelled); - ((EMFormat *)m->format)->base = base; - - /* clean up the job */ - camel_object_unref(job->stream); - if (job->base) - camel_url_free(job->base); - g_free(job); - - g_mutex_lock(m->format->priv->lock); - } - g_mutex_unlock(m->format->priv->lock); - - if (m->estream) { - /* Closing this base stream can queue more jobs, so we need - to check the list again after we've finished */ - d(printf("out of jobs, closing root stream\n")); - camel_stream_write_string((CamelStream *)m->estream, "</body>\n</html>\n"); - camel_stream_close((CamelStream *)m->estream); - camel_object_unref(m->estream); - m->estream = NULL; - } - - /* e_dlist_empty is atomic and doesn't need locking */ - } while (!e_dlist_empty(&m->format->priv->pending_jobs)); - - d(printf("out of jobs, done\n")); - - ((EMFormat *)m->format)->pending_uri_level = puri_level; -} - -static void -efh_format_done (struct _format_msg *m) -{ - d(printf("formatting finished\n")); - - m->format->load_http_now = FALSE; - m->format->priv->format_id = -1; - m->format->state = EM_FORMAT_HTML_STATE_NONE; - g_signal_emit_by_name(m->format, "complete"); -} - -static void -efh_format_free (struct _format_msg *m) -{ - d(printf("formatter freed\n")); - g_object_unref(m->format); - if (m->estream) { - camel_stream_close((CamelStream *)m->estream); - camel_object_unref(m->estream); - } - if (m->folder) - camel_object_unref(m->folder); - g_free(m->uid); - if (m->message) - camel_object_unref(m->message); - if (m->format_source) - g_object_unref(m->format_source); -} - -static MailMsgInfo efh_format_info = { - sizeof (struct _format_msg), - (MailMsgDescFunc) efh_format_desc, - (MailMsgExecFunc) efh_format_exec, - (MailMsgDoneFunc) efh_format_done, - (MailMsgFreeFunc) efh_format_free -}; - -static gboolean -efh_format_timeout(struct _format_msg *m) -{ - GtkHTMLStream *hstream; - EMFormatHTML *efh = m->format; - struct _EMFormatHTMLPrivate *p = efh->priv; - - if (m->format->html == NULL) { - mail_msg_unref(m); - return FALSE; - } - - d(printf("timeout called ...\n")); - if (p->format_id != -1) { - d(printf(" still waiting for cancellation to take effect, waiting ...\n")); - return TRUE; - } - - g_return_val_if_fail (e_dlist_empty(&p->pending_jobs), FALSE); - - d(printf(" ready to go, firing off format thread\n")); - - /* call super-class to kick it off */ - efh_parent->format_clone((EMFormat *)efh, m->folder, m->uid, m->message, m->format_source); - em_format_html_clear_pobject(m->format); - - /* FIXME: method off EMFormat? */ - if (((EMFormat *)efh)->valid) { - camel_cipher_validity_free(((EMFormat *)efh)->valid); - ((EMFormat *)efh)->valid = NULL; - ((EMFormat *)efh)->valid_parent = NULL; - } - - if (m->message == NULL) { - hstream = gtk_html_begin(efh->html); - gtk_html_stream_close(hstream, GTK_HTML_STREAM_OK); - mail_msg_unref(m); - p->last_part = NULL; - } else { - efh->state = EM_FORMAT_HTML_STATE_RENDERING; - - if (p->last_part != m->message) { - hstream = gtk_html_begin (efh->html); - gtk_html_stream_printf (hstream, "<h5>%s</h5>", _("Formatting Message...")); - gtk_html_stream_close (hstream, GTK_HTML_STREAM_OK); - } - - hstream = NULL; - m->estream = (EMHTMLStream *)em_html_stream_new(efh->html, hstream); - - if (p->last_part == m->message) { - em_html_stream_set_flags (m->estream, - GTK_HTML_BEGIN_KEEP_SCROLL | GTK_HTML_BEGIN_KEEP_IMAGES - | GTK_HTML_BEGIN_BLOCK_UPDATES | GTK_HTML_BEGIN_BLOCK_IMAGES); - } else { - /* clear cache of inline-scanned text parts */ - g_hash_table_remove_all(p->text_inline_parts); - - p->last_part = m->message; - } - - efh->priv->format_id = m->base.seq; - mail_msg_unordered_push (m); - } - - efh->priv->format_timeout_id = 0; - efh->priv->format_timeout_msg = NULL; - - return FALSE; -} - -static void efh_format_clone(EMFormat *emf, CamelFolder *folder, const char *uid, CamelMimeMessage *msg, EMFormat *emfsource) -{ - EMFormatHTML *efh = (EMFormatHTML *)emf; - struct _format_msg *m; - - /* How to sub-class ? Might need to adjust api ... */ - - if (efh->html == NULL) - return; - - d(printf("efh_format called\n")); - if (efh->priv->format_timeout_id != 0) { - d(printf(" timeout for last still active, removing ...\n")); - g_source_remove(efh->priv->format_timeout_id); - efh->priv->format_timeout_id = 0; - mail_msg_unref(efh->priv->format_timeout_msg); - efh->priv->format_timeout_msg = NULL; - } - - m = mail_msg_new(&efh_format_info); - m->format = (EMFormatHTML *)emf; - g_object_ref(emf); - m->format_source = emfsource; - if (emfsource) - g_object_ref(emfsource); - m->folder = folder; - if (folder) - camel_object_ref(folder); - m->uid = g_strdup(uid); - m->message = msg; - if (msg) - camel_object_ref(msg); - - if (efh->priv->format_id == -1) { - d(printf(" idle, forcing format\n")); - efh_format_timeout(m); - } else { - d(printf(" still busy, cancelling and queuing wait\n")); - /* cancel and poll for completion */ - mail_msg_cancel(efh->priv->format_id); - efh->priv->format_timeout_msg = m; - efh->priv->format_timeout_id = g_timeout_add(100, (GSourceFunc)efh_format_timeout, m); - } -} - -static void efh_format_error(EMFormat *emf, CamelStream *stream, const char *txt) -{ - char *html; - - html = camel_text_to_html (txt, CAMEL_MIME_FILTER_TOHTML_CONVERT_NL|CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0); - camel_stream_printf(stream, "<em><font color=\"red\">%s</font></em><br>", html); - g_free(html); -} +/* ********************************************************************** */ static void efh_format_text_header (EMFormatHTML *emfh, CamelStream *stream, const char *label, const char *value, guint32 flags) @@ -1859,10 +2430,12 @@ efh_format_headers(EMFormatHTML *efh, CamelStream *stream, CamelMedium *part) charset = camel_iconv_charset_name(charset); if (!efh->simple_headers) - camel_stream_printf(stream, - "<font color=\"#%06x\">\n" - "<table cellpadding=\"0\" width=\"100%%\">", - efh->header_colour & 0xffffff); + camel_stream_printf ( + stream, "<font color=\"#%06x\">\n" + "<table cellpadding=\"0\" width=\"100%%\">", + e_color_to_value ( + &efh->priv->colors[ + EM_FORMAT_HTML_COLOR_HEADER])); hdr_charset = emf->charset ? emf->charset : emf->default_charset; @@ -1944,7 +2517,8 @@ efh_format_headers(EMFormatHTML *efh, CamelStream *stream, CamelMedium *part) face = !g_ascii_strcasecmp (h->name, "Face"); while (header) { - if (emf->show_photo && !photo_name && !g_ascii_strcasecmp (header->name, "From")) + if (em_format_html_get_show_sender_photo (efh) && + !photo_name && !g_ascii_strcasecmp (header->name, "From")) photo_name = header->value; if (!mailer_shown && mailer && (!g_ascii_strcasecmp (header->name, "X-Mailer") || @@ -2002,10 +2576,12 @@ efh_format_headers(EMFormatHTML *efh, CamelStream *stream, CamelMedium *part) if (photo_name) { char *classid; CamelMimePart *photopart; + gboolean only_local_photo; cia = camel_internet_address_new(); camel_address_decode((CamelAddress *) cia, (const char *) photo_name); - photopart = em_utils_contact_photo (cia, emf->photo_local); + only_local_photo = em_format_html_get_only_local_photos (efh); + photopart = em_utils_contact_photo (cia, only_local_photo); if (photopart) { contact_has_photo = TRUE; @@ -2063,7 +2639,8 @@ efh_format_headers(EMFormatHTML *efh, CamelStream *stream, CamelMedium *part) } } -static void efh_format_message(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info) +static void +efh_format_message(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info) { const EMFormatHandler *handle; @@ -2095,57 +2672,3 @@ static void efh_format_message(EMFormat *emf, CamelStream *stream, CamelMimePart emf->valid = save; emf->valid_parent = save_parent; } - -static void efh_format_source(EMFormat *emf, CamelStream *stream, CamelMimePart *part) -{ - CamelStreamFilter *filtered_stream; - CamelMimeFilter *html_filter; - CamelDataWrapper *dw = (CamelDataWrapper *)part; - - filtered_stream = camel_stream_filter_new_with_stream ((CamelStream *) stream); - html_filter = camel_mime_filter_tohtml_new (CAMEL_MIME_FILTER_TOHTML_CONVERT_NL - | CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES - | CAMEL_MIME_FILTER_TOHTML_PRESERVE_8BIT, 0); - camel_stream_filter_add(filtered_stream, html_filter); - camel_object_unref(html_filter); - - camel_stream_write_string((CamelStream *)stream, "<table><tr><td><tt>"); - em_format_format_text(emf, (CamelStream *)filtered_stream, dw); - camel_object_unref(filtered_stream); - - camel_stream_write_string(stream, "</tt></td></tr></table>"); -} - -static void -efh_format_attachment(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const char *mime_type, const EMFormatHandler *handle) -{ - char *text, *html; - - /* we display all inlined attachments only */ - - /* this could probably be cleaned up ... */ - camel_stream_write_string(stream, - "<table border=1 cellspacing=0 cellpadding=0><tr><td>" - "<table width=10 cellspacing=0 cellpadding=0>" - "<tr><td></td></tr></table></td>" - "<td><table width=3 cellspacing=0 cellpadding=0>" - "<tr><td></td></tr></table></td><td><font size=-1>\n"); - - /* output some info about it */ - text = em_format_describe_part(part, mime_type); - html = camel_text_to_html(text, ((EMFormatHTML *)emf)->text_html_flags & CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0); - camel_stream_write_string(stream, html); - g_free(html); - g_free(text); - - camel_stream_write_string(stream, "</font></td></tr><tr></table>"); - - if (handle && em_format_is_inline(emf, emf->part_id->str, part, handle)) - handle->handler(emf, stream, part, handle); -} - -static gboolean -efh_busy(EMFormat *emf) -{ - return (((EMFormatHTML *)emf)->priv->format_id != -1); -} diff --git a/mail/em-format-html.h b/mail/em-format-html.h index a34f7b6915..23e0057f89 100644 --- a/mail/em-format-html.h +++ b/mail/em-format-html.h @@ -22,7 +22,7 @@ */ /* - Concrete class for formatting mails to html + Abstract class for formatting mails to html */ #ifndef EM_FORMAT_HTML_H @@ -73,6 +73,16 @@ typedef enum { EM_FORMAT_HTML_STATE_RENDERING } EMFormatHTMLState; +typedef enum { + EM_FORMAT_HTML_COLOR_BODY, /* header area background */ + EM_FORMAT_HTML_COLOR_CITATION, /* citation font color */ + EM_FORMAT_HTML_COLOR_CONTENT, /* message area background */ + EM_FORMAT_HTML_COLOR_FRAME, /* frame around message area */ + EM_FORMAT_HTML_COLOR_HEADER, /* header font color */ + EM_FORMAT_HTML_COLOR_TEXT, /* message font color */ + EM_FORMAT_HTML_NUM_COLOR_TYPES +} EMFormatHTMLColorType; + /* A HTMLJob will be executed in another thread, in sequence. It's job is to write to its stream, close it if successful, then exit. */ @@ -196,10 +206,14 @@ struct _EMFormatHTMLPObject { * multipart/related objects and inline images. **/ struct _EMFormatHTML { - EMFormat format; + EMFormat parent; + EMFormatHTMLPrivate *priv; +<<<<<<< HEAD:mail/em-format-html.h +======= EMFormatHTMLPrivate *priv; +>>>>>>> master:mail/em-format-html.h GtkHTML *html; EDList pending_object_list; @@ -207,15 +221,6 @@ struct _EMFormatHTML { GSList *headers; guint32 text_html_flags; /* default flags for text to html conversion */ - guint32 body_colour; /* header box colour */ - guint32 header_colour; - guint32 text_colour; - guint32 frame_colour; - guint32 content_colour; - guint32 citation_colour; - unsigned int load_http:2; - unsigned int load_http_now:1; - unsigned int mark_citations:1; unsigned int simple_headers:1; /* simple header format, no box/table */ unsigned int hide_headers:1; /* no headers at all */ unsigned int show_icon:1; /* show an icon when the sender used Evo */ @@ -225,19 +230,40 @@ struct _EMFormatHTML { }; struct _EMFormatHTMLClass { - EMFormatClass format_class; + EMFormatClass parent_class; + + GType html_widget_type; }; GType em_format_html_get_type (void); -EMFormatHTML * em_format_html_new (void); -void em_format_html_load_http (EMFormatHTML *efh); - -void em_format_html_set_load_http (EMFormatHTML *efh, - int style); +void em_format_html_load_images (EMFormatHTML *efh); +void em_format_html_get_color (EMFormatHTML *efh, + EMFormatHTMLColorType type, + GdkColor *color); +void em_format_html_set_color (EMFormatHTML *efh, + EMFormatHTMLColorType type, + const GdkColor *color); +MailConfigHTTPMode + em_format_html_get_image_loading_policy + (EMFormatHTML *efh); +void em_format_html_set_image_loading_policy + (EMFormatHTML *efh, + MailConfigHTTPMode policy); +gboolean em_format_html_get_mark_citations + (EMFormatHTML *efh); void em_format_html_set_mark_citations (EMFormatHTML *efh, - int state, - guint32 citation_colour); + gboolean mark_citations); +gboolean em_format_html_get_only_local_photos + (EMFormatHTML *efh); +void em_format_html_set_only_local_photos + (EMFormatHTML *efh, + gboolean only_local_photos); +gboolean em_format_html_get_show_sender_photo + (EMFormatHTML *efh); +void em_format_html_set_show_sender_photo + (EMFormatHTML *efh, + gboolean show_sender_photo); /* retrieves a pseudo-part icon wrapper for a file */ CamelMimePart * em_format_html_file_part (EMFormatHTML *efh, @@ -261,7 +287,6 @@ EMFormatHTMLPObject * void em_format_html_remove_pobject (EMFormatHTML *efh, EMFormatHTMLPObject *pobject); void em_format_html_clear_pobject (EMFormatHTML *efh); - EMFormatHTMLJob * em_format_html_job_new (EMFormatHTML *efh, void (*callback)(EMFormatHTMLJob *job, int cancelled), diff --git a/mail/em-format-quote.c b/mail/em-format-quote.c index 49c546863a..43c7e2e55c 100644 --- a/mail/em-format-quote.c +++ b/mail/em-format-quote.c @@ -28,7 +28,6 @@ #include <string.h> #include <camel/camel-iconv.h> -#include <camel/camel-stream.h> #include <camel/camel-stream-filter.h> #include <camel/camel-mime-filter-tohtml.h> #include <camel/camel-mime-filter-enriched.h> @@ -55,82 +54,94 @@ static void emfq_format_attachment(EMFormat *, CamelStream *, CamelMimePart *, c static void emfq_builtin_init(EMFormatQuoteClass *efhc); -static EMFormatClass *emfq_parent; +static gpointer parent_class; static void emfq_init(GObject *o) { EMFormatQuote *emfq =(EMFormatQuote *) o; - emfq->priv = g_malloc0(sizeof(*emfq->priv)); - /* we want to convert url's etc */ emfq->text_html_flags = CAMEL_MIME_FILTER_TOHTML_PRE | CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS | CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES; } static void -emfq_finalise(GObject *o) +emfq_finalize (GObject *object) { - EMFormatQuote *emfq =(EMFormatQuote *) o; + EMFormatQuote *emfq =(EMFormatQuote *) object; if (emfq->stream) camel_object_unref(emfq->stream); g_free(emfq->credits); - g_free(emfq->priv); - ((GObjectClass *) emfq_parent)->finalize(o); + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); } static void -emfq_base_init(EMFormatQuoteClass *emfqklass) +emfq_base_init(EMFormatQuoteClass *emfqclass) { - emfq_builtin_init(emfqklass); + emfq_builtin_init(emfqclass); } static void -emfq_class_init(GObjectClass *klass) +emfq_class_init (EMFormatQuoteClass *class) { - ((EMFormatClass *) klass)->format_clone = emfq_format_clone; - ((EMFormatClass *) klass)->format_error = emfq_format_error; - ((EMFormatClass *) klass)->format_source = emfq_format_source; - ((EMFormatClass *) klass)->format_attachment = emfq_format_attachment; + GObjectClass *object_class; + EMFormatClass *format_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMFormatQuotePrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->finalize = emfq_finalize; - klass->finalize = emfq_finalise; + format_class = EM_FORMAT_CLASS (class); + format_class->format_clone = emfq_format_clone; + format_class->format_error = emfq_format_error; + format_class->format_source = emfq_format_source; + format_class->format_attachment = emfq_format_attachment; } GType -em_format_quote_get_type(void) +em_format_quote_get_type (void) { static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof(EMFormatQuoteClass), - (GBaseInitFunc)emfq_base_init, NULL, - (GClassInitFunc)emfq_class_init, - NULL, NULL, - sizeof(EMFormatQuote), 0, - (GInstanceInitFunc) emfq_init + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMFormatQuoteClass), + (GBaseInitFunc) emfq_base_init, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) emfq_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMFormatQuote), + 0, /* n_preallocs */ + (GInstanceInitFunc) emfq_init, + NULL /* value_table */ }; - emfq_parent = g_type_class_ref(em_format_get_type()); - type = g_type_register_static(em_format_get_type(), "EMFormatQuote", &info, 0); + type = g_type_register_static ( + EM_TYPE_FORMAT, "EMFormatQuote", &type_info, 0); } return type; } EMFormatQuote * -em_format_quote_new(const char *credits, CamelStream *stream, guint32 flags) +em_format_quote_new (const gchar *credits, + CamelStream *stream, + guint32 flags) { EMFormatQuote *emfq; - emfq = (EMFormatQuote *)g_object_new(em_format_quote_get_type(), NULL); + emfq = g_object_new (EM_TYPE_FORMAT_QUOTE, NULL); - emfq->credits = g_strdup(credits); + emfq->credits = g_strdup (credits); emfq->stream = stream; - camel_object_ref(stream); + camel_object_ref (stream); emfq->flags = flags; return emfq; @@ -148,7 +159,8 @@ emfq_format_clone(EMFormat *emf, CamelFolder *folder, const char *uid, CamelMime EMFormatQuote *emfq = (EMFormatQuote *) emf; const EMFormatHandler *handle; - ((EMFormatClass *)emfq_parent)->format_clone(emf, folder, uid, msg, src); + /* Chain up to parent's format_clone() method. */ + EM_FORMAT_CLASS (parent_class)->format_clone (emf, folder, uid, msg, src); camel_stream_reset(emfq->stream); if (gconf_client_get_bool(mail_config_get_gconf_client(), "/apps/evolution/mail/composer/top_signature", NULL)) diff --git a/mail/em-format.c b/mail/em-format.c index 89445ab35a..27c627a185 100644 --- a/mail/em-format.c +++ b/mail/em-format.c @@ -32,7 +32,6 @@ #include <gio/gio.h> #include <libedataserver/e-msgport.h> -#include <camel/camel-url.h> #include <camel/camel-stream.h> #include <camel/camel-stream-mem.h> #include <camel/camel-multipart.h> @@ -53,6 +52,7 @@ #include "em-format.h" #include "em-utils.h" #include "mail-config.h" +#include "mail-session.h" #define d(x) @@ -62,8 +62,8 @@ This is still kind of yucky, we should maintian a full tree of all this data, along with/as part of the puri tree */ struct _EMFormatCache { - struct _CamelCipherValidity *valid; /* validity copy */ - struct _CamelMimePart *secured; /* encrypted subpart */ + CamelCipherValidity *valid; /* validity copy */ + CamelMimePart *secured; /* encrypted subpart */ unsigned int state:2; /* inline state */ @@ -85,8 +85,8 @@ enum { EMF_LAST_SIGNAL, }; -static guint emf_signals[EMF_LAST_SIGNAL]; -static GObjectClass *emf_parent; +static gpointer parent_class; +static guint signals[EMF_LAST_SIGNAL]; static void emf_free_cache(struct _EMFormatCache *efc) @@ -111,32 +111,14 @@ emf_insert_cache(EMFormat *emf, const char *partid) } static void -emf_init(GObject *o) +emf_finalize (GObject *object) { - EMFormat *emf = (EMFormat *)o; - - emf->inline_table = g_hash_table_new_full ( - g_str_hash, g_str_equal, - (GDestroyNotify) NULL, - (GDestroyNotify) emf_free_cache); - emf->composer = FALSE; - emf->print = FALSE; - emf->show_photo = TRUE; - emf->photo_local = TRUE; - e_dlist_init(&emf->header_list); - em_format_default_headers(emf); - emf->part_id = g_string_new(""); -} - -static void -emf_finalise(GObject *o) -{ - EMFormat *emf = (EMFormat *)o; + EMFormat *emf = EM_FORMAT (object); if (emf->session) - camel_object_unref(emf->session); + camel_object_unref (emf->session); - g_hash_table_destroy(emf->inline_table); + g_hash_table_destroy (emf->inline_table); em_format_clear_headers(emf); camel_cipher_validity_free(emf->valid); @@ -146,54 +128,83 @@ emf_finalise(GObject *o) /* FIXME: check pending jobs */ - ((GObjectClass *)emf_parent)->finalize(o); + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); } static void -emf_base_init(EMFormatClass *emfklass) +emf_base_init (EMFormatClass *class) { - emfklass->type_handlers = g_hash_table_new(g_str_hash, g_str_equal); - emf_builtin_init(emfklass); + class->type_handlers = g_hash_table_new (g_str_hash, g_str_equal); + emf_builtin_init (class); } static void -emf_class_init(GObjectClass *klass) +emf_class_init (EMFormatClass *class) { - ((EMFormatClass *)klass)->type_handlers = g_hash_table_new(g_str_hash, g_str_equal); - emf_builtin_init((EMFormatClass *)klass); - - klass->finalize = emf_finalise; - ((EMFormatClass *)klass)->find_handler = emf_find_handler; - ((EMFormatClass *)klass)->format_clone = emf_format_clone; - ((EMFormatClass *)klass)->format_secure = emf_format_secure; - ((EMFormatClass *)klass)->busy = emf_busy; - - emf_signals[EMF_COMPLETE] = - g_signal_new("complete", - G_OBJECT_CLASS_TYPE (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EMFormatClass, complete), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + + object_class = G_OBJECT_CLASS (class); + object_class->finalize = emf_finalize; + + class->find_handler = emf_find_handler; + class->format_clone = emf_format_clone; + class->format_secure = emf_format_secure; + class->busy = emf_busy; + + signals[EMF_COMPLETE] = g_signal_new ( + "complete", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMFormatClass, complete), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + class->type_handlers = g_hash_table_new (g_str_hash, g_str_equal); + emf_builtin_init (class); +} + +static void +emf_init (EMFormat *emf) +{ + emf->inline_table = g_hash_table_new_full ( + g_str_hash, g_str_equal, + (GDestroyNotify) NULL, + (GDestroyNotify) emf_free_cache); + emf->composer = FALSE; + emf->print = FALSE; + e_dlist_init(&emf->header_list); + em_format_default_headers(emf); + emf->part_id = g_string_new(""); + + emf->session = session; + camel_object_ref (emf->session); } GType -em_format_get_type(void) +em_format_get_type (void) { static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof(EMFormatClass), - (GBaseInitFunc)emf_base_init, NULL, - (GClassInitFunc)emf_class_init, - NULL, NULL, - sizeof(EMFormat), 0, - (GInstanceInitFunc)emf_init + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMFormatClass), + (GBaseInitFunc) emf_base_init, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) emf_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMFormat), + 0, /* n_preallocs */ + (GInstanceInitFunc) emf_init, + NULL /* value_table */ }; - emf_parent = g_type_class_ref(G_TYPE_OBJECT); - type = g_type_register_static(G_TYPE_OBJECT, "EMFormat", &info, 0); + + type = g_type_register_static ( + G_TYPE_OBJECT, "EMFormat", &type_info, 0); } return type; @@ -255,6 +266,7 @@ em_format_merge_handler(EMFormat *new, EMFormat *old) g_hash_table_foreach (oldc->type_handlers, merge_missing, &fclasses); } + /** * em_format_class_remove_handler: * @emfc: @@ -285,6 +297,20 @@ em_format_class_remove_handler(EMFormatClass *emfc, EMFormatHandler *info) } } +const EMFormatHandler * +em_format_find_handler (EMFormat *emf, + const gchar *mime_type) +{ + EMFormatClass *class; + + g_return_val_if_fail (EM_IS_FORMAT (emf), NULL); + g_return_val_if_fail (mime_type != NULL, NULL); + + class = EM_FORMAT_GET_CLASS (emf); + g_return_val_if_fail (class->find_handler != NULL, NULL); + return class->find_handler (emf, mime_type); +} + /** * em_format_find_handler: * @emf: @@ -758,10 +784,10 @@ emf_busy(EMFormat *emf) /** * em_format_format_clone: - * @emf: Mail formatter. - * @folder: Camel Folder. - * @uid: Uid of message. - * @msg: Camel Message. + * @emf: an #EMFormat + * @folder: a #CamelFolder or %NULL + * @uid: Message UID or %NULL + * @msg: a #CamelMimeMessage or %NULL * @emfsource: Used as a basis for user-altered layout, e.g. inline viewed * attachments. * @@ -772,25 +798,42 @@ emf_busy(EMFormat *emf) * a display refresh, or it can be used to generate an identical layout, * e.g. to print what the user has shown inline. **/ -/* e_format_format_clone is a macro */ +void +em_format_format_clone (EMFormat *emf, + CamelFolder *folder, + const gchar *uid, + CamelMimeMessage *message, + EMFormat *source) +{ + EMFormatClass *class; + + g_return_if_fail (EM_IS_FORMAT (emf)); + g_return_if_fail (folder == NULL || CAMEL_IS_FOLDER (folder)); + g_return_if_fail (message == NULL || CAMEL_IS_MIME_MESSAGE (message)); + g_return_if_fail (source == NULL || EM_IS_FORMAT (source)); + + class = EM_FORMAT_GET_CLASS (emf); + g_return_if_fail (class->format_clone != NULL); + class->format_clone (emf, folder, uid, message, source); +} -/** - * em_format_set_session: - * @emf: - * @s: - * - * Set the CamelSession to be used for signature verification and decryption - * purposes. If this is not set, then signatures cannot be verified or - * encrypted messages viewed. - **/ void -em_format_set_session(EMFormat *emf, struct _CamelSession *s) +em_format_format (EMFormat *emf, + CamelFolder *folder, + const gchar *uid, + CamelMimeMessage *message) { - if (s) - camel_object_ref(s); - if (emf->session) - camel_object_unref(emf->session); - emf->session = s; + /* em_format_format_clone() will check the arguments. */ + em_format_format_clone (emf, folder, uid, message, NULL); +} + +void +em_format_redraw (EMFormat *emf) +{ + g_return_if_fail (EM_IS_FORMAT (emf)); + + em_format_format_clone ( + emf, emf->folder, emf->uid, emf->message, emf); } /** @@ -1030,28 +1073,101 @@ void em_format_set_inline(EMFormat *emf, const char *partid, int state) em_format_redraw(emf); } -void em_format_format_error(EMFormat *emf, CamelStream *stream, const char *fmt, ...) +void +em_format_format_attachment (EMFormat *emf, + CamelStream *stream, + CamelMimePart *mime_part, + const gchar *mime_type, + const struct _EMFormatHandler *info) { + EMFormatClass *class; + + g_return_if_fail (EM_IS_FORMAT (emf)); + g_return_if_fail (CAMEL_IS_STREAM (stream)); + g_return_if_fail (CAMEL_IS_MIME_PART (mime_part)); + g_return_if_fail (mime_type != NULL); + g_return_if_fail (info != NULL); + + class = EM_FORMAT_GET_CLASS (emf); + g_return_if_fail (class->format_attachment != NULL); + class->format_attachment (emf, stream, mime_part, mime_type, info); +} + +void +em_format_format_error (EMFormat *emf, + CamelStream *stream, + const gchar *format, + ...) +{ + EMFormatClass *class; + gchar *errmsg; va_list ap; - char *txt; - va_start(ap, fmt); - txt = g_strdup_vprintf(fmt, ap); - ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->format_error((emf), (stream), (txt)); - g_free(txt); + g_return_if_fail (EM_IS_FORMAT (emf)); + g_return_if_fail (CAMEL_IS_STREAM (stream)); + g_return_if_fail (format != NULL); + + class = EM_FORMAT_GET_CLASS (emf); + g_return_if_fail (class->format_error != NULL); + + va_start (ap, format); + errmsg = g_strdup_vprintf (format, ap); + class->format_error (emf, stream, errmsg); + g_free (errmsg); + va_end (ap); } void -em_format_format_secure(EMFormat *emf, struct _CamelStream *stream, struct _CamelMimePart *part, struct _CamelCipherValidity *valid) +em_format_format_secure (EMFormat *emf, + CamelStream *stream, + CamelMimePart *mime_part, + CamelCipherValidity *valid) { - ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->format_secure(emf, stream, part, valid); + EMFormatClass *class; + + g_return_if_fail (EM_IS_FORMAT (emf)); + g_return_if_fail (CAMEL_IS_STREAM (stream)); + g_return_if_fail (CAMEL_IS_MIME_PART (mime_part)); + g_return_if_fail (valid != NULL); + + class = EM_FORMAT_GET_CLASS (emf); + g_return_if_fail (class->format_secure != NULL); + class->format_secure (emf, stream, mime_part, valid); if (emf->valid_parent == NULL && emf->valid != NULL) { - camel_cipher_validity_free(emf->valid); + camel_cipher_validity_free (emf->valid); emf->valid = NULL; } } +void +em_format_format_source (EMFormat *emf, + CamelStream *stream, + CamelMimePart *mime_part) +{ + EMFormatClass *class; + + g_return_if_fail (EM_IS_FORMAT (emf)); + g_return_if_fail (CAMEL_IS_STREAM (stream)); + g_return_if_fail (CAMEL_IS_MIME_PART (mime_part)); + + class = EM_FORMAT_GET_CLASS (emf); + g_return_if_fail (class->format_source != NULL); + class->format_source (emf, stream, mime_part); +} + +gboolean +em_format_busy (EMFormat *emf) +{ + EMFormatClass *class; + + g_return_val_if_fail (EM_IS_FORMAT (emf), FALSE); + + class = EM_FORMAT_GET_CLASS (emf); + g_return_val_if_fail (class->busy != NULL, FALSE); + return class->busy (emf); +} + /* should this be virtual? */ void em_format_format_content(EMFormat *emf, CamelStream *stream, CamelMimePart *part) @@ -1365,7 +1481,7 @@ emf_multipart_encrypted(EMFormat *emf, CamelStream *stream, CamelMimePart *part, em_format_format_secure(emf, stream, opart, valid); } - /* TODO: Make sure when we finalise this part, it is zero'd out */ + /* TODO: Make sure when we finalize this part, it is zero'd out */ camel_object_unref(opart); camel_object_unref(context); camel_exception_free(ex); @@ -1721,10 +1837,10 @@ static EMFormatHandler type_builtin_table[] = { }; static void -emf_builtin_init(EMFormatClass *klass) +emf_builtin_init(EMFormatClass *class) { int i; for (i=0;i<sizeof(type_builtin_table)/sizeof(type_builtin_table[0]);i++) - g_hash_table_insert(klass->type_handlers, type_builtin_table[i].mime_type, &type_builtin_table[i]); + g_hash_table_insert(class->type_handlers, type_builtin_table[i].mime_type, &type_builtin_table[i]); } diff --git a/mail/em-format.h b/mail/em-format.h index 004d9c2e96..f262d49be1 100644 --- a/mail/em-format.h +++ b/mail/em-format.h @@ -249,8 +249,6 @@ struct _EMFormat { char *default_charset; /* charset fallback */ gboolean composer; /* Formatting from composer ?*/ gboolean print; - gboolean show_photo; /* Want to show the photo of the sender ?*/ - gboolean photo_local; /* Photos only from local addressbooks */ }; struct _EMFormatClass { @@ -286,67 +284,119 @@ struct _EMFormatClass { void (*complete)(EMFormat *); }; -/* helper entry point */ -void em_format_set_session(EMFormat *emf, CamelSession *s); +void em_format_set_mode (EMFormat *emf, + em_format_mode_t type); +void em_format_set_charset (EMFormat *emf, + const char *charset); +void em_format_set_default_charset (EMFormat *emf, + const char *charset); -void em_format_set_mode(EMFormat *emf, em_format_mode_t type); -void em_format_set_charset(EMFormat *emf, const char *charset); -void em_format_set_default_charset(EMFormat *emf, const char *charset); +/* also indicates to show all headers */ +void em_format_clear_headers (EMFormat *emf); -void em_format_clear_headers(EMFormat *emf); /* also indicates to show all headers */ -void em_format_default_headers(EMFormat *emf); -void em_format_add_header(EMFormat *emf, const char *name, guint32 flags); +void em_format_default_headers (EMFormat *emf); +void em_format_add_header (EMFormat *emf, + const gchar *name, + guint32 flags); /* FIXME: Need a 'clone' api to copy details about the current view (inlines etc) Or maybe it should live with sub-classes? */ -int em_format_is_attachment(EMFormat *emf, CamelMimePart *part); +int em_format_is_attachment (EMFormat *emf, + CamelMimePart *part); -int em_format_is_inline(EMFormat *emf, const char *partid, CamelMimePart *part, const EMFormatHandler *handle); -void em_format_set_inline(EMFormat *emf, const char *partid, int state); +int em_format_is_inline (EMFormat *emf, + const char *partid, + CamelMimePart *part, + const EMFormatHandler *handle); +void em_format_set_inline (EMFormat *emf, + const char *partid, + int state); -char *em_format_describe_part(CamelMimePart *part, const char *mimetype); +char * em_format_describe_part (CamelMimePart *part, + const char *mime_type); /* for implementers */ -GType em_format_get_type(void); - -void em_format_class_add_handler(EMFormatClass *emfc, EMFormatHandler *info); -void em_format_class_remove_handler(EMFormatClass *emfc, EMFormatHandler *info); -#define em_format_find_handler(emf, type) ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->find_handler((emf), (type)) -const EMFormatHandler *em_format_fallback_handler(EMFormat *emf, const char *mime_type); +GType em_format_get_type (void); + +void em_format_class_add_handler (EMFormatClass *emfc, + EMFormatHandler *info); +void em_format_class_remove_handler (EMFormatClass *emfc, + EMFormatHandler *info); +const EMFormatHandler * + em_format_find_handler (EMFormat *emf, + const gchar *mime_type); +const EMFormatHandler * + em_format_fallback_handler (EMFormat *emf, + const gchar *mime_type); /* puri is short for pending uri ... really */ -EMFormatPURI *em_format_add_puri(EMFormat *emf, size_t size, const char *uri, CamelMimePart *part, EMFormatPURIFunc func); -EMFormatPURI *em_format_find_visible_puri(EMFormat *emf, const char *uri); -EMFormatPURI *em_format_find_puri(EMFormat *emf, const char *uri); -void em_format_clear_puri_tree(EMFormat *emf); -void em_format_push_level(EMFormat *emf); -void em_format_pull_level(EMFormat *emf); +EMFormatPURI * em_format_add_puri (EMFormat *emf, + size_t size, + const char *uri, + CamelMimePart *part, + EMFormatPURIFunc func); +EMFormatPURI * em_format_find_visible_puri (EMFormat *emf, + const char *uri); +EMFormatPURI * em_format_find_puri (EMFormat *emf, + const char *uri); +void em_format_clear_puri_tree (EMFormat *emf); +void em_format_push_level (EMFormat *emf); +void em_format_pull_level (EMFormat *emf); /* clones inline state/view and format, or use to redraw */ -#define em_format_format_clone(emf, folder, uid, msg, src) ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->format_clone((emf), (folder), (uid), (msg), (src)) +void em_format_format_clone (EMFormat *emf, + CamelFolder *folder, + const gchar *uid, + CamelMimeMessage *message, + EMFormat *source); + /* formats a new message */ -#define em_format_format(emf, folder, uid, msg) ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->format_clone((emf), (folder), (uid), (msg), NULL) -#define em_format_redraw(emf) ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->format_clone((EMFormat *)(emf), \ - ((EMFormat *)(emf))->folder, \ - ((EMFormat *)(emf))->uid, \ - ((EMFormat *)(emf))->message, \ - (EMFormat *)(emf)) -void em_format_format_error(EMFormat *emf, CamelStream *stream, const char *fmt, ...); -#define em_format_format_attachment(emf, stream, msg, type, info) ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->format_attachment((emf), (stream), (msg), (type), (info)) -#define em_format_format_source(emf, stream, msg) ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->format_source((emf), (stream), (msg)) -void em_format_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, CamelCipherValidity *valid); - -#define em_format_busy(emf) ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->busy((emf)) +void em_format_format (EMFormat *emf, + CamelFolder *folder, + const gchar *uid, + CamelMimeMessage *message); +void em_format_redraw (EMFormat *emf); +void em_format_format_attachment (EMFormat *emf, + CamelStream *stream, + CamelMimePart *mime_part, + const gchar *mime_type, + const struct _EMFormatHandler *info); +void em_format_format_error (EMFormat *emf, + CamelStream *stream, + const gchar *format, + ...) G_GNUC_PRINTF (3, 4); +void em_format_format_secure (EMFormat *emf, + CamelStream *stream, + CamelMimePart *mime_part, + CamelCipherValidity *valid); +void em_format_format_source (EMFormat *emf, + CamelStream *stream, + CamelMimePart *mime_part); + +gboolean em_format_busy (EMFormat *emf); /* raw content only */ -void em_format_format_content(EMFormat *emf, CamelStream *stream, CamelMimePart *part); +void em_format_format_content (EMFormat *emf, + CamelStream *stream, + CamelMimePart *part); + /* raw content text parts - should this just be checked/done by above? */ -void em_format_format_text(EMFormat *emf, CamelStream *stream, CamelDataWrapper *part); +void em_format_format_text (EMFormat *emf, + CamelStream *stream, + CamelDataWrapper *part); + +void em_format_part_as (EMFormat *emf, + CamelStream *stream, + CamelMimePart *part, + const gchar *mime_type); +void em_format_part (EMFormat *emf, + CamelStream *stream, + CamelMimePart *part); +void em_format_merge_handler (EMFormat *new, + EMFormat *old); -void em_format_part_as(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const char *mime_type); -void em_format_part(EMFormat *emf, CamelStream *stream, CamelMimePart *part); -void em_format_merge_handler(EMFormat *new, EMFormat *old); +G_END_DECLS G_END_DECLS diff --git a/mail/em-html-stream.c b/mail/em-html-stream.c index daa81d356d..096e1c9aa5 100644 --- a/mail/em-html-stream.c +++ b/mail/em-html-stream.c @@ -27,84 +27,39 @@ #endif #include <stdio.h> -#include <gtkhtml/gtkhtml.h> -#include <gtkhtml/gtkhtml-stream.h> #include <gtk/gtk.h> #include "em-html-stream.h" #define d(x) -static void em_html_stream_class_init (EMHTMLStreamClass *klass); -static void em_html_stream_init (CamelObject *object); -static void em_html_stream_finalize (CamelObject *object); - -static ssize_t emhs_sync_write(CamelStream *stream, const char *buffer, size_t n); -static int emhs_sync_close(CamelStream *stream); -static int emhs_sync_flush(CamelStream *stream); - static EMSyncStreamClass *parent_class = NULL; -CamelType -em_html_stream_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - parent_class = (EMSyncStreamClass *)em_sync_stream_get_type(); - type = camel_type_register (em_sync_stream_get_type(), - "EMHTMLStream", - sizeof (EMHTMLStream), - sizeof (EMHTMLStreamClass), - (CamelObjectClassInitFunc) em_html_stream_class_init, - NULL, - (CamelObjectInitFunc) em_html_stream_init, - (CamelObjectFinalizeFunc) em_html_stream_finalize); - } - - return type; -} - -static void -em_html_stream_class_init (EMHTMLStreamClass *klass) -{ - ((EMSyncStreamClass *)klass)->sync_write = emhs_sync_write; - ((EMSyncStreamClass *)klass)->sync_flush = emhs_sync_flush; - ((EMSyncStreamClass *)klass)->sync_close = emhs_sync_close; -} - -static void -em_html_stream_init (CamelObject *object) -{ - /*EMHTMLStream *emhs = (EMHTMLStream *)object;*/ -} - static void -emhs_cleanup(EMHTMLStream *emhs) +emhs_cleanup (EMHTMLStream *emhs) { if (emhs->sync.cancel && emhs->html_stream) - gtk_html_stream_close (emhs->html_stream, GTK_HTML_STREAM_ERROR); + gtk_html_stream_close ( + emhs->html_stream, GTK_HTML_STREAM_ERROR); + emhs->html_stream = NULL; emhs->sync.cancel = TRUE; - g_signal_handler_disconnect(emhs->html, emhs->destroy_id); - g_object_unref(emhs->html); + g_signal_handler_disconnect (emhs->html, emhs->destroy_id); + g_object_unref (emhs->html); emhs->html = NULL; } static void -em_html_stream_finalize (CamelObject *object) +emhs_gtkhtml_destroy (GtkHTML *html, + EMHTMLStream *emhs) { - EMHTMLStream *emhs = (EMHTMLStream *)object; - - d(printf("%p: finalising stream\n", object)); - if (emhs->html_stream) { - d(printf("%p: html stream still open - error\n", object)); - /* set 'in finalise' flag */ - camel_stream_close((CamelStream *)emhs); - } + emhs->sync.cancel = TRUE; + emhs_cleanup (emhs); } static ssize_t -emhs_sync_write(CamelStream *stream, const char *buffer, size_t n) +emhs_sync_write (CamelStream *stream, + const char *buffer, + size_t n) { EMHTMLStream *emhs = EM_HTML_STREAM (stream); @@ -112,9 +67,10 @@ emhs_sync_write(CamelStream *stream, const char *buffer, size_t n) return -1; if (emhs->html_stream == NULL) - emhs->html_stream = gtk_html_begin_full (emhs->html, NULL, NULL, emhs->flags); + emhs->html_stream = gtk_html_begin_full ( + emhs->html, NULL, NULL, emhs->flags); - gtk_html_stream_write(emhs->html_stream, buffer, n); + gtk_html_stream_write (emhs->html_stream, buffer, n); return (ssize_t) n; } @@ -133,48 +89,93 @@ emhs_sync_flush(CamelStream *stream) } static int -emhs_sync_close(CamelStream *stream) +emhs_sync_close (CamelStream *stream) { EMHTMLStream *emhs = (EMHTMLStream *)stream; if (emhs->html_stream == NULL) return -1; - gtk_html_stream_close(emhs->html_stream, GTK_HTML_STREAM_OK); - emhs_cleanup(emhs); + gtk_html_stream_close (emhs->html_stream, GTK_HTML_STREAM_OK); + emhs_cleanup (emhs); return 0; } static void -emhs_gtkhtml_destroy(struct _GtkHTML *html, EMHTMLStream *emhs) +em_html_stream_class_init (EMHTMLStreamClass *class) { - d(printf("%p: emhs gtkhtml destroy\n", emhs)); - emhs->sync.cancel = TRUE; - emhs_cleanup(emhs); + EMSyncStreamClass *sync_stream_class; + + parent_class = (EMSyncStreamClass *)em_sync_stream_get_type(); + + sync_stream_class = EM_SYNC_STREAM_CLASS (class); + sync_stream_class->sync_write = emhs_sync_write; + sync_stream_class->sync_flush = emhs_sync_flush; + sync_stream_class->sync_close = emhs_sync_close; +} + +static void +em_html_stream_init (EMHTMLStream *emhs) +{ +} + +static void +em_html_stream_finalize (EMHTMLStream *emhs) +{ + if (emhs->html_stream) { + /* set 'in finalise' flag */ + camel_stream_close (CAMEL_STREAM (emhs)); + } +} + +CamelType +em_html_stream_get_type (void) +{ + static CamelType type = CAMEL_INVALID_TYPE; + + if (G_UNLIKELY (type == CAMEL_INVALID_TYPE)) { + type = camel_type_register ( + em_sync_stream_get_type(), + "EMHTMLStream", + sizeof (EMHTMLStream), + sizeof (EMHTMLStreamClass), + (CamelObjectClassInitFunc) em_html_stream_class_init, + NULL, + (CamelObjectInitFunc) em_html_stream_init, + (CamelObjectFinalizeFunc) em_html_stream_finalize); + } + + return type; } /* TODO: Could pass NULL for html_stream, and do a gtk_html_begin on first data -> less flashing */ CamelStream * -em_html_stream_new(struct _GtkHTML *html, struct _GtkHTMLStream *html_stream) +em_html_stream_new (GtkHTML *html, + GtkHTMLStream *html_stream) { EMHTMLStream *new; + g_return_val_if_fail (GTK_IS_HTML (html), NULL); + new = EM_HTML_STREAM (camel_object_new (EM_HTML_STREAM_TYPE)); new->html_stream = html_stream; - new->html = html; + new->html = g_object_ref (html); new->flags = 0; - g_object_ref(html); - new->destroy_id = g_signal_connect(html, "destroy", G_CALLBACK(emhs_gtkhtml_destroy), new); + new->destroy_id = g_signal_connect ( + html, "destroy", + G_CALLBACK (emhs_gtkhtml_destroy), new); - em_sync_stream_set_buffer_size(&new->sync, 8192); + em_sync_stream_set_buffer_size (&new->sync, 8192); - return (CamelStream *)new; + return CAMEL_STREAM (new); } void em_html_stream_set_flags (EMHTMLStream *emhs, GtkHTMLBeginFlags flags) { + g_return_if_fail (EM_IS_HTML_STREAM (emhs)); + emhs->flags = flags; } diff --git a/mail/em-html-stream.h b/mail/em-html-stream.h index a8eabdda55..674cc590af 100644 --- a/mail/em-html-stream.h +++ b/mail/em-html-stream.h @@ -24,44 +24,47 @@ #ifndef EM_HTML_STREAM_H #define EM_HTML_STREAM_H -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ +#include <gtkhtml/gtkhtml.h> +#include <gtkhtml/gtkhtml-stream.h> +#include <mail/em-sync-stream.h> -#define EM_HTML_STREAM_TYPE (em_html_stream_get_type ()) -#define EM_HTML_STREAM(obj) (CAMEL_CHECK_CAST((obj), EM_HTML_STREAM_TYPE, EMHTMLStream)) -#define EM_HTML_STREAM_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), EM_HTML_STREAM_TYPE, EMHTMLStreamClass)) -#define EM_IS_HTML_STREAM(o) (CAMEL_CHECK_TYPE((o), EM_HTML_STREAM_TYPE)) +#define EM_HTML_STREAM_TYPE \ + (em_html_stream_get_type ()) +#define EM_HTML_STREAM(obj) \ + (CAMEL_CHECK_CAST \ + ((obj), EM_HTML_STREAM_TYPE, EMHTMLStream)) +#define EM_HTML_STREAM_CLASS(cls) \ + (CAMEL_CHECK_CLASS_CAST \ + ((cls), EM_HTML_STREAM_TYPE, EMHTMLStreamClass)) +#define EM_IS_HTML_STREAM(obj) \ + (CAMEL_CHECK_TYPE \ + ((obj), EM_HTML_STREAM_TYPE)) -struct _GtkHTML; -struct _GtkHTMLStream; +G_BEGIN_DECLS -#include "mail/em-sync-stream.h" +typedef struct _EMHTMLStream EMHTMLStream; +typedef struct _EMHTMLStreamClass EMHTMLStreamClass; -typedef struct _EMHTMLStream { +struct _EMHTMLStream { EMSyncStream sync; guint destroy_id; - struct _GtkHTML *html; - struct _GtkHTMLStream *html_stream; + GtkHTML *html; + GtkHTMLStream *html_stream; GtkHTMLBeginFlags flags; -} EMHTMLStream; +}; -typedef struct { +struct _EMHTMLStreamClass { EMSyncStreamClass parent_class; -} EMHTMLStreamClass; +}; +CamelType em_html_stream_get_type (void); +CamelStream * em_html_stream_new (GtkHTML *html, + GtkHTMLStream *html_stream); +void em_html_stream_set_flags (EMHTMLStream *emhs, + GtkHTMLBeginFlags flags); -CamelType em_html_stream_get_type (void); - -/* the html_stream is closed when we are finalised (with an error), or closed (ok) */ -CamelStream *em_html_stream_new(struct _GtkHTML *html, struct _GtkHTMLStream *html_stream); -void em_html_stream_set_flags (EMHTMLStream *emhs, GtkHTMLBeginFlags flags); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ +G_END_DECLS #endif /* EM_HTML_STREAM_H */ diff --git a/mail/em-mailer-prefs.c b/mail/em-mailer-prefs.c index e489e16826..379d126c0b 100644 --- a/mail/em-mailer-prefs.c +++ b/mail/em-mailer-prefs.c @@ -25,6 +25,7 @@ #endif #include <string.h> +#include <glib/gi18n-lib.h> #include "em-mailer-prefs.h" #include "em-format.h" @@ -33,7 +34,6 @@ #include <gtkhtml/gtkhtml-properties.h> #include <libxml/tree.h> #include "misc/e-charset-picker.h" -#include <bonobo/bonobo-generic-factory.h> #include <glade/glade.h> @@ -41,9 +41,10 @@ #include "libedataserverui/e-cell-renderer-color.h" +#include "e-util/e-binding.h" #include "e-util/e-util-private.h" -#include "e-util/e-util-labels.h" +#include "e-mail-label-manager.h" #include "mail-config.h" #include "em-junk-hook.h" #include "em-config.h" @@ -51,7 +52,7 @@ static void em_mailer_prefs_class_init (EMMailerPrefsClass *class); static void em_mailer_prefs_init (EMMailerPrefs *dialog); -static void em_mailer_prefs_dispose (GObject *obj); +static void em_mailer_prefs_finalize (GObject *object); static GtkVBoxClass *parent_class = NULL; @@ -127,7 +128,7 @@ em_mailer_prefs_class_init (EMMailerPrefsClass *klass) object_class = (GObjectClass *) klass; parent_class = g_type_class_ref (gtk_vbox_get_type ()); - object_class->dispose = em_mailer_prefs_dispose; + object_class->finalize = em_mailer_prefs_finalize; } static void @@ -137,15 +138,10 @@ em_mailer_prefs_init (EMMailerPrefs *preferences) } static void -em_mailer_prefs_dispose (GObject *obj) +em_mailer_prefs_finalize (GObject *obj) { EMMailerPrefs *prefs = (EMMailerPrefs *) obj; - if (prefs->header_list_store) { - g_object_unref (prefs->header_list_store); - prefs->header_list_store = NULL; - } - g_object_unref (prefs->gui); if (prefs->labels_change_notify_id) { @@ -154,157 +150,48 @@ em_mailer_prefs_dispose (GObject *obj) prefs->labels_change_notify_id = 0; } - ((GObjectClass *)(parent_class))->dispose (obj); + ((GObjectClass *)(parent_class))->finalize (obj); } - -static void -color_button_set_color (GtkColorButton *color_button, const gchar *spec) +static gboolean +mark_seen_timeout_transform (const GValue *src_value, + GValue *dst_value, + gpointer user_data) { - GdkColor color; + gdouble v_double; + + /* Shell Settings (int) -> Spin Button (double) */ + v_double = (gdouble) g_value_get_int (src_value); + g_value_set_double (dst_value, v_double / 1000.0); - if (gdk_color_parse (spec, &color)) - gtk_color_button_set_color (color_button, &color); + return TRUE; } -static void -citation_color_set (GtkColorButton *color_button, EMMailerPrefs *prefs) +static gboolean +mark_seen_timeout_reverse_transform (const GValue *src_value, + GValue *dst_value, + gpointer user_data) { - GdkColor color; - gchar spec[16]; + gdouble v_double; - gtk_color_button_get_color (color_button, &color); - g_snprintf (spec, sizeof (spec), "#%04x%04x%04x", - color.red, color.green, color.blue); + /* Spin Button (double) -> Shell Settings (int) */ + v_double = g_value_get_double (src_value); + g_value_set_int (dst_value, v_double * 1000); - gconf_client_set_string (prefs->gconf, - "/apps/evolution/mail/display/citation_colour", - spec, NULL); + return TRUE; } enum { - LABEL_LIST_COLUMN_COLOR, - LABEL_LIST_COLUMN_TAG, - LABEL_LIST_COLUMN_NAME -}; - -enum { JH_LIST_COLUMN_NAME, JH_LIST_COLUMN_VALUE, }; -static void -label_sensitive_buttons (EMMailerPrefs *prefs) -{ - gboolean can_remove = FALSE, have_selected = FALSE, locked; - - g_return_if_fail (prefs); - - /* it's not sensitive if it's locked for updates */ - locked = !GTK_WIDGET_IS_SENSITIVE (prefs->label_tree); - - if (!locked) { - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prefs->label_tree)); - if (gtk_tree_selection_get_selected (selection, &model, &iter)) { - gchar *tag = NULL; - - gtk_tree_model_get (model, &iter, LABEL_LIST_COLUMN_TAG, &tag, -1); - - can_remove = tag && !e_util_labels_is_system (tag); - have_selected = TRUE; - - g_free (tag); - } - } - - gtk_widget_set_sensitive (prefs->label_remove, !locked && can_remove); - gtk_widget_set_sensitive (prefs->label_edit, !locked && have_selected); -} - -static void -label_tree_cursor_changed (GtkWidget *widget, gpointer user_data) -{ - label_sensitive_buttons (user_data); -} - -static void -label_tree_refill (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data) -{ - EMMailerPrefs *prefs = (EMMailerPrefs *)user_data; - GSList *labels, *l; - GtkTreeSelection *selection; - GtkListStore *store; - GtkTreeModel *model; - GtkTreeIter last_iter; - gchar *last_path = NULL; - - g_return_if_fail (prefs != NULL); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prefs->label_tree)); - if (gtk_tree_selection_get_selected (selection, &model, &last_iter)) - last_path = gtk_tree_model_get_string_from_iter (model, &last_iter); - - store = GTK_LIST_STORE (model); - gtk_list_store_clear (store); - - /* cannot use mail-config cache here, because it's (or can be) updated later than this function call */ - labels = e_util_labels_parse (client); - - for (l = labels; l; l = l->next) { - GdkColor color; - GtkTreeIter iter; - EUtilLabel *label = l->data; - - if (label->colour) - gdk_color_parse (label->colour, &color); - - gtk_list_store_append (store, &iter); - gtk_list_store_set ( - store, &iter, - LABEL_LIST_COLUMN_COLOR, label->colour ? &color : NULL, - LABEL_LIST_COLUMN_NAME, label->name, - LABEL_LIST_COLUMN_TAG, label->tag, - -1); - } - - if (last_path) { - gint children; - - children = gtk_tree_model_iter_n_children (model, NULL); - if (children > 0) { - GtkTreePath *path; - - if (!gtk_tree_model_get_iter_from_string (model, &last_iter, last_path)) - gtk_tree_model_iter_nth_child (model, &last_iter, NULL, children - 1); - - path = gtk_tree_model_get_path (model, &last_iter); - if (path) { - GtkTreeViewColumn *focus_col = gtk_tree_view_get_column (GTK_TREE_VIEW (prefs->label_tree), LABEL_LIST_COLUMN_NAME); - - gtk_tree_view_set_cursor (GTK_TREE_VIEW (prefs->label_tree), path, focus_col, FALSE); - gtk_tree_view_row_activated (GTK_TREE_VIEW (prefs->label_tree), path, focus_col); - gtk_tree_path_free (path); - } - } - - g_free (last_path); - } - - label_sensitive_buttons (prefs); - e_util_labels_free (labels); -} - static void jh_tree_refill (EMMailerPrefs *prefs) { - GtkListStore *store; + GtkListStore *store = prefs->junk_header_list_store; GSList *l, *cjh = gconf_client_get_list (prefs->gconf, "/apps/evolution/mail/junk/custom_header", GCONF_VALUE_STRING, NULL); - store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (prefs->junk_header_tree))); gtk_list_store_clear (store); for (l = cjh; l; l = l->next) { @@ -422,126 +309,28 @@ jh_remove_cb (GtkWidget *widget, gpointer user_data) } -static gboolean -init_junk_tree (GtkTreeView *jh_tree, EMMailerPrefs *prefs) +static GtkListStore * +init_junk_tree (GtkWidget *label_tree, EMMailerPrefs *prefs) { GtkListStore *store; GtkCellRenderer *renderer; gint col; - g_return_val_if_fail (jh_tree != NULL, FALSE); - g_return_val_if_fail (prefs != NULL, FALSE); + g_return_val_if_fail (label_tree != NULL, NULL); + g_return_val_if_fail (prefs != NULL, NULL); store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING); - gtk_tree_view_set_model (GTK_TREE_VIEW (jh_tree), GTK_TREE_MODEL (store)); - g_object_unref (store); + gtk_tree_view_set_model (GTK_TREE_VIEW (label_tree), GTK_TREE_MODEL (store)); renderer = gtk_cell_renderer_text_new (); - col = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (jh_tree), -1, _("Header"), renderer, "text", JH_LIST_COLUMN_NAME, NULL); + col = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (label_tree), -1, _("Header"), renderer, "text", JH_LIST_COLUMN_NAME, NULL); g_object_set (G_OBJECT (renderer), "editable", TRUE, NULL); renderer = gtk_cell_renderer_text_new (); - gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (jh_tree), -1, _("Contains Value"), renderer, "text", JH_LIST_COLUMN_VALUE, NULL); + gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (label_tree), -1, _("Contains Value"), renderer, "text", JH_LIST_COLUMN_VALUE, NULL); g_object_set (G_OBJECT (renderer), "editable", TRUE, NULL); - jh_tree_refill (prefs); - - return TRUE; -} - -static gboolean -init_label_tree (GtkWidget *label_tree, EMMailerPrefs *prefs, gboolean locked) -{ - GtkListStore *store; - GtkCellRenderer *renderer; - gint col; - - g_return_val_if_fail (label_tree != NULL, FALSE); - g_return_val_if_fail (prefs != NULL, FALSE); - - store = gtk_list_store_new (3, GDK_TYPE_COLOR, G_TYPE_STRING, G_TYPE_STRING); - gtk_tree_view_set_model (GTK_TREE_VIEW (label_tree), GTK_TREE_MODEL (store)); - g_object_unref (store); - - renderer = e_cell_renderer_color_new (); - gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (label_tree), -1, _("Color"), renderer, "color", LABEL_LIST_COLUMN_COLOR, NULL); - - renderer = gtk_cell_renderer_text_new (); - col = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (label_tree), -1, _("Tag"), renderer, "text", LABEL_LIST_COLUMN_TAG, NULL); - g_object_set (G_OBJECT (renderer), "editable", FALSE, NULL); - gtk_tree_view_column_set_visible (gtk_tree_view_get_column (GTK_TREE_VIEW (label_tree), col - 1), FALSE); - - renderer = gtk_cell_renderer_text_new (); - gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (label_tree), -1, _("Name"), renderer, "text", LABEL_LIST_COLUMN_NAME, NULL); - g_object_set (G_OBJECT (renderer), "editable", FALSE, NULL); - - if (!locked) - g_signal_connect (label_tree, "cursor-changed", G_CALLBACK (label_tree_cursor_changed), prefs); - - label_tree_refill (NULL, 0, NULL, prefs); - - prefs->labels_change_notify_id = gconf_client_notify_add (prefs->gconf, E_UTIL_LABELS_GCONF_KEY, label_tree_refill, prefs, NULL, NULL); - - return TRUE; -} - -static void -label_add_cb (GtkWidget *widget, gpointer user_data) -{ - char *tag; - - tag = e_util_labels_add_with_dlg (GTK_WINDOW (gtk_widget_get_toplevel (widget)), NULL); - - g_free (tag); -} - -static void -label_remove_cb (GtkWidget *widget, gpointer user_data) -{ - EMMailerPrefs *prefs = user_data; - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - - g_return_if_fail (prefs != NULL); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prefs->label_tree)); - if (gtk_tree_selection_get_selected (selection, &model, &iter)) { - gchar *tag = NULL; - - gtk_tree_model_get (model, &iter, LABEL_LIST_COLUMN_TAG, &tag, -1); - - if (tag && !e_util_labels_is_system (tag)) - e_util_labels_remove (tag); - - g_free (tag); - } -} - -static void -label_edit_cb (GtkWidget *widget, gpointer user_data) -{ - EMMailerPrefs *prefs = user_data; - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - - g_return_if_fail (prefs != NULL); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prefs->label_tree)); - if (gtk_tree_selection_get_selected (selection, &model, &iter)) { - gchar *tag = NULL; - - gtk_tree_model_get (model, &iter, LABEL_LIST_COLUMN_TAG, &tag, -1); - - if (tag) { - char *str = e_util_labels_add_with_dlg (GTK_WINDOW (gtk_widget_get_toplevel (widget)), tag); - - g_free (str); - } - - g_free (tag); - } + return store; } static void @@ -726,80 +515,6 @@ emmp_header_entry_changed (GtkWidget *entry, gpointer user_data) } static void -mark_seen_timeout_changed (GtkSpinButton *spin, EMMailerPrefs *prefs) -{ - int timeout; - - timeout = (int) (gtk_spin_button_get_value (prefs->timeout) * 1000.0); - gconf_client_set_int (prefs->gconf, "/apps/evolution/mail/display/mark_seen_timeout", timeout, NULL); -} - -static void -address_compress_count_changed (GtkSpinButton *spin, EMMailerPrefs *prefs) -{ - int count; - - count = (int) gtk_spin_button_get_value (prefs->address_count); - - gconf_client_set_int (prefs->gconf, "/apps/evolution/mail/display/address_count", count, NULL); -} - -static void -mlimit_count_changed (GtkSpinButton *spin, EMMailerPrefs *prefs) -{ - int count; - - count = (int) gtk_spin_button_get_value (prefs->mlimit_count); - - gconf_client_set_int (prefs->gconf, "/apps/evolution/mail/display/message_text_part_limit", count, NULL); -} - -static void -spin_button_init (EMMailerPrefs *prefs, GtkSpinButton *spin, const char *key, float div, GCallback value_changed) -{ - GError *err = NULL; - double min, max; - char *mkey, *p; - int val; - - gtk_spin_button_get_range (spin, &min, &max); - - mkey = g_alloca (strlen (key) + 5); - p = g_stpcpy (mkey, key); - *p++ = '_'; - - /* see if the admin locked down the min value */ - strcpy (p, "min"); - val = gconf_client_get_int (prefs->gconf, mkey, &err); - if (err == NULL) - g_clear_error (&err); - else - min = (1.0 * val) / div; - - /* see if the admin locked down the max value */ - strcpy (p, "max"); - val = gconf_client_get_int (prefs->gconf, mkey, &err); - if (err == NULL) - g_clear_error (&err); - else - max = (1.0 * val) / div; - - gtk_spin_button_set_range (spin, min, max); - - /* get the value */ - val = gconf_client_get_int (prefs->gconf, key, NULL); - gtk_spin_button_set_value (spin, (1.0 * val) / div); - - if (value_changed) { - g_object_set_data ((GObject *) spin, "key", (void *) key); - g_signal_connect (spin, "value-changed", value_changed, prefs); - } - - if (!gconf_client_key_is_writable (prefs->gconf, key, NULL)) - gtk_widget_set_sensitive ((GtkWidget *) spin, FALSE); -} - -static void toggle_button_toggled (GtkToggleButton *toggle, EMMailerPrefs *prefs) { const char *key; @@ -809,16 +524,6 @@ toggle_button_toggled (GtkToggleButton *toggle, EMMailerPrefs *prefs) } static void -photo_toggle_changed (GtkToggleButton *toggle, EMMailerPrefs *prefs) -{ - toggle_button_toggled (toggle, prefs); - if (gtk_toggle_button_get_active (toggle)) - gtk_widget_set_sensitive ((GtkWidget *) prefs->photo_local, TRUE); - else - gtk_widget_set_sensitive ((GtkWidget *) prefs->photo_local, FALSE); -} - -static void junk_book_lookup_button_toggled (GtkToggleButton *toggle, EMMailerPrefs *prefs) { toggle_button_toggled (toggle, prefs); @@ -842,42 +547,6 @@ custom_junk_button_toggled (GtkToggleButton *toggle, EMMailerPrefs *prefs) } -#if 0 -// not used at the moment, commenting out -static void -toggle_button_toggled_not (GtkToggleButton *toggle, EMMailerPrefs *prefs) -{ - const char *key; - - key = g_object_get_data ((GObject *) toggle, "key"); - gconf_client_set_bool (prefs->gconf, key, !gtk_toggle_button_get_active (toggle), NULL); -} -#endif - -static void -custom_font_changed (GtkToggleButton *toggle, EMMailerPrefs *prefs) -{ - gboolean use_custom; - - use_custom = !gtk_toggle_button_get_active (toggle); - - gtk_widget_set_sensitive (GTK_WIDGET (prefs->font_fixed), use_custom); - gtk_widget_set_sensitive (GTK_WIDGET (prefs->font_variable), use_custom); - - gconf_client_set_bool (prefs->gconf, "/apps/evolution/mail/display/fonts/use_custom", use_custom, NULL); -} - -static void -font_changed (GtkFontButton *font_button, EMMailerPrefs *prefs) -{ - const gchar *key; - const gchar *font_name; - - key = g_object_get_data (G_OBJECT (font_button), "key"); - font_name = gtk_font_button_get_font_name (font_button); - gconf_client_set_string (prefs->gconf, key, font_name, NULL); -} - static void toggle_button_init (EMMailerPrefs *prefs, GtkToggleButton *toggle, int not, const char *key, GCallback toggled) { @@ -933,74 +602,78 @@ charset_menu_init (EMMailerPrefs *prefs) } static void -trash_days_changed (GtkComboBox *combobox, EMMailerPrefs *prefs) +trash_days_activate (GtkWidget *item, EMMailerPrefs *prefs) { - int idx; - - idx = gtk_combo_box_get_active (combobox); - g_return_if_fail (idx >= 0 && idx < G_N_ELEMENTS (empty_trash_frequency)); + int days; - gconf_client_set_int (prefs->gconf, "/apps/evolution/mail/trash/empty_on_exit_days", empty_trash_frequency [idx].days, NULL); + days = GPOINTER_TO_INT (g_object_get_data ((GObject *) item, "days")); + gconf_client_set_int (prefs->gconf, "/apps/evolution/mail/trash/empty_on_exit_days", days, NULL); } static void emmp_empty_trash_init (EMMailerPrefs *prefs) { int locked, days, hist = 0, i; - - toggle_button_init (prefs, prefs->empty_trash, FALSE, - "/apps/evolution/mail/trash/empty_on_exit", - G_CALLBACK (toggle_button_toggled)); + GtkWidget *menu, *item; days = gconf_client_get_int(prefs->gconf, "/apps/evolution/mail/trash/empty_on_exit_days", NULL); - - gtk_list_store_clear (GTK_LIST_STORE (gtk_combo_box_get_model (prefs->empty_trash_days))); + menu = gtk_menu_new(); for (i = 0; i < G_N_ELEMENTS (empty_trash_frequency); i++) { if (days >= empty_trash_frequency[i].days) hist = i; - gtk_combo_box_append_text (prefs->empty_trash_days, _(empty_trash_frequency[i].label)); + item = gtk_menu_item_new_with_label (_(empty_trash_frequency[i].label)); + g_object_set_data ((GObject *) item, "days", GINT_TO_POINTER (empty_trash_frequency[i].days)); + g_signal_connect (item, "activate", G_CALLBACK (trash_days_activate), prefs); + + gtk_widget_show (item); + gtk_menu_shell_append((GtkMenuShell *)menu, item); } - g_signal_connect (prefs->empty_trash_days, "changed", G_CALLBACK (trash_days_changed), prefs); - gtk_combo_box_set_active (prefs->empty_trash_days, hist); + gtk_widget_show(menu); + gtk_option_menu_set_menu((GtkOptionMenu *)prefs->empty_trash_days, menu); + gtk_option_menu_set_history((GtkOptionMenu *)prefs->empty_trash_days, hist); locked = !gconf_client_key_is_writable (prefs->gconf, "/apps/evolution/mail/trash/empty_on_exit_days", NULL); gtk_widget_set_sensitive ((GtkWidget *) prefs->empty_trash_days, !locked); } static void -junk_days_changed (GtkComboBox *combobox, EMMailerPrefs *prefs) +junk_days_activate (GtkWidget *item, EMMailerPrefs *prefs) { - int idx; - - idx = gtk_combo_box_get_active (combobox); - g_return_if_fail (idx >= 0 && idx < G_N_ELEMENTS (empty_trash_frequency)); + int days; - gconf_client_set_int (prefs->gconf, "/apps/evolution/mail/junk/empty_on_exit_days", empty_trash_frequency[idx].days, NULL); + days = GPOINTER_TO_INT (g_object_get_data ((GObject *) item, "days")); + gconf_client_set_int (prefs->gconf, "/apps/evolution/mail/junk/empty_on_exit_days", days, NULL); } static void emmp_empty_junk_init (EMMailerPrefs *prefs) { int locked, days, hist = 0, i; + GtkWidget *menu, *item; toggle_button_init (prefs, prefs->empty_junk, FALSE, "/apps/evolution/mail/junk/empty_on_exit", G_CALLBACK (toggle_button_toggled)); days = gconf_client_get_int(prefs->gconf, "/apps/evolution/mail/junk/empty_on_exit_days", NULL); - - gtk_list_store_clear (GTK_LIST_STORE (gtk_combo_box_get_model (prefs->empty_junk_days))); + menu = gtk_menu_new(); for (i = 0; i < G_N_ELEMENTS (empty_trash_frequency); i++) { if (days >= empty_trash_frequency[i].days) hist = i; - gtk_combo_box_append_text (prefs->empty_junk_days, _(empty_trash_frequency[i].label)); + item = gtk_menu_item_new_with_label (_(empty_trash_frequency[i].label)); + g_object_set_data ((GObject *) item, "days", GINT_TO_POINTER (empty_trash_frequency[i].days)); + g_signal_connect (item, "activate", G_CALLBACK (junk_days_activate), prefs); + + gtk_widget_show (item); + gtk_menu_shell_append((GtkMenuShell *)menu, item); } - g_signal_connect (prefs->empty_junk_days, "changed", G_CALLBACK (junk_days_changed), prefs); - gtk_combo_box_set_active (prefs->empty_junk_days, hist); + gtk_widget_show(menu); + gtk_option_menu_set_menu((GtkOptionMenu *)prefs->empty_junk_days, menu); + gtk_option_menu_set_history((GtkOptionMenu *)prefs->empty_junk_days, hist); locked = !gconf_client_key_is_writable (prefs->gconf, "/apps/evolution/mail/junk/empty_on_exit_days", NULL); gtk_widget_set_sensitive ((GtkWidget *) prefs->empty_junk_days, !locked); @@ -1160,15 +833,18 @@ create_combo_text_widget (void) { } static void -em_mailer_prefs_construct (EMMailerPrefs *prefs) +em_mailer_prefs_construct (EMMailerPrefs *prefs, + EShell *shell) { GSList *header_config_list, *header_add_list, *p; + EShellSettings *shell_settings; GHashTable *default_header_hash; GtkWidget *toplevel; + GtkWidget *container; + GtkWidget *widget; GtkTreeSelection *selection; GtkCellRenderer *renderer; GtkTreeIter iter; - char *font, *buf; GladeXML *gui; gboolean locked; int val, i; @@ -1177,6 +853,8 @@ em_mailer_prefs_construct (EMMailerPrefs *prefs) GSList *l; char *gladefile; + shell_settings = e_shell_get_shell_settings (shell); + gladefile = g_build_filename (EVOLUTION_GLADEDIR, "mail-config.glade", NULL); @@ -1202,96 +880,119 @@ em_mailer_prefs_construct (EMMailerPrefs *prefs) /* General tab */ /* Message Display */ - prefs->timeout_toggle = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "chkMarkTimeout")); - toggle_button_init (prefs, prefs->timeout_toggle, FALSE, - "/apps/evolution/mail/display/mark_seen", - G_CALLBACK (toggle_button_toggled)); - - prefs->timeout = GTK_SPIN_BUTTON (glade_xml_get_widget (gui, "spinMarkTimeout")); - spin_button_init (prefs, prefs->timeout, - "/apps/evolution/mail/display/mark_seen_timeout", - 1000.0, G_CALLBACK (mark_seen_timeout_changed)); - - prefs->mlimit_toggle = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "mlimit_checkbutton")); - toggle_button_init (prefs, prefs->mlimit_toggle, FALSE, - "/apps/evolution/mail/display/force_message_limit", - G_CALLBACK (toggle_button_toggled)); - - prefs->magic_spacebar = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "magic_spacebar_checkbox")); - toggle_button_init (prefs, prefs->magic_spacebar, FALSE, - "/apps/evolution/mail/display/magic_spacebar", - G_CALLBACK (toggle_button_toggled)); - - prefs->mlimit_count = GTK_SPIN_BUTTON (glade_xml_get_widget (gui, "mlimit_spin")); - spin_button_init (prefs, prefs->mlimit_count, - "/apps/evolution/mail/display/message_text_part_limit", - 1, G_CALLBACK (mlimit_count_changed)); - - prefs->address_toggle = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "address_checkbox")); - toggle_button_init (prefs, prefs->address_toggle, FALSE, - "/apps/evolution/mail/display/address_compress", - G_CALLBACK (toggle_button_toggled)); - - prefs->address_count = GTK_SPIN_BUTTON (glade_xml_get_widget (gui, "address_spin")); - spin_button_init (prefs, prefs->address_count, - "/apps/evolution/mail/display/address_count", - 1, G_CALLBACK (address_compress_count_changed)); + widget = glade_xml_get_widget (gui, "chkMarkTimeout"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-mark-seen", + G_OBJECT (widget), "active"); + + /* The "mark seen" timeout requires special transform functions + * because we display the timeout value to the user in seconds + * but store the settings value in milliseconds. */ + widget = glade_xml_get_widget (gui, "spinMarkTimeout"); + prefs->timeout = GTK_SPIN_BUTTON (widget); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-mark-seen", + G_OBJECT (widget), "sensitive"); + e_mutual_binding_new_full ( + G_OBJECT (shell_settings), "mail-mark-seen-timeout", + G_OBJECT (widget), "value", + mark_seen_timeout_transform, + mark_seen_timeout_reverse_transform, + NULL, NULL); + + widget = glade_xml_get_widget (gui, "mlimit_checkbutton"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-force-message-limit", + G_OBJECT (widget), "active"); + + widget = glade_xml_get_widget (gui, "mlimit_spin"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-force-message-limit", + G_OBJECT (widget), "sensitive"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-message-text-part-limit", + G_OBJECT (widget), "value"); + + widget = glade_xml_get_widget (gui, "address_checkbox"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-address-compress", + G_OBJECT (widget), "active"); + + widget = glade_xml_get_widget (gui, "address_spin"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-address-compress", + G_OBJECT (widget), "sensitive"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-address-count", + G_OBJECT (widget), "value"); + + widget = glade_xml_get_widget (gui, "magic_spacebar_checkbox"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-magic-spacebar", + G_OBJECT (widget), "active"); prefs->charset = GTK_OPTION_MENU (glade_xml_get_widget (gui, "omenuCharset")); charset_menu_init (prefs); - prefs->citation_highlight = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "chkHighlightCitations")); - toggle_button_init (prefs, prefs->citation_highlight, FALSE, - "/apps/evolution/mail/display/mark_citations", - G_CALLBACK (toggle_button_toggled)); - - prefs->citation_color = GTK_COLOR_BUTTON (glade_xml_get_widget (gui, "colorButtonHighlightCitations")); - buf = gconf_client_get_string (prefs->gconf, "/apps/evolution/mail/display/citation_colour", NULL); - color_button_set_color (prefs->citation_color, buf ? buf : "#737373"); - g_signal_connect (prefs->citation_color, "color-set", G_CALLBACK (citation_color_set), prefs); - if (!gconf_client_key_is_writable (prefs->gconf, "/apps/evolution/mail/display/citation_colour", NULL)) - gtk_widget_set_sensitive ((GtkWidget *) prefs->citation_color, FALSE); - g_free (buf); - - prefs->enable_search_folders = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "chkEnableSearchFolders")); - toggle_button_init (prefs, prefs->enable_search_folders, FALSE, - "/apps/evolution/mail/display/enable_vfolders", - G_CALLBACK (toggle_button_toggled)); + widget = glade_xml_get_widget (gui, "chkHighlightCitations"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-mark-citations", + G_OBJECT (widget), "active"); + + widget = glade_xml_get_widget (gui, "colorButtonHighlightCitations"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-mark-citations", + G_OBJECT (widget), "sensitive"); + e_mutual_binding_new_full ( + G_OBJECT (shell_settings), "mail-citation-color", + G_OBJECT (widget), "color", + e_binding_transform_string_to_color, + e_binding_transform_color_to_string, + NULL, NULL); + + widget = glade_xml_get_widget (gui, "chkEnableSearchFolders"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-enable-search-folders", + G_OBJECT (widget), "active"); /* Deleting Mail */ - prefs->empty_trash = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "chkEmptyTrashOnExit")); - prefs->empty_trash_days = GTK_COMBO_BOX (glade_xml_get_widget (gui, "comboboxEmptyTrashDays")); + widget = glade_xml_get_widget (gui, "chkEmptyTrashOnExit"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-empty-trash-on-exit", + G_OBJECT (widget), "active"); + + prefs->empty_trash_days = GTK_OPTION_MENU (glade_xml_get_widget (gui, "omenuEmptyTrashDays")); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-empty-trash-on-exit", + G_OBJECT (prefs->empty_trash_days), "sensitive"); emmp_empty_trash_init (prefs); - prefs->confirm_expunge = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "chkConfirmExpunge")); - toggle_button_init (prefs, prefs->confirm_expunge, FALSE, - "/apps/evolution/mail/prompts/expunge", - G_CALLBACK (toggle_button_toggled)); - - /* Mail Fonts */ - font = gconf_client_get_string (prefs->gconf, "/apps/evolution/mail/display/fonts/monospace", NULL); - prefs->font_fixed = GTK_FONT_BUTTON (glade_xml_get_widget (gui, "FontFixed")); - gtk_font_button_set_font_name (prefs->font_fixed, font); - g_free (font); - g_object_set_data ((GObject *) prefs->font_fixed, "key", "/apps/evolution/mail/display/fonts/monospace"); - g_signal_connect (prefs->font_fixed, "font-set", G_CALLBACK (font_changed), prefs); - if (!gconf_client_key_is_writable (prefs->gconf, "/apps/evolution/mail/display/fonts/monospace", NULL)) - gtk_widget_set_sensitive ((GtkWidget *) prefs->font_fixed, FALSE); - - font = gconf_client_get_string (prefs->gconf, "/apps/evolution/mail/display/fonts/variable", NULL); - prefs->font_variable = GTK_FONT_BUTTON (glade_xml_get_widget (gui, "FontVariable")); - gtk_font_button_set_font_name (prefs->font_variable, font); - g_free (font); - g_object_set_data ((GObject *) prefs->font_variable, "key", "/apps/evolution/mail/display/fonts/variable"); - g_signal_connect (prefs->font_variable, "font-set", G_CALLBACK (font_changed), prefs); - if (!gconf_client_key_is_writable (prefs->gconf, "/apps/evolution/mail/display/fonts/variable", NULL)) - gtk_widget_set_sensitive ((GtkWidget *) prefs->font_variable, FALSE); - - prefs->font_share = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "radFontUseSame")); - toggle_button_init (prefs, prefs->font_share, TRUE, - "/apps/evolution/mail/display/fonts/use_custom", - G_CALLBACK (custom_font_changed)); - custom_font_changed (prefs->font_share, prefs); + widget = glade_xml_get_widget (gui, "chkConfirmExpunge"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-confirm-expunge", + G_OBJECT (widget), "active"); + + /* Mail Fonts */ + widget = glade_xml_get_widget (gui, "radFontUseSame"); + e_mutual_binding_new_with_negation ( + G_OBJECT (shell_settings), "mail-use-custom-fonts", + G_OBJECT (widget), "active"); + + widget = glade_xml_get_widget (gui, "FontFixed"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-font-monospace", + G_OBJECT (widget), "font-name"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-use-custom-fonts", + G_OBJECT (widget), "sensitive"); + + widget = glade_xml_get_widget (gui, "FontVariable"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-font-variable", + G_OBJECT (widget), "font-name"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-use-custom-fonts", + G_OBJECT (widget), "sensitive"); /* HTML Mail tab */ @@ -1318,49 +1019,40 @@ em_mailer_prefs_construct (EMMailerPrefs *prefs) g_signal_connect (prefs->images_sometimes, "toggled", G_CALLBACK (http_images_changed), prefs); g_signal_connect (prefs->images_always, "toggled", G_CALLBACK (http_images_changed), prefs); - prefs->show_animated = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "chkShowAnimatedImages")); - toggle_button_init (prefs, prefs->show_animated, FALSE, - "/apps/evolution/mail/display/animate_images", - G_CALLBACK (toggle_button_toggled)); - - prefs->prompt_unwanted_html = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "chkPromptWantHTML")); - toggle_button_init (prefs, prefs->prompt_unwanted_html, FALSE, - "/apps/evolution/mail/prompts/unwanted_html", - G_CALLBACK (toggle_button_toggled)); - - /* Labels... */ - locked = !gconf_client_key_is_writable (prefs->gconf, E_UTIL_LABELS_GCONF_KEY, NULL); - prefs->label_add = glade_xml_get_widget (gui, "labelAdd"); - prefs->label_edit = glade_xml_get_widget (gui, "labelEdit"); - prefs->label_remove = glade_xml_get_widget (gui, "labelRemove"); - prefs->label_tree = glade_xml_get_widget (gui, "labelTree"); + widget = glade_xml_get_widget (gui, "chkShowAnimatedImages"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-show-animated-images", + G_OBJECT (widget), "active"); - gtk_widget_set_sensitive (prefs->label_add, !locked); - gtk_widget_set_sensitive (prefs->label_remove, !locked); - gtk_widget_set_sensitive (prefs->label_edit, !locked); - gtk_widget_set_sensitive (prefs->label_tree, !locked); + widget = glade_xml_get_widget (gui, "chkPromptWantHTML"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-confirm-unwanted-html", + G_OBJECT (widget), "active"); - init_label_tree (prefs->label_tree, prefs, locked); + container = glade_xml_get_widget (gui, "labels-alignment"); + widget = e_mail_label_manager_new (); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); - if (!locked) { - g_signal_connect (G_OBJECT (prefs->label_add), "clicked", G_CALLBACK (label_add_cb), prefs); - g_signal_connect (G_OBJECT (prefs->label_remove), "clicked", G_CALLBACK (label_remove_cb), prefs); - g_signal_connect (G_OBJECT (prefs->label_edit), "clicked", G_CALLBACK (label_edit_cb), prefs); - } + e_binding_new ( + G_OBJECT (shell_settings), "mail-label-list-store", + G_OBJECT (widget), "list-store"); /* headers */ locked = !gconf_client_key_is_writable (prefs->gconf, "/apps/evolution/mail/display/headers", NULL); - prefs->photo_show= GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "photo_show")); - toggle_button_init (prefs, prefs->photo_show, FALSE, - "/apps/evolution/mail/display/sender_photo", - G_CALLBACK (photo_toggle_changed)); - prefs->photo_local = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "photo_local")); - toggle_button_init (prefs, prefs->photo_local, FALSE, - "/apps/evolution/mail/display/photo_local", - G_CALLBACK (toggle_button_toggled)); - if (!gtk_toggle_button_get_active (prefs->photo_show)) - gtk_widget_set_sensitive ((GtkWidget *) prefs->photo_local, FALSE); + widget = glade_xml_get_widget (gui, "photo_show"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-show-sender-photo", + G_OBJECT (widget), "active"); + + widget = glade_xml_get_widget (gui, "photo_local"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-show-sender-photo", + G_OBJECT (widget), "sensitive"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-only-local-photos", + G_OBJECT (widget), "active"); /* always de-sensitised until the user types something in the entry */ prefs->add_header = GTK_BUTTON (glade_xml_get_widget (gui, "cmdHeadersAdd")); @@ -1467,13 +1159,13 @@ em_mailer_prefs_construct (EMMailerPrefs *prefs) g_slist_free (header_add_list); /* Junk prefs */ - prefs->check_incoming = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "chkCheckIncomingMail")); - toggle_button_init (prefs, prefs->check_incoming, FALSE, - "/apps/evolution/mail/junk/check_incoming", - G_CALLBACK (toggle_button_toggled)); + widget = glade_xml_get_widget (gui, "chkCheckIncomingMail"); + e_mutual_binding_new ( + G_OBJECT (shell_settings), "mail-check-for-junk", + G_OBJECT (widget), "active"); prefs->empty_junk = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "junk_empty_check")); - prefs->empty_junk_days = GTK_COMBO_BOX (glade_xml_get_widget (gui, "junk_empty_combobox")); + prefs->empty_junk_days = GTK_OPTION_MENU (glade_xml_get_widget (gui, "junk_empty_combo")); emmp_empty_junk_init (prefs); prefs->default_junk_plugin = GTK_COMBO_BOX (glade_xml_get_widget (gui, "default_junk_plugin")); @@ -1497,7 +1189,7 @@ em_mailer_prefs_construct (EMMailerPrefs *prefs) junk_book_lookup_button_toggled (prefs->junk_book_lookup, prefs); - init_junk_tree ((GtkTreeView *)prefs->junk_header_tree, prefs); + prefs->junk_header_list_store = init_junk_tree ((GtkWidget *)prefs->junk_header_tree, prefs); toggle_button_init (prefs, prefs->junk_header_check, FALSE, "/apps/evolution/mail/junk/check_custom_header", G_CALLBACK (custom_junk_button_toggled)); @@ -1515,14 +1207,18 @@ em_mailer_prefs_construct (EMMailerPrefs *prefs) } GtkWidget * -em_mailer_prefs_new (void) +em_mailer_prefs_new (EShell *shell) { EMMailerPrefs *new; - new = (EMMailerPrefs *) g_object_new (em_mailer_prefs_get_type (), NULL); - em_mailer_prefs_construct (new); + g_return_val_if_fail (E_IS_SHELL (shell), NULL); + + new = g_object_new (EM_TYPE_MAILER_PREFS, NULL); + + /* FIXME Kill this function. */ + em_mailer_prefs_construct (new, shell); - return (GtkWidget *) new; + return GTK_WIDGET (new); } diff --git a/mail/em-mailer-prefs.h b/mail/em-mailer-prefs.h index 3b52d9f40a..c7dc6ac80a 100644 --- a/mail/em-mailer-prefs.h +++ b/mail/em-mailer-prefs.h @@ -20,36 +20,34 @@ * */ -#ifndef __EM_MAILER_PREFS_H__ -#define __EM_MAILER_PREFS_H__ - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ +#ifndef EM_MAILER_PREFS_H +#define EM_MAILER_PREFS_H #include <gtk/gtk.h> -#include <shell/Evolution.h> - -struct _ESignature; -struct _GtkToggleButton; -struct _GtkOptionMenu; -struct _GtkComboBox; -struct _GdkPixbuf; -struct _GtkWidget; -struct _GladeXML; -struct _GtkFileChooserbutton; -struct _GtkFontButton; -struct _GConfClient; -struct _GtkButton; -struct _GtkTreeView; -struct _GtkWindow; - -#define EM_MAILER_PREFS_TYPE (em_mailer_prefs_get_type ()) -#define EM_MAILER_PREFS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EM_MAILER_PREFS_TYPE, EMMailerPrefs)) -#define EM_MAILER_PREFS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), EM_MAILER_PREFS_TYPE, EMMailerPrefsClass)) -#define EM_IS_MAILER_PREFS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EM_MAILER_PREFS_TYPE)) -#define EM_IS_MAILER_PREFS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EM_MAILER_PREFS_TYPE)) +#include <glade/glade.h> +#include <gconf/gconf-client.h> +#include <shell/e-shell.h> + +/* Standard GObject macros */ +#define EM_TYPE_MAILER_PREFS \ + (em_mailer_prefs_get_type ()) +#define EM_MAILER_PREFS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), EM_TYPE_MAILER_PREFS, EMMailerPrefs)) +#define EM_MAILER_PREFS_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), EM_TYPE_MAILER_PREFS, EMMailerPrefsClass)) +#define EM_IS_MAILER_PREFS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), EM_TYPE_MAILER_PREFS)) +#define EM_IS_MAILER_PREFS_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), EM_TYPE_MAILER_PREFS)) +#define EM_MAILER_PREFS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), EM_TYPE_MAILER_PREFS)) + +G_BEGIN_DECLS typedef struct _EMMailerPrefs EMMailerPrefs; typedef struct _EMMailerPrefsClass EMMailerPrefsClass; @@ -64,25 +62,14 @@ struct _EMMailerPrefsHeader { struct _EMMailerPrefs { GtkVBox parent_object; - GNOME_Evolution_Shell shell; - - struct _GladeXML *gui; - struct _GConfClient *gconf; + GladeXML *gui; + GConfClient *gconf; /* General tab */ /* Message Display */ - struct _GtkToggleButton *timeout_toggle; - struct _GtkSpinButton *timeout; - struct _GtkToggleButton *address_toggle; - struct _GtkSpinButton *address_count; - struct _GtkToggleButton *mlimit_toggle; - struct _GtkSpinButton *mlimit_count; - struct _GtkOptionMenu *charset; - struct _GtkToggleButton *citation_highlight; - struct _GtkColorButton *citation_color; - struct _GtkToggleButton *enable_search_folders; - struct _GtkToggleButton *magic_spacebar; + GtkSpinButton *timeout; + GtkOptionMenu *charset; /* Deleting Mail */ struct _GtkToggleButton *empty_trash; @@ -90,75 +77,65 @@ struct _EMMailerPrefs { struct _GtkToggleButton *confirm_expunge; /* HTML Mail tab */ - struct _GtkFontButton *font_variable; - struct _GtkFontButton *font_fixed; - struct _GtkToggleButton *font_share; + GtkFontButton *font_variable; + GtkFontButton *font_fixed; + GtkToggleButton *font_share; /* Loading Images */ - struct _GtkToggleButton *images_always; - struct _GtkToggleButton *images_sometimes; - struct _GtkToggleButton *images_never; + GtkToggleButton *images_always; + GtkToggleButton *images_sometimes; + GtkToggleButton *images_never; - struct _GtkToggleButton *show_animated; - struct _GtkToggleButton *autodetect_links; - struct _GtkToggleButton *prompt_unwanted_html; + GtkToggleButton *autodetect_links; /* Labels and Colours tab */ - struct _GtkWidget *label_add; - struct _GtkWidget *label_edit; - struct _GtkWidget *label_remove; - struct _GtkWidget *label_tree; + GtkWidget *label_add; + GtkWidget *label_edit; + GtkWidget *label_remove; + GtkWidget *label_tree; + GtkListStore *label_list_store; guint labels_change_notify_id; /* mail_config's notify id */ /* Headers tab */ - struct _GtkButton *add_header; - struct _GtkButton *remove_header; - struct _GtkEntry *entry_header; - struct _GtkTreeView *header_list; - struct _GtkListStore *header_list_store; - struct _GtkToggleButton *photo_show; - struct _GtkToggleButton *photo_local; + GtkButton *add_header; + GtkButton *remove_header; + GtkEntry *entry_header; + GtkTreeView *header_list; + GtkListStore *header_list_store; /* Junk prefs */ - struct _GtkToggleButton *check_incoming; - struct _GtkToggleButton *empty_junk; - struct _GtkComboBox *empty_junk_days; + GtkToggleButton *empty_junk; + GtkComboBox *empty_junk_days; - struct _GtkToggleButton *sa_local_tests_only; - struct _GtkToggleButton *sa_use_daemon; - struct _GtkComboBox *default_junk_plugin; - struct _GtkLabel *plugin_status; - struct _GtkImage *plugin_image; - - struct _GtkToggleButton *junk_header_check; - struct _GtkTreeView *junk_header_tree; - struct _GtkButton *junk_header_add; - struct _GtkButton *junk_header_remove; - struct _GtkToggleButton *junk_book_lookup; - struct _GtkToggleButton *junk_lookup_local_only; + GtkToggleButton *sa_local_tests_only; + GtkToggleButton *sa_use_daemon; + GtkComboBox *default_junk_plugin; + GtkLabel *plugin_status; + GtkImage *plugin_image; + + GtkToggleButton *junk_header_check; + GtkTreeView *junk_header_tree; + GtkListStore *junk_header_list_store; + GtkButton *junk_header_add; + GtkButton *junk_header_remove; + GtkToggleButton *junk_book_lookup; + GtkToggleButton *junk_lookup_local_only; }; struct _EMMailerPrefsClass { GtkVBoxClass parent_class; - - /* signals */ - }; -GType em_mailer_prefs_get_type (void); -GtkWidget * create_combo_text_widget (void); - -struct _GtkWidget *em_mailer_prefs_new (void); +GType em_mailer_prefs_get_type (void); +GtkWidget * create_combo_text_widget (void); -EMMailerPrefsHeader *em_mailer_prefs_header_from_xml(const char *xml); -char *em_mailer_prefs_header_to_xml(EMMailerPrefsHeader *header); -void em_mailer_prefs_header_free(EMMailerPrefsHeader *header); +GtkWidget * em_mailer_prefs_new (EShell *shell); -/* needed by global config */ -#define EM_MAILER_PREFS_CONTROL_ID "OAFIID:GNOME_Evolution_Mail_MailerPrefs_ConfigControl:" BASE_VERSION +EMMailerPrefsHeader * + em_mailer_prefs_header_from_xml (const gchar *xml); +gchar * em_mailer_prefs_header_to_xml (EMMailerPrefsHeader *header); +void em_mailer_prefs_header_free (EMMailerPrefsHeader *header); -#ifdef __cplusplus -} -#endif /* __cplusplus */ +G_END_DECLS -#endif /* __EM_MAILER_PREFS_H__ */ +#endif /* EM_MAILER_PREFS_H */ diff --git a/mail/em-message-browser.c b/mail/em-message-browser.c deleted file mode 100644 index 728b27ec43..0000000000 --- a/mail/em-message-browser.c +++ /dev/null @@ -1,399 +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: - * Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <glib.h> -#ifdef G_OS_WIN32 -/* Work around 'DATADIR' and 'interface' lossage in <windows.h> */ -#define DATADIR crap_DATADIR -#include <windows.h> -#undef DATADIR -#undef interface -#endif - -#include <gdk/gdkkeysyms.h> - -#include <gconf/gconf-client.h> - -#include <camel/camel-folder.h> - -#include <bonobo/bonobo-main.h> -#include <bonobo/bonobo-object.h> -#include <bonobo/bonobo-window.h> -#include <bonobo/bonobo-generic-factory.h> -#include <bonobo/bonobo-ui-component.h> -#include <bonobo/bonobo-ui-util.h> - -#include "e-util/e-util-private.h" - -#include "em-format-html-display.h" -#include "em-message-browser.h" -#include "em-menu.h" - -#include "evolution-shell-component-utils.h" /* Pixmap stuff, sigh */ - -#define EM_MESSAGE_BROWSER_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), EM_TYPE_MESSAGE_BROWSER, EMMessageBrowserPrivate)) - -#define DEFAULT_WIDTH 600 -#define DEFAULT_HEIGHT 400 - -struct _EMMessageBrowserPrivate { - GtkWidget *preview; /* container for message display */ -}; - -static gpointer parent_class; -static GtkAllocation window_size = { 0, 0, 0, 0 }; - -static void -emmb_close (BonoboUIComponent *uid, - gpointer data, - const gchar *path) -{ - EMMessageBrowser *emmb = data; - GtkWidget *toplevel; - - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (emmb)); - gtk_widget_destroy (toplevel); -} - -static BonoboUIVerb emmb_verbs[] = { - BONOBO_UI_UNSAFE_VERB ("MessageBrowserClose", emmb_close), - BONOBO_UI_VERB_END -}; - -static void -emmb_set_message (EMFolderView *emfv, - const gchar *uid, - gint nomarkseen) -{ - EMMessageBrowser *emmb = EM_MESSAGE_BROWSER (emfv); - EMFolderViewClass *folder_view_class; - CamelMessageInfo *info; - - /* Chain up to parent's set_message() method. */ - folder_view_class = EM_FOLDER_VIEW_CLASS (parent_class); - folder_view_class->set_message (emfv, uid, nomarkseen); - - if (uid == NULL) { - gtk_widget_destroy (GTK_WIDGET (emfv)); - return; - } - - info = camel_folder_get_message_info (emfv->folder, uid); - - if (info != NULL) { - gtk_window_set_title ( - GTK_WINDOW (emmb->window), - camel_message_info_subject (info)); - camel_folder_free_message_info (emfv->folder, info); - } - - /* Well we don't know if it got displayed (yet) ... but whatever ... */ - if (!nomarkseen) - camel_folder_set_message_flags ( - emfv->folder, uid, - CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN); -} - -static void -emmb_activate (EMFolderView *emfv, - BonoboUIComponent *uic, - gint state) -{ - EMFolderViewClass *folder_view_class; - - folder_view_class = EM_FOLDER_VIEW_CLASS (parent_class); - - if (state) { - /* Chain up to parent's activate() method. */ - folder_view_class->activate (emfv, uic, state); - - bonobo_ui_component_add_verb_list_with_data ( - uic, emmb_verbs, emfv); - bonobo_ui_component_set_prop( - uic, "/commands/EditPaste", "sensitive", "0", NULL); - } else { - const BonoboUIVerb *verb; - - for (verb = &emmb_verbs[0]; verb->cname; verb++) - bonobo_ui_component_remove_verb (uic, verb->cname); - - /* Chain up to parent's activate() method. */ - folder_view_class->activate (emfv, uic, state); - } -} - -static void -emmb_list_message_selected_cb (struct _MessageList *ml, - const gchar *uid, - EMMessageBrowser *emmb) -{ - EMFolderView *emfv = EM_FOLDER_VIEW (emmb); - CamelMessageInfo *info; - - if (uid == NULL) - return; - - info = camel_folder_get_message_info (emfv->folder, uid); - if (info == NULL) - return; - - gtk_window_set_title ( - GTK_WINDOW (emmb->window), - camel_message_info_subject (info)); - gtk_widget_grab_focus ( - GTK_WIDGET (emfv->preview->formathtml.html)); - - camel_folder_free_message_info (emfv->folder, info); -} - -static void -emmb_window_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - GConfClient *client; - - /* FIXME Have GConfBridge handle this. */ - - /* save to in-memory variable for current session access */ - window_size = *allocation; - - /* save the setting across sessions */ - client = gconf_client_get_default (); - gconf_client_set_int ( - client, "/apps/evolution/mail/message_window/width", - window_size.width, NULL); - gconf_client_set_int ( - client, "/apps/evolution/mail/message_window/height", - window_size.height, NULL); - g_object_unref (client); -} - -static int -emmb_key_press_event_cb (EMMessageBrowser *emmb, - GdkEventKey *event) -{ - if (event->keyval == GDK_Escape) { - GtkWidget *toplevel; - - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (emmb)); - gtk_widget_destroy (toplevel); - g_signal_stop_emission_by_name (emmb, "key-press-event"); - - return TRUE; - } - - return FALSE; -} - -static void -emmb_destroy (GtkObject *gtk_object) -{ - EMFolderView *emfv = EM_FOLDER_VIEW (gtk_object); - - if (emfv->list) { - gtk_widget_destroy (GTK_WIDGET (emfv->list)); - emfv->list = NULL; - } - - /* Chain up to parent's destroy() method. */ - GTK_OBJECT_CLASS (parent_class)->destroy (gtk_object); -} - -static void -emmb_class_init (EMMessageBrowserClass *class) -{ - GtkObjectClass *gtk_object_class; - EMFolderViewClass *folder_view_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (EMMessageBrowserPrivate)); - - gtk_object_class = GTK_OBJECT_CLASS (class); - gtk_object_class->destroy = emmb_destroy; - - folder_view_class = EM_FOLDER_VIEW_CLASS (class); - folder_view_class->update_message_style = FALSE; - folder_view_class->set_message = emmb_set_message; - folder_view_class->activate = emmb_activate; -} - -static void -emmb_init (EMMessageBrowser *emmb) -{ - EMFolderView *emfv = EM_FOLDER_VIEW (emmb); - GtkWidget *widget; - gchar *filename; - - emmb->priv = EM_MESSAGE_BROWSER_GET_PRIVATE (emmb); - - emfv->preview_active = TRUE; - - g_slist_foreach (emfv->ui_files, (GFunc) g_free, NULL); - g_slist_free (emfv->ui_files); - emfv->ui_files = NULL; - - filename = g_build_filename ( - EVOLUTION_UIDIR, "evolution-mail-messagedisplay.xml", NULL); - emfv->ui_files = g_slist_append (emfv->ui_files, filename); - - filename = g_build_filename ( - EVOLUTION_UIDIR, "evolution-mail-message.xml", NULL); - emfv->ui_files = g_slist_append (emfv->ui_files, filename); - - widget = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy ( - GTK_SCROLLED_WINDOW (widget), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type ( - GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); - gtk_widget_show (widget); - emmb->priv->preview = widget; - - widget = GTK_WIDGET (emfv->preview->formathtml.html); - gtk_container_add (GTK_CONTAINER (emmb->priv->preview), widget); - gtk_widget_show (widget); - - gtk_box_pack_start ( - GTK_BOX (emmb), emmb->priv->preview, TRUE, TRUE, 0); - gtk_box_pack_start( - GTK_BOX (emmb), em_format_html_get_search_dialog ( - emfv->preview), FALSE, FALSE, 0); - - /** @HookPoint-EMMenu: Standalone Message View Menu - * @Id: org.gnome.evolution.mail.messagebrowser - * @Class: org.gnome.evolution.mail.bonobomenu:1.0 - * @Target: EMMenuTargetSelect - * - * The main menu of standalone message viewer. - */ - EM_FOLDER_VIEW (emmb)->menu = - em_menu_new ("org.gnome.evolution.mail.messagebrowser"); -} - -GType -em_message_browser_get_type (void) -{ - static GType type = 0; - - if (G_UNLIKELY (type == 0)) { - static const GTypeInfo type_info = { - sizeof (EMMessageBrowserClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) emmb_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (EMMessageBrowser), - 0, /* n_preallocs */ - (GInstanceInitFunc) emmb_init, - NULL /* value_table */ - }; - - type = g_type_register_static ( - EM_TYPE_FOLDER_VIEW, "EMMessageBrowser", - &type_info, 0); - } - - return type; -} - -GtkWidget * -em_message_browser_new (void) -{ - return g_object_new (EM_TYPE_MESSAGE_BROWSER, NULL); -} - -GtkWidget * -em_message_browser_window_new (void) -{ - EMMessageBrowser *emmb; - BonoboUIContainer *uicont; - BonoboUIComponent *uic; - - emmb = (EMMessageBrowser *) em_message_browser_new (); - gtk_widget_show (GTK_WIDGET (emmb)); - - /* FIXME: title set elsewhere? */ - emmb->window = g_object_new ( - BONOBO_TYPE_WINDOW, "title", "Evolution", NULL); - bonobo_window_set_contents ( - BONOBO_WINDOW (emmb->window), GTK_WIDGET (emmb)); - - uic = bonobo_ui_component_new_default (); - uicont = bonobo_window_get_ui_container (BONOBO_WINDOW (emmb->window)); - bonobo_ui_component_set_container (uic, BONOBO_OBJREF (uicont), NULL); - - em_folder_view_activate (EM_FOLDER_VIEW (emmb), uic, TRUE); - - if (window_size.width == 0) { - /* initialize @window_size with the previous session's size */ - - /* FIXME Have GConfBridge handle this. */ - - GConfClient *client; - GError *error = NULL; - - client = gconf_client_get_default (); - - window_size.width = gconf_client_get_int ( - client, "/apps/evolution/mail/message_window/width", - &error); - if (error != NULL) { - window_size.width = DEFAULT_WIDTH; - g_clear_error (&error); - } - - window_size.height = gconf_client_get_int ( - client, "/apps/evolution/mail/message_window/height", - &error); - if (error != NULL) { - window_size.height = DEFAULT_HEIGHT; - g_clear_error (&error); - } - - g_object_unref (client); - } - - gtk_window_set_default_size ( - GTK_WINDOW (emmb->window), - window_size.width, window_size.height); - - g_signal_connect ( - emmb->window, "size-allocate", - G_CALLBACK (emmb_window_size_allocate), NULL); - g_signal_connect ( - EM_FOLDER_VIEW (emmb)->list, "message_selected", - G_CALLBACK (emmb_list_message_selected_cb), emmb); - g_signal_connect ( - emmb, "key-press-event", - G_CALLBACK (emmb_key_press_event_cb), NULL); - - /* cleanup? */ - - return GTK_WIDGET (emmb); -} diff --git a/mail/em-message-browser.h b/mail/em-message-browser.h deleted file mode 100644 index cf00a74a75..0000000000 --- a/mail/em-message-browser.h +++ /dev/null @@ -1,74 +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/> - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef EM_MESSAGE_BROWSER_H -#define EM_MESSAGE_BROWSER_H - -#include <gtk/gtk.h> -#include "em-folder-view.h" - -/* Standard GObject macros */ -#define EM_TYPE_MESSAGE_BROWSER \ - (em_message_browser_get_type ()) -#define EM_MESSAGE_BROWSER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), EM_TYPE_MESSAGE_BROWSER, EMMessageBrowser)) -#define EM_MESSAGE_BROWSER_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), EM_TYPE_MESSAGE_BROWSER, EMMessageBrowserClass)) -#define EM_IS_MESSAGE_BROWSER(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), EM_TYPE_MESSAGE_BROWSER)) -#define EM_IS_MESSAGE_BROWSER_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), EM_TYPE_MESSAGE_BROWSER)) -#define EM_MESSAGE_BROWSER_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), EM_TYPE_MESSAGE_BROWSER, EMMessageBrowserClass)) - -G_BEGIN_DECLS - -typedef struct _EMMessageBrowser EMMessageBrowser; -typedef struct _EMMessageBrowserClass EMMessageBrowserClass; -typedef struct _EMMessageBrowserPrivate EMMessageBrowserPrivate; - -struct _EMMessageBrowser { - EMFolderView parent; - - /* container, if setup */ - GtkWidget *window; - - EMMessageBrowserPrivate *priv; -}; - -struct _EMMessageBrowserClass { - EMFolderViewClass parent_class; -}; - -GType em_message_browser_get_type (void); - -GtkWidget * em_message_browser_new (void); - -/* Also sets up a bonobo container window w/ docks and so on. */ -GtkWidget * em_message_browser_window_new (void); - -G_END_DECLS - -#endif /* EM_MESSAGE_BROWSER_H */ diff --git a/mail/em-network-prefs.c b/mail/em-network-prefs.c index ef711ac251..13f71b966e 100644 --- a/mail/em-network-prefs.c +++ b/mail/em-network-prefs.c @@ -32,8 +32,6 @@ #include "em-network-prefs.h" -#include <bonobo/bonobo-generic-factory.h> - #include <gdk/gdkkeysyms.h> #include <gconf/gconf-client.h> #include <glade/glade.h> diff --git a/mail/em-network-prefs.h b/mail/em-network-prefs.h index 27c4e77685..50d986c5d1 100644 --- a/mail/em-network-prefs.h +++ b/mail/em-network-prefs.h @@ -20,30 +20,37 @@ * */ -#ifndef __EM_NETWORK_PREFS_H__ -#define __EM_NETWORK_PREFS_H__ - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ +#ifndef EM_NETWORK_PREFS_H +#define EM_NETWORK_PREFS_H #include <gtk/gtk.h> - -#define EM_NETWORK_PREFS_TYPE (em_network_prefs_get_type ()) -#define EM_NETWORK_PREFS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EM_NETWORK_PREFS_TYPE, EMNetworkPrefs)) -#define EM_NETWORK_PREFS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), EM_NETWORK_PREFS_TYPE, EMNetworkPrefsClass)) -#define EM_IS_NETWORK_PREFS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EM_NETWORK_PREFS_TYPE)) -#define EM_IS_NETWORK_PREFS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EM_NETWORK_PREFS_TYPE)) +#include <glade/glade.h> +#include <gconf/gconf-client.h> + +/* Standard GObject macros */ +#define EM_TYPE_NETWORK_PREFS \ + (em_network_prefs_get_type ()) +#define EM_NETWORK_PREFS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), EM_TYPE_NETWORK_PREFS, EMNetworkPrefs)) +#define EM_NETWORK_PREFS_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), EM_TYPE_NETWORK_PREFS, EMNetworkPrefsClass)) +#define EM_IS_NETWORK_PREFS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), EM_TYPE_NETWORK_PREFS)) +#define EM_IS_NETWORK_PREFS_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), EM_TYPE_NETWORK_PREFS)) +#define EM_NETWORK_PREFS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), EM_TYPE_NETWORK_PREFS, EMNetworkPrefsClass)) + +G_BEGIN_DECLS typedef struct _EMNetworkPrefs EMNetworkPrefs; typedef struct _EMNetworkPrefsClass EMNetworkPrefsClass; -struct _GtkToggleButton; -struct _GtkEntry; -struct _GladeXML; -struct _GConfClient; - typedef enum { NETWORK_PROXY_SYS_SETTINGS, NETWORK_PROXY_DIRECT_CONNECTION, @@ -51,66 +58,47 @@ typedef enum { NETWORK_PROXY_AUTOCONFIG } NetworkConfigProxyType; - struct _EMNetworkPrefs { GtkVBox parent_object; - struct _GConfClient *gconf; + GConfClient *gconf; - struct _GladeXML *gui; + GladeXML *gui; /* Default Behavior */ - struct _GtkToggleButton *sys_proxy; - struct _GtkToggleButton *no_proxy; - struct _GtkToggleButton *manual_proxy; -#if 0 - struct _GtkToggleButton *auto_proxy; -#endif - struct _GtkToggleButton *use_auth; - - struct _GtkEntry *http_host; - struct _GtkEntry *https_host; - struct _GtkEntry *ignore_hosts; -#if 0 - struct _GtkEntry *auto_proxy_url; -#endif - struct _GtkEntry *auth_user; - struct _GtkEntry *auth_pwd; - - struct _GtkLabel *lbl_http_host; - struct _GtkLabel *lbl_http_port; - struct _GtkLabel *lbl_https_host; - struct _GtkLabel *lbl_https_port; - struct _GtkLabel *lbl_ignore_hosts; - struct _GtkLabel *lbl_auth_user; - struct _GtkLabel *lbl_auth_pwd; - - struct _GtkSpinButton *http_port; - struct _GtkSpinButton *https_port; -#if 0 - struct _GtkLabel *lbl_socks_host; - struct _GtkEntry *socks_host; - struct _GtkLabel *lbl_socks_port; - struct _GtkSpinButton *socks_port; -#endif + GtkToggleButton *sys_proxy; + GtkToggleButton *no_proxy; + GtkToggleButton *manual_proxy; + GtkToggleButton *use_auth; + + GtkEntry *http_host; + GtkEntry *https_host; + GtkEntry *socks_host; + GtkEntry *ignore_hosts; + GtkEntry *auth_user; + GtkEntry *auth_pwd; + + GtkLabel *lbl_http_host; + GtkLabel *lbl_http_port; + GtkLabel *lbl_https_host; + GtkLabel *lbl_https_port; + GtkLabel *lbl_socks_host; + GtkLabel *lbl_socks_port; + GtkLabel *lbl_ignore_hosts; + GtkLabel *lbl_auth_user; + GtkLabel *lbl_auth_pwd; + + GtkSpinButton *http_port; + GtkSpinButton *https_port; }; struct _EMNetworkPrefsClass { GtkVBoxClass parent_class; - - /* signals */ - }; -GType em_network_prefs_get_type (void); - -struct _GtkWidget *em_network_prefs_new (void); - -/* needed by global config */ -#define EM_NETWORK_PREFS_CONTROL_ID "OAFIID:GNOME_Evolution_Mail_NetworkPrefs_ConfigControl:" BASE_VERSION +GType em_network_prefs_get_type (void); +GtkWidget * em_network_prefs_new (void); -#ifdef __cplusplus -} -#endif /* __cplusplus */ +G_END_DECLS -#endif /* __EM_NETWORK_PREFS_H__ */ +#endif /* EM_NETWORK_PREFS_H */ diff --git a/mail/em-popup.c b/mail/em-popup.c index debad8cb56..914b9840b5 100644 --- a/mail/em-popup.c +++ b/mail/em-popup.c @@ -55,8 +55,6 @@ #include <e-util/e-util.h> #include "e-attachment.h" -static void emp_standard_menu_factory(EPopup *emp, void *data); - static GObjectClass *emp_parent; static void @@ -110,8 +108,6 @@ emp_class_init(GObjectClass *klass) { klass->finalize = emp_finalise; ((EPopupClass *)klass)->target_free = emp_target_free; - - e_popup_class_add_factory((EPopupClass *)klass, NULL, emp_standard_menu_factory, NULL); } GType @@ -357,419 +353,6 @@ done: /* ********************************************************************** */ -static void -emp_part_popup_saveas(EPopup *ep, EPopupItem *item, void *data) -{ - EPopupTarget *t = ep->target; - CamelMimePart *part = NULL; - - part = ((EMPopupTargetPart *) t)->part; - - em_utils_save_part(ep->target->widget, _("Save As..."), part); -} - -static void -emp_part_popup_set_background(EPopup *ep, EPopupItem *item, void *data) -{ - EPopupTarget *t = ep->target; - GConfClient *gconf; - char *str, *filename, *path, *extension; - unsigned int i=1; - CamelMimePart *part = NULL; - - part = ((EMPopupTargetPart *) t)->part; - - if (!part) - return; - - filename = g_strdup(camel_mime_part_get_filename(part)); - - /* if filename is blank, create a default filename based on MIME type */ - if (!filename || !filename[0]) { - CamelContentType *ct; - - ct = camel_mime_part_get_content_type(part); - g_free (filename); - filename = g_strdup_printf (_("untitled_image.%s"), ct->subtype); - } - - e_filename_make_safe(filename); - - path = g_build_filename(g_get_home_dir(), ".gnome2", "wallpapers", filename, NULL); - - extension = strrchr(filename, '.'); - if (extension) - *extension++ = 0; - - /* if file exists, stick a (number) on the end */ - while (g_file_test(path, G_FILE_TEST_EXISTS)) { - char *name; - name = g_strdup_printf(extension?"%s (%d).%s":"%s (%d)", filename, i++, extension); - g_free(path); - path = g_build_filename(g_get_home_dir(), ".gnome2", "wallpapers", name, NULL); - g_free(name); - } - - g_free(filename); - - if (em_utils_save_part_to_file(ep->target->widget, path, part)) { - gconf = gconf_client_get_default(); - - /* if the filename hasn't changed, blank the filename before - * setting it so that gconf detects a change and updates it */ - if ((str = gconf_client_get_string(gconf, "/desktop/gnome/background/picture_filename", NULL)) != NULL - && strcmp (str, path) == 0) { - gconf_client_set_string(gconf, "/desktop/gnome/background/picture_filename", "", NULL); - } - - g_free (str); - gconf_client_set_string(gconf, "/desktop/gnome/background/picture_filename", path, NULL); - - /* if GNOME currently doesn't display a picture, set to "wallpaper" - * display mode, otherwise leave it alone */ - if ((str = gconf_client_get_string(gconf, "/desktop/gnome/background/picture_options", NULL)) == NULL - || strcmp(str, "none") == 0) { - gconf_client_set_string(gconf, "/desktop/gnome/background/picture_options", "wallpaper", NULL); - } - - gconf_client_suggest_sync(gconf, NULL); - - g_free(str); - g_object_unref(gconf); - } - - g_free(path); -} - -static void -emp_part_popup_reply_sender(EPopup *ep, EPopupItem *item, void *data) -{ - EPopupTarget *t = ep->target; - CamelMimeMessage *message; - CamelMimePart *part; - - part = ((EMPopupTargetPart *) t)->part; - - message = (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *)part); - em_utils_reply_to_message(NULL, NULL, message, REPLY_MODE_SENDER, NULL); -} - -static void -emp_part_popup_reply_list (EPopup *ep, EPopupItem *item, void *data) -{ - EPopupTarget *t = ep->target; - CamelMimeMessage *message; - CamelMimePart *part; - - part = ((EMPopupTargetPart *) t)->part; - - message = (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *)part); - em_utils_reply_to_message(NULL, NULL, message, REPLY_MODE_LIST, NULL); -} - -static void -emp_part_popup_reply_all (EPopup *ep, EPopupItem *item, void *data) -{ - EPopupTarget *t = ep->target; - CamelMimeMessage *message; - CamelMimePart *part; - - part = ((EMPopupTargetPart *) t)->part; - - message = (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *)part); - em_utils_reply_to_message(NULL, NULL, message, REPLY_MODE_ALL, NULL); -} - -static void -emp_part_popup_forward (EPopup *ep, EPopupItem *item, void *data) -{ - EPopupTarget *t = ep->target; - CamelMimeMessage *message; - CamelMimePart *part; - - part = ((EMPopupTargetPart *) t)->part; - - /* TODO: have a emfv specific override so we can get the parent folder uri */ - message = (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *) part); - em_utils_forward_message(message, NULL); -} - -static EMPopupItem emp_standard_object_popups[] = { - { E_POPUP_ITEM, "00.part.00", N_("_Save As..."), emp_part_popup_saveas, NULL, "document-save-as", 0 }, - { E_POPUP_ITEM, "00.part.10", N_("Set as _Background"), emp_part_popup_set_background, NULL, NULL, EM_POPUP_PART_IMAGE }, - { E_POPUP_BAR, "10.part", NULL, NULL, NULL, NULL, EM_POPUP_PART_MESSAGE }, - { E_POPUP_ITEM, "10.part.00", N_("_Reply to sender"), emp_part_popup_reply_sender, NULL, "mail-reply-sender" , EM_POPUP_PART_MESSAGE }, - { E_POPUP_ITEM, "10.part.01", N_("Reply to _List"), emp_part_popup_reply_list, NULL, NULL, EM_POPUP_PART_MESSAGE}, - { E_POPUP_ITEM, "10.part.03", N_("Reply to _All"), emp_part_popup_reply_all, NULL, "mail-reply-all", EM_POPUP_PART_MESSAGE}, - { E_POPUP_BAR, "20.part", NULL, NULL, NULL, NULL, EM_POPUP_PART_MESSAGE }, - { E_POPUP_ITEM, "20.part.00", N_("_Forward"), emp_part_popup_forward, NULL, "mail-forward", EM_POPUP_PART_MESSAGE }, -}; - -static const EPopupItem emp_standard_part_apps_bar = { E_POPUP_BAR, "99.object" }; - -/* ********************************************************************** */ - -static void -emp_uri_popup_link_open(EPopup *ep, EPopupItem *item, void *data) -{ - EMPopupTargetURI *t = (EMPopupTargetURI *)ep->target; - - /* FIXME Pass a parent window. */ - e_show_uri (NULL, t->uri); -} - -static void -emp_uri_popup_address_send(EPopup *ep, EPopupItem *item, void *data) -{ - EMPopupTargetURI *t = (EMPopupTargetURI *)ep->target; - - /* TODO: have an emfv specific override to get the from uri */ - em_utils_compose_new_message_with_mailto(t->uri, NULL); -} - -static void -emp_uri_popup_address_add(EPopup *ep, EPopupItem *item, void *data) -{ - EMPopupTargetURI *t = (EMPopupTargetURI *)ep->target; - CamelURL *url; - - url = camel_url_new(t->uri, NULL); - if (url == NULL) { - g_warning("cannot parse url '%s'", t->uri); - return; - } - - if (url->path && url->path[0]) - em_utils_add_address(ep->target->widget, url->path); - - camel_url_free(url); -} - -static EPopupItem emp_standard_uri_popups[] = { - { E_POPUP_ITEM, "00.uri.00", N_("_Open Link in Browser"), emp_uri_popup_link_open, NULL, NULL, EM_POPUP_URI_HTTP }, - { E_POPUP_ITEM, "00.uri.10", N_("_Send New Message To..."), emp_uri_popup_address_send, NULL, "mail-message-new", EM_POPUP_URI_MAILTO }, - { E_POPUP_ITEM, "00.uri.20", N_("_Add to Address Book"), emp_uri_popup_address_add, NULL, "contact-new", EM_POPUP_URI_MAILTO }, -}; - -/* ********************************************************************** */ - -#define LEN(x) (sizeof(x)/sizeof(x[0])) - -static void -emp_apps_open_in(EPopup *ep, EPopupItem *item, void *data) -{ - char *path; - EPopupTarget *target = ep->target; - CamelMimePart *part; - - part = ((EMPopupTargetPart *) target)->part; - - path = em_utils_temp_save_part(target->widget, part, TRUE); - if (path) { - GAppInfo *app = item->user_data; - GList *uris = NULL; - GError *error = NULL; - - if (g_app_info_supports_files (app)) { - GFile *file = g_file_new_for_path (path); - - uris = g_list_append (uris, file); - g_app_info_launch (app, uris, NULL, &error); - g_object_unref (file); - } else { - char *uri; - - uri = e_util_filename_to_uri (path); - uris = g_list_append (uris, uri); - - g_app_info_launch_uris (app, uris, NULL, &error); - g_free (uri); - } - - if (error) { - g_warning ("%s", error->message); - g_error_free (error); - } - - g_list_free (uris); - g_free (path); - } -} - -static void -emp_apps_popup_free(EPopup *ep, GSList *free_list, void *data) -{ - while (free_list) { - GSList *n = free_list->next; - EPopupItem *item = free_list->data; - - if (item->user_data && item->activate == emp_apps_open_in) - g_object_unref (item->user_data); - - g_free(item->path); - g_free(item->label); - g_free(item); - g_slist_free_1(free_list); - - free_list = n; - } -} - -static void -emp_standard_items_free(EPopup *ep, GSList *items, void *data) -{ - g_slist_free(items); -} - -static void -emp_add_vcard (EPopup *ep, EPopupItem *item, void *data) -{ - EPopupTarget *target = ep->target; - CamelMimePart *part; - CamelDataWrapper *content; - CamelStreamMem *mem; - - - part = ((EMPopupTargetPart *) target)->part; - - if (!part) - return; - - content = camel_medium_get_content_object (CAMEL_MEDIUM (part)); - mem = CAMEL_STREAM_MEM (camel_stream_mem_new ()); - - if (camel_data_wrapper_decode_to_stream (content, CAMEL_STREAM (mem)) == -1 || - !mem->buffer->data) - g_warning ("Read part's content failed!"); - else { - GString *vcard = g_string_new_len ((const gchar *) mem->buffer->data, mem->buffer->len); - - em_utils_add_vcard (target->widget, vcard->str); - - g_string_free (vcard, TRUE); - } - - camel_object_unref (mem); -} - -static void -emp_standard_menu_factory(EPopup *emp, void *data) -{ - int i, len; - EPopupItem *items; - GSList *menus = NULL; - GList *apps = NULL; - char *mime_type = NULL; - const char *filename = NULL; - - switch (emp->target->type) { -#if 0 - case EM_POPUP_TARGET_SELECT: - return; - items = emp_standard_select_popups; - len = LEN(emp_standard_select_popups); - break; -#endif - case EM_POPUP_TARGET_URI: { - /*EMPopupTargetURI *t = (EMPopupTargetURI *)target;*/ - - items = emp_standard_uri_popups; - len = LEN(emp_standard_uri_popups); - break; } - case EM_POPUP_TARGET_PART: { - EMPopupTargetPart *t = (EMPopupTargetPart *)emp->target; - mime_type = camel_data_wrapper_get_mime_type((CamelDataWrapper *)t->part); - filename = camel_mime_part_get_filename(t->part); - - items = emp_standard_object_popups; - len = LEN(emp_standard_object_popups); - break; } - default: - items = NULL; - len = 0; - } - - if (mime_type) { - gchar *cp; - - /* GIO expects lowercase MIME types. */ - for (cp = mime_type; *cp != '\0'; cp++) - *cp = g_ascii_tolower (*cp); - - cp = g_content_type_from_mime_type (mime_type); - apps = g_app_info_get_all_for_type (cp ? cp : mime_type); - g_free (cp); - - if (apps == NULL || strcmp (mime_type, "application/octet-stream") == 0) { - if (filename != NULL) { - gchar *name_type; - - name_type = e_util_guess_mime_type (filename, FALSE); - cp = g_content_type_from_mime_type (name_type); - /* show alternative apps first */ - apps = g_list_concat (g_app_info_get_all_for_type (cp ? cp : name_type), apps); - g_free (cp); - g_free (name_type); - } - } - - if (apps) { - GString *label = g_string_new(""); - GSList *open_menus = NULL; - GList *l; - - menus = g_slist_prepend(menus, (void *)&emp_standard_part_apps_bar); - - for (l = apps, i = 0; l; l = l->next, i++) { - GAppInfo *app = l->data; - EPopupItem *item; - - item = g_malloc0(sizeof(*item)); - item->type = E_POPUP_ITEM; - item->path = g_strdup_printf("99.object.%02d", i); - item->label = g_strdup_printf(_("Open in %s..."), g_app_info_get_name (app)); - item->activate = emp_apps_open_in; - item->user_data = app; - - open_menus = g_slist_prepend(open_menus, item); - } - - if (open_menus) - e_popup_add_items(emp, open_menus, NULL, emp_apps_popup_free, NULL); - - g_string_free(label, TRUE); - g_list_free(apps); - } - - if (g_ascii_strcasecmp (mime_type, "text/x-vcard") == 0|| - g_ascii_strcasecmp (mime_type, "text/vcard") == 0) { - EPopupItem *item; - - item = g_malloc0 (sizeof (*item)); - item->type = E_POPUP_ITEM; - item->path = "00.00.vcf.00"; /* make it first item */ - item->label = _("_Add to Address Book"); - item->activate = emp_add_vcard; - item->user_data = NULL; - item->image = "contact-new"; - - e_popup_add_items (emp, g_slist_append (NULL, item), NULL, NULL, NULL); - } - - g_free (mime_type); - } - - for (i=0;i<len;i++) { - if ((items[i].visible & emp->target->mask) == 0) - menus = g_slist_prepend(menus, &items[i]); - } - - if (menus) - e_popup_add_items(emp, menus, NULL, emp_standard_items_free, NULL); -} - -/* ********************************************************************** */ - /* Popup menu plugin handler */ /* diff --git a/mail/em-search-context.c b/mail/em-search-context.c index 5bf98614c6..a8a63ebe2d 100644 --- a/mail/em-search-context.c +++ b/mail/em-search-context.c @@ -33,35 +33,40 @@ #include "filter/filter-option.h" #include "filter/filter-int.h" -static FilterElement *em_search_new_element(RuleContext *rc, const char *type); +static gpointer parent_class; -static RuleContextClass *parent_class = NULL; - -static void -em_search_context_finalise (GObject *obj) +static FilterElement * +search_context_new_element (RuleContext *context, + const gchar *type) { - G_OBJECT_CLASS (parent_class)->finalize (obj); + if (strcmp (type, "system-flag") == 0) + return (FilterElement *) filter_option_new (); + + if (strcmp (type, "score") == 0) + return (FilterElement *) filter_int_new_type ("score", -3, 3); + + /* Chain up to parent's new_element() method. */ + return RULE_CONTEXT_CLASS (parent_class)->new_element (context, type); } static void -em_search_context_class_init (EMSearchContextClass *klass) +search_context_class_init (EMSearchContextClass *class) { - parent_class = g_type_class_ref (RULE_TYPE_CONTEXT); + RuleContextClass *rule_context_class; - ((GObjectClass *)klass)->finalize = em_search_context_finalise; - ((RuleContextClass *)klass)->new_element = em_search_new_element; + parent_class = g_type_class_peek_parent (class); + + rule_context_class = RULE_CONTEXT_CLASS (class); + rule_context_class->new_element = search_context_new_element; } static void -em_search_context_init (EMSearchContext *vc) +search_context_init (EMSearchContext *vc) { - rule_context_add_part_set ((RuleContext *)vc, "partset", filter_part_get_type (), - rule_context_add_part, rule_context_next_part); - - rule_context_add_rule_set ((RuleContext *)vc, "ruleset", filter_rule_get_type (), - rule_context_add_rule, rule_context_next_rule); + RuleContext *rule_context; - ((RuleContext *)vc)->flags = RULE_CONTEXT_THREADING | RULE_CONTEXT_GROUPING; + rule_context = RULE_CONTEXT (vc); + rule_context->flags = RULE_CONTEXT_THREADING | RULE_CONTEXT_GROUPING; } GType @@ -69,46 +74,29 @@ em_search_context_get_type (void) { static GType type = 0; - if (!type) { - static const GTypeInfo info = { + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { sizeof (EMSearchContextClass), - NULL, /* base_class_init */ - NULL, /* base_class_finalize */ - (GClassInitFunc) em_search_context_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) search_context_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ sizeof (EMSearchContext), - 0, /* n_preallocs */ - (GInstanceInitFunc) em_search_context_init, + 0, /* n_preallocs */ + (GInstanceInitFunc) search_context_init, + NULL /* value_table */ }; - type = g_type_register_static (RULE_TYPE_CONTEXT, "EMSearchContext", &info, 0); + type = g_type_register_static ( + RULE_TYPE_CONTEXT, "EMSearchContext", &type_info, 0); } return type; } -/** - * em_search_context_new: - * - * Create a new EMSearchContext object. - * - * Return value: A new #EMSearchContext object. - **/ -EMSearchContext * +RuleContext * em_search_context_new (void) { - return (EMSearchContext *) g_object_new (EM_SEARCH_TYPE_CONTEXT, NULL, NULL); -} - -static FilterElement * -em_search_new_element(RuleContext *rc, const char *type) -{ - if (!strcmp (type, "system-flag")) { - return (FilterElement *) filter_option_new (); - } else if (!strcmp (type, "score")) { - return (FilterElement *) filter_int_new_type("score", -3, 3); - } else { - return parent_class->new_element(rc, type); - } + return g_object_new (EM_SEARCH_TYPE_CONTEXT, NULL); } diff --git a/mail/em-search-context.h b/mail/em-search-context.h index 3df5c1d577..ad18570901 100644 --- a/mail/em-search-context.h +++ b/mail/em-search-context.h @@ -22,31 +22,46 @@ * */ -#ifndef _EM_SEARCH_CONTEXT_H -#define _EM_SEARCH_CONTEXT_H +#ifndef EM_SEARCH_CONTEXT_H +#define EM_SEARCH_CONTEXT_H -#include "filter/rule-context.h" +#include <filter/rule-context.h> -#define EM_SEARCH_TYPE_CONTEXT (em_search_context_get_type ()) -#define EM_SEARCH_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EM_SEARCH_TYPE_CONTEXT, EMSearchContext)) -#define EM_SEARCH_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EM_SEARCH_TYPE_CONTEXT, EMSearchContextClass)) -#define IS_EM_SEARCH_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EM_SEARCH_TYPE_CONTEXT)) -#define IS_EM_SEARCH_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EM_SEARCH_TYPE_CONTEXT)) -#define EM_SEARCH_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EM_SEARCH_TYPE_CONTEXT, EMSearchContextClass)) +/* Standard GObject macros */ +#define EM_SEARCH_TYPE_CONTEXT \ + (em_search_context_get_type ()) +#define EM_SEARCH_CONTEXT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), EM_SEARCH_TYPE_CONTEXT, EMSearchContext)) +#define EM_SEARCH_CONTEXT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), EM_SEARCH_TYPE_CONTEXT, EMSearchContextClass)) +#define EM_IS_SEARCH_CONTEXT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), EM_SEARCH_TYPE_CONTEXT)) +#define EM_IS_SEARCH_CONTEXT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), EM_SEARCH_TYPE_CONTEXT)) +#define EM_SEARCH_CONTEXT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), EM_SEARCH_TYPE_CONTEXT, EMSearchContextClass)) + +G_BEGIN_DECLS typedef struct _EMSearchContext EMSearchContext; typedef struct _EMSearchContextClass EMSearchContextClass; struct _EMSearchContext { - RuleContext parent_object; + RuleContext parent; }; struct _EMSearchContextClass { RuleContextClass parent_class; }; -GType em_search_context_get_type (void); +GType em_search_context_get_type (void); +RuleContext * em_search_context_new (void); -EMSearchContext *em_search_context_new (void); +G_END_DECLS -#endif /* ! _EM_SEARCH_CONTEXT_H */ +#endif /* EM_SEARCH_CONTEXT_H */ diff --git a/mail/em-subscribe-editor.c b/mail/em-subscribe-editor.c index 724b9b4874..a47c6b931d 100644 --- a/mail/em-subscribe-editor.c +++ b/mail/em-subscribe-editor.c @@ -35,8 +35,9 @@ #include "camel/camel-exception.h" #include "camel/camel-store.h" #include "camel/camel-session.h" -#include "libedataserver/e-account-list.h" #include "libedataserver/e-msgport.h" + +#include "e-util/e-account-utils.h" #include "e-util/e-util-private.h" #include "em-subscribe-editor.h" @@ -819,7 +820,8 @@ window_size_allocate (GtkWidget *widget, GtkAllocation *allocation) g_object_unref (gconf); } -GtkDialog *em_subscribe_editor_new(void) +GtkWidget * +em_subscribe_editor_new(void) { EMSubscribeEditor *se; EAccountList *accounts; @@ -894,7 +896,7 @@ GtkDialog *em_subscribe_editor_new(void) 1, TRUE, -1); - accounts = mail_config_get_accounts (); + accounts = e_get_account_list (); for (iter = e_list_get_iterator ((EList *) accounts); e_iterator_is_valid (iter); e_iterator_next (iter)) { @@ -944,5 +946,5 @@ GtkDialog *em_subscribe_editor_new(void) gtk_window_set_default_size ((GtkWindow *) se->dialog, window_size.width, window_size.height); g_signal_connect (se->dialog, "size-allocate", G_CALLBACK (window_size_allocate), NULL); - return se->dialog; + return GTK_WIDGET (se->dialog); } diff --git a/mail/em-subscribe-editor.h b/mail/em-subscribe-editor.h index aa9c9a2c2d..5e6f4f5e4a 100644 --- a/mail/em-subscribe-editor.h +++ b/mail/em-subscribe-editor.h @@ -23,6 +23,6 @@ #include <gtk/gtk.h> -GtkDialog *em_subscribe_editor_new(void); +GtkWidget *em_subscribe_editor_new(void); #endif /* ! _EM_SUBSCRIBE_EDITOR_H */ diff --git a/mail/em-utils.c b/mail/em-utils.c index 7685e76845..2da8efaad2 100644 --- a/mail/em-utils.c +++ b/mail/em-utils.c @@ -56,7 +56,6 @@ #include <gio/gio.h> -#include "mail-component.h" #include "mail-mt.h" #include "mail-ops.h" #include "mail-tools.h" @@ -69,10 +68,10 @@ #include "e-util/e-util.h" #include "e-util/e-util-private.h" #include "e-util/e-mktemp.h" -#include "libedataserver/e-account-list.h" +#include "e-util/e-account-utils.h" #include "e-util/e-dialog-utils.h" #include "e-util/e-error.h" - +#include "widgets/misc/e-alert-activity.h" #include "em-utils.h" #include "em-composer-utils.h" @@ -80,11 +79,10 @@ #include "em-format-quote.h" #include "em-account-editor.h" #include "e-attachment.h" -#include "e-activity-handler.h" -static void emu_save_part_done (CamelMimePart *part, char *name, int done, void *data); +#include "e-mail-shell-module.h" -extern struct _CamelSession *session; +static void emu_save_part_done (CamelMimePart *part, char *name, int done, void *data); #define d(x) @@ -194,20 +192,24 @@ druid_destroy_cb (gpointer user_data, GObject *deadbeef) * otherwise. **/ gboolean -em_utils_configure_account (GtkWidget *parent) +em_utils_configure_account (GtkWindow *parent) { EMAccountEditor *emae; + EAccountList *account_list; + + g_return_val_if_fail (GTK_IS_WINDOW (parent), FALSE); emae = em_account_editor_new(NULL, EMAE_DRUID, "org.gnome.evolution.mail.config.accountDruid"); - if (parent != NULL) - e_dialog_set_transient_for((GtkWindow *)emae->editor, parent); + gtk_window_set_transient_for (GTK_WINDOW (emae->editor), parent); g_object_weak_ref((GObject *)emae->editor, (GWeakNotify) druid_destroy_cb, NULL); gtk_widget_show(emae->editor); gtk_grab_add(emae->editor); gtk_main(); - return mail_config_is_configured(); + account_list = e_get_account_list (); + + return (e_list_length ((EList *) account_list) > 0); } /** @@ -224,16 +226,19 @@ em_utils_configure_account (GtkWidget *parent) * or %FALSE otherwise. **/ gboolean -em_utils_check_user_can_send_mail (GtkWidget *parent) +em_utils_check_user_can_send_mail (GtkWindow *parent) { + EAccountList *account_list; EAccount *account; - if (!mail_config_is_configured ()) { + account_list = e_get_account_list (); + + if (e_list_length ((EList *) account_list) == 0) { if (!em_utils_configure_account (parent)) return FALSE; } - if (!(account = mail_config_get_default_account ())) + if (!(account = e_get_default_account ())) return FALSE; /* Check for a transport */ @@ -253,11 +258,12 @@ em_filter_editor_response (GtkWidget *dialog, int button, gpointer user_data) EMFilterContext *fc; if (button == GTK_RESPONSE_OK) { + const gchar *data_dir; char *user; + data_dir = e_shell_module_get_data_dir (mail_shell_module); fc = g_object_get_data ((GObject *) dialog, "context"); - user = g_strdup_printf ("%s/filters.xml", - mail_component_peek_base_directory (mail_component_peek ())); + user = g_strdup_printf ("%s/filters.xml", data_dir); rule_context_save ((RuleContext *) fc, user); g_free (user); } @@ -284,7 +290,7 @@ static EMFilterSource em_filter_source_element_names[] = { void em_utils_edit_filters (GtkWidget *parent) { - const char *base_directory = mail_component_peek_base_directory (mail_component_peek ()); + const gchar *data_dir; char *user, *system; EMFilterContext *fc; @@ -293,8 +299,10 @@ em_utils_edit_filters (GtkWidget *parent) return; } + data_dir = e_shell_module_get_data_dir (mail_shell_module); + fc = em_filter_context_new (); - user = g_strdup_printf ("%s/filters.xml", base_directory); + user = g_build_filename (data_dir, "filters.xml", NULL); system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL); rule_context_load ((RuleContext *) fc, system, user); g_free (user); @@ -385,12 +393,14 @@ emu_save_get_filename_for_part (CamelMimePart *part) * Saves a mime part to disk (prompting the user for filename). **/ void -em_utils_save_part (GtkWidget *parent, const char *prompt, CamelMimePart *part) +em_utils_save_part (GtkWindow *parent, const char *prompt, CamelMimePart *part) { GtkWidget *file_chooser; const gchar *utf8_filename; gchar *uri = NULL, *filename; + g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent)); + utf8_filename = emu_save_get_filename_for_part (part); filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL); em_filename_make_safe (filename); @@ -500,12 +510,14 @@ get_unique_file_names (GSList *parts) } void -em_utils_save_parts (GtkWidget *parent, const gchar *prompt, GSList *parts) +em_utils_save_parts (GtkWindow *parent, const gchar *prompt, GSList *parts) { GtkWidget *file_chooser; gchar *path_uri; GSList *iter, *file_names, *iter_file; + g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent)); + file_chooser = e_file_get_save_filesel ( parent, prompt, NULL, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); @@ -556,7 +568,7 @@ exit: * Returns %TRUE if saving succeeded, %FALSE otherwise **/ gboolean -em_utils_save_part_to_file(GtkWidget *parent, const char *filename, CamelMimePart *part) +em_utils_save_part_to_file(GtkWindow *parent, const char *filename, CamelMimePart *part) { int done; char *dirname; @@ -567,7 +579,7 @@ em_utils_save_part_to_file(GtkWidget *parent, const char *filename, CamelMimePar dirname = g_path_get_dirname(filename); if (g_mkdir_with_parents(dirname, 0777) == -1) { - GtkWidget *w = e_error_new((GtkWindow *)parent, "mail:no-create-path", filename, g_strerror(errno), NULL); + GtkWidget *w = e_error_new(parent, "mail:no-create-path", filename, g_strerror(errno), NULL); g_free(dirname); em_utils_show_error_silent (w); return FALSE; @@ -576,13 +588,13 @@ em_utils_save_part_to_file(GtkWidget *parent, const char *filename, CamelMimePar if (g_access(filename, F_OK) == 0) { if (g_access(filename, W_OK) != 0) { - e_error_run((GtkWindow *)parent, E_ERROR_ASK_FILE_EXISTS_OVERWRITE, filename, NULL); + e_error_run(parent, E_ERROR_ASK_FILE_EXISTS_OVERWRITE, filename, NULL); return FALSE; } } if (g_stat(filename, &st) != -1 && !S_ISREG(st.st_mode)) { - GtkWidget *w = e_error_new((GtkWindow *)parent, "mail:no-write-path-notfile", filename, NULL); + GtkWidget *w = e_error_new(parent, "mail:no-write-path-notfile", filename, NULL); em_utils_show_error_silent (w); return FALSE; } @@ -635,13 +647,14 @@ emu_save_messages_response(GtkWidget *filesel, int response, struct _save_messag * user for filename). **/ void -em_utils_save_messages (GtkWidget *parent, CamelFolder *folder, GPtrArray *uids) +em_utils_save_messages (GtkWindow *parent, CamelFolder *folder, GPtrArray *uids) { struct _save_messages_data *data; GtkWidget *filesel; char *filename = NULL; CamelMessageInfo *info = NULL; + g_return_if_fail (GTK_IS_WINDOW (parent)); g_return_if_fail (CAMEL_IS_FOLDER (folder)); g_return_if_fail (uids != NULL); @@ -681,7 +694,7 @@ emu_add_address_cb(BonoboListener *listener, const char *name, const CORBA_any * /* one of email or vcard should be always NULL, never both of them */ static void -emu_add_address_or_vcard (struct _GtkWidget *parent, const char *email, const char *vcard) +emu_add_address_or_vcard (GtkWindow *parent, const char *email, const char *vcard) { GtkWidget *win; GtkWidget *control; @@ -704,14 +717,7 @@ emu_add_address_or_vcard (struct _GtkWidget *parent, const char *email, const ch win = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title((GtkWindow *)win, _("Add address")); - if (parent && !GTK_IS_WINDOW (parent)) { - parent = gtk_widget_get_toplevel (parent); - if (!parent || !(GTK_WIDGET_TOPLEVEL (parent))) - parent = NULL; - } - - if (parent) - gtk_window_set_transient_for((GtkWindow *)win, ((GtkWindow *)parent)); + gtk_window_set_transient_for((GtkWindow *)win, parent); gtk_window_set_position((GtkWindow *)win, GTK_WIN_POS_CENTER_ON_PARENT); gtk_window_set_type_hint((GtkWindow *)win, GDK_WINDOW_TYPE_HINT_DIALOG); @@ -742,8 +748,10 @@ emu_add_address_or_vcard (struct _GtkWidget *parent, const char *email, const ch * Add address @email to the addressbook. **/ void -em_utils_add_address (struct _GtkWidget *parent, const char *email) +em_utils_add_address (GtkWindow *parent, const char *email) { + g_return_if_fail (GTK_IS_WINDOW (parent)); + emu_add_address_or_vcard (parent, email, NULL); } @@ -752,8 +760,10 @@ em_utils_add_address (struct _GtkWidget *parent, const char *email) * Adds whole vCard to the addressbook. **/ void -em_utils_add_vcard (struct _GtkWidget *parent, const char *vcard) +em_utils_add_vcard (GtkWindow *parent, const char *vcard) { + g_return_if_fail (GTK_IS_WINDOW (parent)); + emu_add_address_or_vcard (parent, NULL, vcard); } @@ -804,7 +814,7 @@ tag_editor_response (GtkWidget *dialog, int button, struct ted_t *ted) camel_tag_list_free (&tags); if (ted->emfv->preview) - em_format_redraw(ted->emfv->preview); + em_format_redraw (EM_FORMAT (ted->emfv->preview)); } gtk_widget_destroy (dialog); @@ -820,19 +830,18 @@ tag_editor_response (GtkWidget *dialog, int button, struct ted_t *ted) * @folder and @uids. **/ void -em_utils_flag_for_followup (GtkWidget *parent, CamelFolder *folder, GPtrArray *uids) +em_utils_flag_for_followup (GtkWindow *parent, CamelFolder *folder, GPtrArray *uids) { GtkWidget *editor; struct ted_t *ted; int i; + g_return_if_fail (GTK_IS_WINDOW (parent)); g_return_if_fail (CAMEL_IS_FOLDER (folder)); g_return_if_fail (uids != NULL); editor = (GtkWidget *) message_tag_followup_new (); - - if (parent != NULL) - e_dialog_set_transient_for ((GtkWindow *) editor, parent); + gtk_window_set_transient_for (GTK_WINDOW (editor), parent); camel_object_ref (folder); @@ -884,10 +893,11 @@ em_utils_flag_for_followup (GtkWidget *parent, CamelFolder *folder, GPtrArray *u * @folder and @uids. **/ void -em_utils_flag_for_followup_clear (GtkWidget *parent, CamelFolder *folder, GPtrArray *uids) +em_utils_flag_for_followup_clear (GtkWindow *parent, CamelFolder *folder, GPtrArray *uids) { int i; + g_return_if_fail (GTK_IS_WINDOW (parent)); g_return_if_fail (CAMEL_IS_FOLDER (folder)); g_return_if_fail (uids != NULL); @@ -918,11 +928,12 @@ em_utils_flag_for_followup_clear (GtkWidget *parent, CamelFolder *folder, GPtrAr * Flag-for-Followup. **/ void -em_utils_flag_for_followup_completed (GtkWidget *parent, CamelFolder *folder, GPtrArray *uids) +em_utils_flag_for_followup_completed (GtkWindow *parent, CamelFolder *folder, GPtrArray *uids) { char *now; int i; + g_return_if_fail (GTK_IS_WINDOW (parent)); g_return_if_fail (CAMEL_IS_FOLDER (folder)); g_return_if_fail (uids != NULL); @@ -1378,19 +1389,23 @@ em_utils_temp_save_part(GtkWidget *parent, CamelMimePart *part, gboolean mode) gboolean em_utils_folder_is_templates (CamelFolder *folder, const char *uri) { + CamelFolder *local_templates_folder; EAccountList *accounts; EAccount *account; EIterator *iter; int is = FALSE; char *templates_uri; - if (folder == mail_component_get_folder (NULL, MAIL_COMPONENT_FOLDER_TEMPLATES)) + local_templates_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_TEMPLATES); + + if (folder == local_templates_folder) return TRUE; - if (uri == NULL) + if (folder == NULL || uri == NULL) return FALSE; - accounts = mail_config_get_accounts(); + accounts = e_get_account_list (); iter = e_list_get_iterator ((EList *)accounts); while (e_iterator_is_valid (iter)) { account = (EAccount *)e_iterator_get (iter); @@ -1425,19 +1440,23 @@ em_utils_folder_is_templates (CamelFolder *folder, const char *uri) gboolean em_utils_folder_is_drafts(CamelFolder *folder, const char *uri) { + CamelFolder *local_drafts_folder; EAccountList *accounts; EAccount *account; EIterator *iter; int is = FALSE; char *drafts_uri; - if (folder == mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_DRAFTS)) + local_drafts_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_DRAFTS); + + if (folder == local_drafts_folder) return TRUE; - if (uri == NULL) + if (folder == NULL || uri == NULL) return FALSE; - accounts = mail_config_get_accounts(); + accounts = e_get_account_list (); iter = e_list_get_iterator((EList *)accounts); while (e_iterator_is_valid(iter)) { account = (EAccount *)e_iterator_get(iter); @@ -1472,19 +1491,23 @@ em_utils_folder_is_drafts(CamelFolder *folder, const char *uri) gboolean em_utils_folder_is_sent(CamelFolder *folder, const char *uri) { + CamelFolder *local_sent_folder; EAccountList *accounts; EAccount *account; EIterator *iter; int is = FALSE; char *sent_uri; - if (folder == mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_SENT)) + local_sent_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_SENT); + + if (folder == local_sent_folder) return TRUE; - if (uri == NULL) + if (folder == NULL || uri == NULL) return FALSE; - accounts = mail_config_get_accounts(); + accounts = e_get_account_list (); iter = e_list_get_iterator((EList *)accounts); while (e_iterator_is_valid(iter)) { account = (EAccount *)e_iterator_get(iter); @@ -1519,8 +1542,13 @@ em_utils_folder_is_sent(CamelFolder *folder, const char *uri) gboolean em_utils_folder_is_outbox(CamelFolder *folder, const char *uri) { + CamelFolder *local_outbox_folder; + + local_outbox_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_OUTBOX); + /* <Highlander>There can be only one.</Highlander> */ - return folder == mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX); + return folder == local_outbox_folder; } /** @@ -1619,7 +1647,6 @@ em_utils_part_to_html(CamelMimePart *part, ssize_t *len, EMFormat *source) emfq = em_format_quote_new(NULL, (CamelStream *)mem, 0); ((EMFormat *) emfq)->composer = TRUE; - em_format_set_session((EMFormat *)emfq, session); if (source) { /* copy over things we can, other things are internal, perhaps need different api than 'clone' */ if (source->default_charset) @@ -1669,7 +1696,6 @@ em_utils_message_to_html(CamelMimeMessage *message, const char *credits, guint32 emfq = em_format_quote_new(credits, (CamelStream *)mem, flags); ((EMFormat *) emfq)->composer = TRUE; - em_format_set_session((EMFormat *)emfq, session); if (!source) { GConfClient *gconf; @@ -1743,7 +1769,7 @@ em_utils_empty_trash (GtkWidget *parent) camel_exception_init (&ex); /* expunge all remote stores */ - accounts = mail_config_get_accounts (); + accounts = e_get_account_list (); iter = e_list_get_iterator ((EList *) accounts); while (e_iterator_is_valid (iter)) { account = (EAccount *) e_iterator_get (iter); @@ -1912,7 +1938,7 @@ char *em_uri_to_camel(const char *euri) uid = g_strdup(eurl->host); } - accounts = mail_config_get_accounts(); + accounts = e_get_account_list (); account = e_account_list_find(accounts, E_ACCOUNT_FIND_UID, uid); g_free(uid); @@ -2384,7 +2410,7 @@ em_utils_clear_get_password_canceled_accounts_flag (void) { EAccountList *accounts; - accounts = mail_config_get_accounts (); + accounts = e_get_account_list (); if (accounts) { EIterator *iter; @@ -2405,25 +2431,63 @@ em_utils_clear_get_password_canceled_accounts_flag (void) } -static void error_response(GtkObject *o, int button, void *data) -{ - gtk_widget_destroy((GtkWidget *)o); -} - void em_utils_show_error_silent (GtkWidget *widget) { - EActivityHandler *handler = mail_component_peek_activity_handler (mail_component_peek ()); - if(!g_object_get_data ((GObject *) widget, "response-handled")) - g_signal_connect(widget, "response", G_CALLBACK(error_response), NULL); - e_activity_handler_make_error (handler, "mail", E_LOG_ERROR, widget); + EActivity *activity; + + activity = e_alert_activity_new_warning (widget); + e_shell_module_add_activity (mail_shell_module, activity); + g_object_unref (activity); + + if (g_object_get_data (G_OBJECT (widget), "response-handled") == NULL) + g_signal_connect ( + widget, "response", + G_CALLBACK (gtk_widget_destroy), NULL); } void em_utils_show_info_silent (GtkWidget *widget) { - EActivityHandler *handler = mail_component_peek_activity_handler (mail_component_peek ()); - if(!g_object_get_data ((GObject *) widget, "response-handled")) - g_signal_connect(widget, "response", G_CALLBACK(error_response), NULL); - e_activity_handler_make_error (handler, "mail", E_LOG_WARNINGS, widget); + EActivity *activity; + + activity = e_alert_activity_new_info (widget); + e_shell_module_add_activity (mail_shell_module, activity); + g_object_unref (activity); + + if (g_object_get_data (G_OBJECT (widget), "response-handled") == NULL) + g_signal_connect ( + widget, "response", + G_CALLBACK (gtk_widget_destroy), NULL); +} + +gchar * +em_utils_url_unescape_amp (const gchar *url) +{ + gchar *buff; + int i, j, amps; + + if (!url) + return NULL; + + amps = 0; + for (i = 0; url [i]; i++) { + if (url [i] == '&' && strncmp (url + i, "&", 5) == 0) + amps++; + } + + buff = g_strdup (url); + + if (!amps) + return buff; + + for (i = 0, j = 0; url [i]; i++, j++) { + buff [j] = url [i]; + + if (url [i] == '&' && strncmp (url + i, "&", 5) == 0) + i += 4; + } + buff [j] = 0; + + return buff; } diff --git a/mail/em-utils.h b/mail/em-utils.h index d64c411a5f..60c6e22c47 100644 --- a/mail/em-utils.h +++ b/mail/em-utils.h @@ -23,79 +23,71 @@ #ifndef __EM_UTILS_H__ #define __EM_UTILS_H__ -#include <glib.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - +#include <gtk/gtk.h> #include <sys/types.h> +#include <camel/camel-exception.h> +#include <camel/camel-folder.h> +#include <camel/camel-internet-address.h> +#include <camel/camel-mime-message.h> +#include <camel/camel-mime-part.h> +#include <camel/camel-stream.h> + +G_BEGIN_DECLS -struct _GtkWidget; -struct _GtkWindow; -struct _CamelFolder; -struct _CamelInternetAddress; -struct _CamelStream; -struct _CamelMimeMessage; -struct _CamelMimePart; -struct _GtkSelectionData; -struct _GtkAdjustment; -struct _CamelException; struct _EMFormat; -gboolean em_utils_prompt_user(struct _GtkWindow *parent, const char *promptkey, const char *tag, const char *arg0, ...); +gboolean em_utils_prompt_user(GtkWindow *parent, const char *promptkey, const char *tag, const char *arg0, ...); GPtrArray *em_utils_uids_copy (GPtrArray *uids); void em_utils_uids_free (GPtrArray *uids); -gboolean em_utils_configure_account (struct _GtkWidget *parent); -gboolean em_utils_check_user_can_send_mail (struct _GtkWidget *parent); +gboolean em_utils_configure_account (GtkWindow *parent); +gboolean em_utils_check_user_can_send_mail (GtkWindow *parent); -void em_utils_edit_filters (struct _GtkWidget *parent); +void em_utils_edit_filters (GtkWidget *parent); void em_filename_make_safe (gchar *string); -void em_utils_edit_vfolders (struct _GtkWidget *parent); +void em_utils_edit_vfolders (GtkWidget *parent); -void em_utils_save_part(struct _GtkWidget *parent, const char *prompt, struct _CamelMimePart *part); -gboolean em_utils_save_part_to_file(struct _GtkWidget *parent, const char *filename, struct _CamelMimePart *part); -void em_utils_save_messages (struct _GtkWidget *parent, struct _CamelFolder *folder, GPtrArray *uids); +void em_utils_save_part(GtkWindow *parent, const char *prompt, CamelMimePart *part); +gboolean em_utils_save_part_to_file(GtkWindow *parent, const char *filename, CamelMimePart *part); +void em_utils_save_messages (GtkWindow *parent, CamelFolder *folder, GPtrArray *uids); -void em_utils_add_address(struct _GtkWidget *parent, const char *email); -void em_utils_add_vcard(struct _GtkWidget *parent, const char *vcard); +void em_utils_add_address(GtkWindow *parent, const char *email); +void em_utils_add_vcard(GtkWindow *parent, const char *vcard); -void em_utils_flag_for_followup (struct _GtkWidget *parent, struct _CamelFolder *folder, GPtrArray *uids); -void em_utils_flag_for_followup_clear (struct _GtkWidget *parent, struct _CamelFolder *folder, GPtrArray *uids); -void em_utils_flag_for_followup_completed (struct _GtkWidget *parent, struct _CamelFolder *folder, GPtrArray *uids); +void em_utils_flag_for_followup (GtkWindow *parent, CamelFolder *folder, GPtrArray *uids); +void em_utils_flag_for_followup_clear (GtkWindow *parent, CamelFolder *folder, GPtrArray *uids); +void em_utils_flag_for_followup_completed (GtkWindow *parent, CamelFolder *folder, GPtrArray *uids); /* This stuff that follows probably doesn't belong here, then again, the stuff above probably belongs elsewhere */ -void em_utils_selection_set_mailbox(struct _GtkSelectionData *data, struct _CamelFolder *folder, GPtrArray *uids); -void em_utils_selection_get_mailbox(struct _GtkSelectionData *data, struct _CamelFolder *folder); -void em_utils_selection_get_message(struct _GtkSelectionData *data, struct _CamelFolder *folder); -/* FIXME: be nice if these also worked on struct _CamelFolder's, no easy way to get uri from folder yet tho */ -void em_utils_selection_set_uidlist(struct _GtkSelectionData *data, const char *uri, GPtrArray *uids); -void em_utils_selection_get_uidlist(struct _GtkSelectionData *data, struct _CamelFolder *dest, int move, struct _CamelException *ex); -void em_utils_selection_set_urilist(struct _GtkSelectionData *data, struct _CamelFolder *folder, GPtrArray *uids); -void em_utils_selection_get_urilist(struct _GtkSelectionData *data, struct _CamelFolder *folder); +void em_utils_selection_set_mailbox(GtkSelectionData *data, CamelFolder *folder, GPtrArray *uids); +void em_utils_selection_get_mailbox(GtkSelectionData *data, CamelFolder *folder); +void em_utils_selection_get_message(GtkSelectionData *data, CamelFolder *folder); +/* FIXME: be nice if these also worked on CamelFolder's, no easy way to get uri from folder yet tho */ +void em_utils_selection_set_uidlist(GtkSelectionData *data, const char *uri, GPtrArray *uids); +void em_utils_selection_get_uidlist(GtkSelectionData *data, CamelFolder *dest, int move, CamelException *ex); +void em_utils_selection_set_urilist(GtkSelectionData *data, CamelFolder *folder, GPtrArray *uids); +void em_utils_selection_get_urilist(GtkSelectionData *data, CamelFolder *folder); -char *em_utils_temp_save_part(struct _GtkWidget *parent, struct _CamelMimePart *part, gboolean mode); -void em_utils_save_parts (struct _GtkWidget *parent, const char *prompt, GSList * parts); +char *em_utils_temp_save_part(GtkWidget *parent, CamelMimePart *part, gboolean mode); +void em_utils_save_parts (GtkWindow *parent, const char *prompt, GSList * parts); -gboolean em_utils_folder_is_drafts(struct _CamelFolder *folder, const char *uri); -gboolean em_utils_folder_is_templates(struct _CamelFolder *folder, const char *uri); -gboolean em_utils_folder_is_sent(struct _CamelFolder *folder, const char *uri); -gboolean em_utils_folder_is_outbox(struct _CamelFolder *folder, const char *uri); +gboolean em_utils_folder_is_drafts(CamelFolder *folder, const char *uri); +gboolean em_utils_folder_is_templates(CamelFolder *folder, const char *uri); +gboolean em_utils_folder_is_sent(CamelFolder *folder, const char *uri); +gboolean em_utils_folder_is_outbox(CamelFolder *folder, const char *uri); -void em_utils_adjustment_page(struct _GtkAdjustment *adj, gboolean down); +void em_utils_adjustment_page(GtkAdjustment *adj, gboolean down); char *em_utils_get_proxy_uri (const char *uri); /* FIXME: should this have an override charset? */ -char *em_utils_part_to_html(struct _CamelMimePart *part, ssize_t *len, struct _EMFormat *source); -char *em_utils_message_to_html(struct _CamelMimeMessage *msg, const char *credits, guint32 flags, ssize_t *len, struct _EMFormat *source, const char *append); +char *em_utils_part_to_html(CamelMimePart *part, ssize_t *len, struct _EMFormat *source); +char *em_utils_message_to_html(CamelMimeMessage *msg, const char *credits, guint32 flags, ssize_t *len, struct _EMFormat *source, const char *append); -void em_utils_expunge_folder (struct _GtkWidget *parent, struct _CamelFolder *folder); -void em_utils_empty_trash (struct _GtkWidget *parent); +void em_utils_expunge_folder (GtkWidget *parent, CamelFolder *folder); +void em_utils_empty_trash (GtkWidget *parent); /* returns the folder name portion of an URI */ char *em_utils_folder_name_from_uri (const char *uri); @@ -105,20 +97,21 @@ char *em_uri_from_camel (const char *curi); char *em_uri_to_camel (const char *euri); /* Run errors silently on the status bar */ -void em_utils_show_error_silent (struct _GtkWidget *widget); -void em_utils_show_info_silent (struct _GtkWidget *widget); +void em_utils_show_error_silent (GtkWidget *widget); +void em_utils_show_info_silent (GtkWidget *widget); /* is this address in the addressbook? caches results */ -gboolean em_utils_in_addressbook (struct _CamelInternetAddress *addr, gboolean local_only); -struct _CamelMimePart *em_utils_contact_photo (struct _CamelInternetAddress *addr, gboolean local); +gboolean em_utils_in_addressbook (CamelInternetAddress *addr, gboolean local_only); +CamelMimePart *em_utils_contact_photo (CamelInternetAddress *addr, gboolean local); -const char *em_utils_snoop_type(struct _CamelMimePart *part); +const char *em_utils_snoop_type(CamelMimePart *part); /* clears flag 'get_password_canceled' at every known accounts, so if needed, get_password will show dialog */ void em_utils_clear_get_password_canceled_accounts_flag (void); -#ifdef __cplusplus -} -#endif /* __cplusplus */ +/* Unescapes & back to a real & in URIs */ +gchar *em_utils_url_unescape_amp (const gchar *url); + +G_END_DECLS #endif /* __EM_UTILS_H__ */ diff --git a/mail/em-vfolder-editor.c b/mail/em-vfolder-editor.c index b0614d937f..9c43b211ed 100644 --- a/mail/em-vfolder-editor.c +++ b/mail/em-vfolder-editor.c @@ -99,7 +99,7 @@ em_vfolder_editor_get_type (void) * * Return value: A new #EMVFolderEditor object. **/ -EMVFolderEditor * +GtkWidget * em_vfolder_editor_new (EMVFolderContext *vc) { EMVFolderEditor *ve = (EMVFolderEditor *) g_object_new (em_vfolder_editor_get_type(), NULL); @@ -116,7 +116,7 @@ em_vfolder_editor_new (EMVFolderContext *vc) gtk_widget_hide(glade_xml_get_widget (gui, "filter_source")); g_object_unref (gui); - return ve; + return GTK_WIDGET (ve); } static FilterRule * diff --git a/mail/em-vfolder-editor.h b/mail/em-vfolder-editor.h index bbdb6ffce8..d46c35fa3d 100644 --- a/mail/em-vfolder-editor.h +++ b/mail/em-vfolder-editor.h @@ -47,6 +47,6 @@ struct _EMVFolderEditorClass { GType em_vfolder_editor_get_type (void); -EMVFolderEditor *em_vfolder_editor_new (EMVFolderContext *vc); +GtkWidget *em_vfolder_editor_new (EMVFolderContext *vc); #endif /* ! _EM_VFOLDER_EDITOR_H */ diff --git a/mail/em-vfolder-rule.c b/mail/em-vfolder-rule.c index 6e12a0456d..128b63b744 100644 --- a/mail/em-vfolder-rule.c +++ b/mail/em-vfolder-rule.c @@ -37,10 +37,11 @@ #include "mail/em-utils.h" #include "mail/em-folder-tree.h" #include "mail/em-folder-selector.h" -#include "mail/mail-component.h" #include "e-util/e-error.h" #include "e-util/e-util-private.h" +#include "e-mail-shell-module.h" + #define d(x) static int validate(FilterRule *); @@ -505,9 +506,11 @@ static void source_add(GtkWidget *widget, struct _source_data *data) { EMFolderTree *emft; + EMFolderTreeModel *model; GtkWidget *dialog; - emft =(EMFolderTree *)em_folder_tree_new_with_model(mail_component_peek_tree_model(mail_component_peek())); + model = e_mail_shell_module_get_folder_tree_model (mail_shell_module); + emft =(EMFolderTree *)em_folder_tree_new_with_model (model); em_folder_tree_set_excluded(emft, EMFT_EXCLUDE_NOSELECT); dialog = em_folder_selector_new(emft, EM_FOLDER_SELECTOR_CAN_CREATE, _("Select Folder"), NULL, _("_Add")); diff --git a/mail/evolution-mail.schemas.in b/mail/evolution-mail.schemas.in index fbebba87cb..3dca693698 100644 --- a/mail/evolution-mail.schemas.in +++ b/mail/evolution-mail.schemas.in @@ -354,6 +354,20 @@ </schema> <schema> + <key>/schema/apps/evolution/mail/display/show_all_headers</key> + <applyto>/apps/evolution/mail/display/show_all_headers</applyto> + <owner>evolution-mail</owner> + <type>bool</type> + <default>false</default> + <locale name="C"> + <short>Show all message headers</short> + <long> + Show all the headers when viewing a messages. + </long> + </locale> + </schema> + + <schema> <key>/schemas/apps/evolution/mail/display/headers</key> <applyto>/apps/evolution/mail/display/headers</applyto> <owner>evolution-mail</owner> @@ -556,16 +570,19 @@ </schema> <schema> - <key>/schemas/apps/evolution/mail/display/show_wide</key> - <applyto>/apps/evolution/mail/display/show_wide</applyto> + <key>/schemas/apps/evolution/mail/display/layout</key> + <applyto>/apps/evolution/mail/display/layout</applyto> <owner>evolution-mail</owner> - <type>bool</type> - <default>false</default> + <type>int</type> + <default>0</default> <locale name="C"> - <short>Use side-by-side or wide layout</short> - <long> - If the "Preview" pane is on, then show it side-by-side rather than vertically. - </long> + <short>Layout style</short> + <long> + The layout style determines where to place the preview pane + in relation to the message list. "0" (Classic View) places + the preview pane below the message list. "1" (Vertical View) + places the preview pane next to the message list. + </long> </locale> </schema> @@ -730,29 +747,41 @@ </locale> </schema> - <!-- Message Window --> + <!-- Mail Browser --> <schema> - <key>/schemas/apps/evolution/mail/message_window/width</key> - <applyto>/apps/evolution/mail/message_window/width</applyto> + <key>/schemas/apps/evolution/mail/mail_browser_width</key> + <applyto>/apps/evolution/mail/mail_browser_width</applyto> <owner>evolution-mail</owner> <type>int</type> <default>600</default> <locale name="C"> - <short>Message Window default width</short> - <long>Default width of the message window.</long> + <short>Mail browser width</short> + <long>Default width of the mail browser window.</long> </locale> </schema> <schema> - <key>/schemas/apps/evolution/mail/message_window/height</key> - <applyto>/apps/evolution/mail/message_window/height</applyto> + <key>/schemas/apps/evolution/mail/mail_browser_height</key> + <applyto>/apps/evolution/mail/mail_browser_height</applyto> <owner>evolution-mail</owner> <type>int</type> <default>400</default> <locale name="C"> - <short>Message Window default height</short> - <long>Default height of the message window.</long> + <short>Mail browser height</short> + <long>Default height of the mail browser window.</long> + </locale> + </schema> + + <schema> + <key>/schemas/apps/evolution/mail/mail_browser_maximized</key> + <applyto>/apps/evolution/mail/mail_browser_maximized</applyto> + <owner>evolution-mail</owner> + <type>bool</type> + <default>false</default> + <locale name="C"> + <short>Mail browser maximized</short> + <long>Default maximized state of the mail browser window.</long> </locale> </schema> diff --git a/mail/filtertypes.xml b/mail/filtertypes.xml index f2f69c4c06..a93b887271 100644 --- a/mail/filtertypes.xml +++ b/mail/filtertypes.xml @@ -636,7 +636,7 @@ </option> </input> <input type="optionlist" name="versus"> - <dynamic func="e_util_labels_get_filter_options"/> + <dynamic func="e_mail_labels_get_filter_options"/> </input> </part> @@ -923,7 +923,7 @@ <title>Set Label</title> <code>(set-label ${label})</code> <input type="optionlist" name="label"> - <dynamic func="e_util_labels_get_filter_options"/> + <dynamic func="e_mail_labels_get_filter_options"/> </input> </part> <part name="colour"> diff --git a/mail/importers/evolution-mbox-importer.c b/mail/importers/evolution-mbox-importer.c index 2943772b68..36cf8768ff 100644 --- a/mail/importers/evolution-mbox-importer.c +++ b/mail/importers/evolution-mbox-importer.c @@ -40,9 +40,8 @@ #include <camel/camel-exception.h> +#include "mail/e-mail-shell-module.h" #include "mail/em-folder-selection-button.h" - -#include "mail/mail-component.h" #include "mail/mail-mt.h" #include "mail-importer.h" @@ -73,15 +72,20 @@ static GtkWidget * mbox_getwidget(EImport *ei, EImportTarget *target, EImportImporter *im) { GtkWidget *hbox, *w; + EMFolderTreeModel *model; + const gchar *local_inbox_folder_uri; + + local_inbox_folder_uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, E_MAIL_FOLDER_INBOX); + model = e_mail_shell_module_get_folder_tree_model (mail_shell_module); hbox = gtk_hbox_new(FALSE, 0); w = gtk_label_new(_("Destination folder:")); gtk_box_pack_start((GtkBox *)hbox, w, FALSE, TRUE, 6); - w = em_folder_selection_button_new(_("Select folder"), _("Select folder to import into")); - em_folder_selection_button_set_selection((EMFolderSelectionButton *)w, - mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_INBOX)); + w = em_folder_selection_button_new(model, _("Select folder"), _("Select folder to import into")); + em_folder_selection_button_set_selection((EMFolderSelectionButton *)w, local_inbox_folder_uri); g_signal_connect(w, "selected", G_CALLBACK(folder_selected), target); gtk_box_pack_start((GtkBox *)hbox, w, FALSE, TRUE, 6); diff --git a/mail/importers/mail-importer.c b/mail/importers/mail-importer.c index 44db11fb56..fde63dfdae 100644 --- a/mail/importers/mail-importer.c +++ b/mail/importers/mail-importer.c @@ -48,8 +48,8 @@ #include "e-util/e-util-private.h" #include "mail/mail-mt.h" -#include "mail/mail-component.h" #include "mail/mail-tools.h" +#include "mail/e-mail-shell-module.h" #include "mail-importer.h" @@ -203,7 +203,8 @@ import_mbox_exec (struct _import_mbox_msg *m) } if (m->uri == NULL || m->uri[0] == 0) - folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_INBOX); + folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_INBOX); else folder = mail_tool_uri_to_folder(m->uri, CAMEL_STORE_FOLDER_CREATE, &m->base.ex); @@ -360,6 +361,7 @@ import_folders_rec(struct _import_folders_data *m, const char *filepath, const c GDir *dir; const char *d; struct stat st; + const gchar *data_dir; char *filefull, *foldersub, *uri, *utf8_filename; const char *folder; @@ -367,6 +369,8 @@ import_folders_rec(struct _import_folders_data *m, const char *filepath, const c if (dir == NULL) return; + data_dir = e_shell_module_get_data_dir (mail_shell_module); + utf8_filename = g_filename_to_utf8 (filepath, -1, NULL, NULL, NULL); camel_operation_start(NULL, _("Scanning %s"), utf8_filename); g_free (utf8_filename); @@ -395,9 +399,9 @@ import_folders_rec(struct _import_folders_data *m, const char *filepath, const c break; } /* FIXME: need a better way to get default store location */ - uri = g_strdup_printf("mbox:%s/local#%s", mail_component_peek_base_directory(NULL), folder); + uri = g_strdup_printf("mbox:%s/local#%s", data_dir, folder); } else { - uri = g_strdup_printf("mbox:%s/local#%s/%s", mail_component_peek_base_directory(NULL), folderparent, folder); + uri = g_strdup_printf("mbox:%s/local#%s/%s", data_dir, folderparent, folder); } printf("importing to uri %s\n", uri); diff --git a/mail/mail-autofilter.c b/mail/mail-autofilter.c index eb8caa78d9..f73c44be42 100644 --- a/mail/mail-autofilter.c +++ b/mail/mail-autofilter.c @@ -32,7 +32,6 @@ #include "mail-vfolder.h" #include "mail-autofilter.h" -#include "mail-component.h" #include "em-utils.h" #include "e-util/e-error.h" #include "e-util/e-util-private.h" @@ -49,6 +48,8 @@ #include <camel/camel-internet-address.h> #include <camel/camel-mime-message.h> +#include "e-mail-shell-module.h" + #define d(x) static void @@ -346,14 +347,15 @@ void filter_gui_add_from_message (CamelMimeMessage *msg, const char *source, int flags) { EMFilterContext *fc; + const gchar *data_dir; char *user, *system; FilterRule *rule; g_return_if_fail (msg != NULL); fc = em_filter_context_new (); - user = g_strdup_printf ("%s/filters.xml", - mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "filters.xml", NULL); system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL); rule_context_load ((RuleContext *)fc, system, user); g_free (system); @@ -371,6 +373,7 @@ void mail_filter_rename_uri(CamelStore *store, const char *olduri, const char *newuri) { EMFilterContext *fc; + const gchar *data_dir; char *user, *system; GList *changed; char *eolduri, *enewuri; @@ -379,7 +382,8 @@ mail_filter_rename_uri(CamelStore *store, const char *olduri, const char *newuri enewuri = em_uri_from_camel(newuri); fc = em_filter_context_new (); - user = g_strdup_printf ("%s/filters.xml", mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "filters.xml", NULL); system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL); rule_context_load ((RuleContext *)fc, system, user); g_free (system); @@ -403,6 +407,7 @@ void mail_filter_delete_uri(CamelStore *store, const char *uri) { EMFilterContext *fc; + const gchar *data_dir; char *user, *system; GList *deleted; char *euri; @@ -410,7 +415,8 @@ mail_filter_delete_uri(CamelStore *store, const char *uri) euri = em_uri_from_camel(uri); fc = em_filter_context_new (); - user = g_strdup_printf ("%s/filters.xml", mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "filters.xml", NULL); system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL); rule_context_load ((RuleContext *)fc, system, user); g_free (system); diff --git a/mail/mail-component-factory.c b/mail/mail-component-factory.c deleted file mode 100644 index 04d44e9725..0000000000 --- a/mail/mail-component-factory.c +++ /dev/null @@ -1,125 +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: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "mail-component.h" -#include "em-account-prefs.h" -#include "em-mailer-prefs.h" -#include "em-composer-prefs.h" -#include "em-network-prefs.h" - -#include "mail-config-factory.h" -#include "mail-config.h" -#include "mail-mt.h" - -#include "em-popup.h" -#include "em-menu.h" -#include "em-event.h" -#include "em-config.h" -#include "em-format-hook.h" -#include "em-junk-hook.h" -#include "em-format-html-display.h" - -#include "importers/mail-importer.h" -#include "e-util/e-import.h" - -#include <bonobo-activation/bonobo-activation.h> -#include <bonobo/bonobo-shlib-factory.h> - -#include <string.h> - -/* TODO: clean up these definitions */ - -#define FACTORY_ID "OAFIID:GNOME_Evolution_Mail_Factory:" BASE_VERSION -#define COMPONENT_ID "OAFIID:GNOME_Evolution_Mail_Component:" BASE_VERSION -#define FOLDER_INFO_ID "OAFIID:GNOME_Evolution_FolderInfo:" BASE_VERSION - -static BonoboObject * -factory(BonoboGenericFactory *factory, const char *component_id, void *closure) -{ - BonoboObject *o; - - if (strcmp (component_id, COMPONENT_ID) == 0) { - MailComponent *component = mail_component_peek (); - - bonobo_object_ref (BONOBO_OBJECT (component)); - return BONOBO_OBJECT (component); - } else if (strcmp (component_id, EM_ACCOUNT_PREFS_CONTROL_ID) == 0 - || strcmp (component_id, EM_MAILER_PREFS_CONTROL_ID) == 0 - || strcmp (component_id, EM_COMPOSER_PREFS_CONTROL_ID) == 0 - || strcmp (component_id, EM_NETWORK_PREFS_CONTROL_ID) == 0) { - return mail_config_control_factory_cb (factory, component_id, CORBA_OBJECT_NIL); - } - - o = mail_importer_factory_cb(factory, component_id, NULL); - if (o == NULL) - g_warning (FACTORY_ID ": Don't know what to do with %s", component_id); - - return o; -} - -static Bonobo_Unknown -make_factory (PortableServer_POA poa, const char *iid, gpointer impl_ptr, CORBA_Environment *ev) -{ - static int init = 0; - - if (!init) { - EImportClass *klass; - - init = 1; - - mail_config_init(); - mail_msg_init(); - - e_plugin_hook_register_type(em_popup_hook_get_type()); - e_plugin_hook_register_type(em_menu_hook_get_type()); - e_plugin_hook_register_type(em_config_hook_get_type()); - - em_format_hook_register_type(em_format_get_type()); - em_format_hook_register_type(em_format_html_get_type()); - em_format_hook_register_type(em_format_html_display_get_type()); - em_junk_hook_register_type(emj_get_type()); - - e_plugin_hook_register_type(em_format_hook_get_type()); - e_plugin_hook_register_type(em_event_hook_get_type()); - e_plugin_hook_register_type(em_junk_hook_get_type()); - - klass = g_type_class_ref(e_import_get_type()); - e_import_class_add_importer(klass, mbox_importer_peek(), NULL, NULL); - e_import_class_add_importer(klass, elm_importer_peek(), NULL, NULL); - e_import_class_add_importer(klass, pine_importer_peek(), NULL, NULL); - } - - return bonobo_shlib_factory_std (FACTORY_ID, poa, impl_ptr, factory, NULL, ev); -} - -static BonoboActivationPluginObject plugin_list[] = { - { FACTORY_ID, make_factory}, - { NULL } -}; - -const BonoboActivationPlugin Bonobo_Plugin_info = { - plugin_list, "Evolution Mail component factory" -}; diff --git a/mail/mail-component.c b/mail/mail-component.c index 556715d662..926f5716c9 100644 --- a/mail/mail-component.c +++ b/mail/mail-component.c @@ -99,33 +99,6 @@ #define d(x) -static void create_local_item_cb(EUserCreatableItemsHandler *handler, const char *item_type_name, void *data); -static void view_changed_timeout_remove (EComponentView *component_view); - -#define MAIL_COMPONENT_DEFAULT(mc) if (mc == NULL) mc = mail_component_peek(); - -#define PARENT_TYPE evolution_component_get_type () -static BonoboObjectClass *parent_class = NULL; - -#define OFFLINE 0 -#define ONLINE 1 - -struct _store_info { - CamelStore *store; - char *name; - - /* we keep a reference to these so they remain around for the session */ - CamelFolder *vtrash; - CamelFolder *vjunk; - - /* for setup only */ - void (*done)(CamelStore *store, CamelFolderInfo *info, void *data); - void *done_data; - - int ref_count:31; - guint removed:1; -}; - struct _MailComponentPrivate { GMutex *lock; @@ -156,305 +129,6 @@ struct _MailComponentPrivate { guint mail_sync_in_progress; /* is greater than 0 if still waiting to finish sync on some store */ }; -/* indexed by _mail_component_folder_t */ -static struct { - char *name; - char *uri; - CamelFolder *folder; -} mc_default_folders[] = { - /* translators: standard local mailbox names */ - { N_("Inbox"), }, - { N_("Drafts"), }, - { N_("Outbox"), }, - { N_("Sent"), }, - { N_("Templates"), }, - { "Inbox", }, /* 'always local' inbox */ -}; - -static struct _store_info * -store_info_new(CamelStore *store, const char *name) -{ - struct _store_info *si; - - si = g_malloc0(sizeof(*si)); - si->ref_count = 1; - if (name == NULL) - si->name = camel_service_get_name((CamelService *)store, TRUE); - else - si->name = g_strdup(name); - si->store = store; - camel_object_ref(store); - /* If these are vfolders then they need to be opened now, - * otherwise they wont keep track of all folders */ - if ((store->flags & CAMEL_STORE_VTRASH) != 0) - si->vtrash = camel_store_get_trash(store, NULL); - if ((store->flags & CAMEL_STORE_VJUNK) != 0) - si->vjunk = camel_store_get_junk(store, NULL); - - return si; -} - -static void -store_info_ref(struct _store_info *si) -{ - si->ref_count++; -} - -static void -store_info_unref(struct _store_info *si) -{ - if (si->ref_count > 1) { - si->ref_count--; - return; - } - - if (si->vtrash) - camel_object_unref(si->vtrash); - if (si->vjunk) - camel_object_unref(si->vjunk); - camel_object_unref(si->store); - g_free(si->name); - g_free(si); -} - -static gboolean -mc_add_store_done(CamelStore *store, CamelFolderInfo *info, void *data) -{ - struct _store_info *si = data; - - if (si->done) - si->done(store, info, si); - - if (!si->removed) { - /* let the counters know about the already opened junk/trash folders */ - if (si->vtrash) - mail_note_folder(si->vtrash); - if (si->vjunk) - mail_note_folder(si->vjunk); - } - - store_info_unref(si); - - return TRUE; -} - -/* Utility functions. */ -static void -mc_add_store(MailComponent *component, CamelStore *store, const char *name, void (*done)(CamelStore *store, CamelFolderInfo *info, void *data)) -{ - struct _store_info *si; - - MAIL_COMPONENT_DEFAULT(component); - - si = store_info_new(store, name); - si->done = done; - g_hash_table_insert(component->priv->store_hash, store, si); - em_folder_tree_model_add_store(component->priv->model, store, si->name); - store_info_ref(si); - mail_note_store(store, NULL, mc_add_store_done, si); -} - -static void -mc_add_local_store_done(CamelStore *store, CamelFolderInfo *info, void *data) -{ - /*MailComponent *mc = data;*/ - int i; - - for (i=0;i<sizeof(mc_default_folders)/sizeof(mc_default_folders[0]);i++) { - if (mc_default_folders[i].folder) - mail_note_folder(mc_default_folders[i].folder); - } -} - -static void -mc_add_local_store(CamelStore *store, const char *name, MailComponent *mc) -{ - mc_add_store(mc, store, name, mc_add_local_store_done); - camel_object_unref(store); - g_object_unref(mc); -} - -static void -mc_setup_local_store(MailComponent *mc) -{ - MailComponentPrivate *p = mc->priv; - CamelURL *url; - char *tmp; - CamelException ex; - int i; - - g_mutex_lock(p->lock); - if (p->local_store != NULL) { - g_mutex_unlock(p->lock); - return; - } - - camel_exception_init(&ex); - - url = camel_url_new("mbox:", NULL); - tmp = g_build_filename (p->base_directory, "local", NULL); - camel_url_set_path(url, tmp); - g_free(tmp); - tmp = camel_url_to_string(url, 0); - p->local_store = (CamelStore *)camel_session_get_service(session, tmp, CAMEL_PROVIDER_STORE, &ex); - g_free(tmp); - if (p->local_store == NULL) - goto fail; - - for (i=0;i<sizeof(mc_default_folders)/sizeof(mc_default_folders[0]);i++) { - /* FIXME: should this uri be account relative? */ - camel_url_set_fragment(url, mc_default_folders[i].name); - mc_default_folders[i].uri = camel_url_to_string(url, 0); - mc_default_folders[i].folder = camel_store_get_folder(p->local_store, mc_default_folders[i].name, - CAMEL_STORE_FOLDER_CREATE, &ex); - camel_exception_clear(&ex); - } - - camel_url_free(url); - g_mutex_unlock(p->lock); - - g_object_ref(mc); - camel_object_ref(p->local_store); - mail_async_event_emit(p->async_event, MAIL_ASYNC_GUI, (MailAsyncFunc)mc_add_local_store, p->local_store, _("On This Computer"), mc); - - return; -fail: - g_mutex_unlock(p->lock); - - g_warning("Could not setup local store/folder: %s", ex.desc); - - camel_url_free(url); - camel_exception_clear(&ex); -} - -static void -load_accounts (MailComponent *component, EAccountList *accounts) -{ - EIterator *iter; - - /* Load each service (don't connect!). Check its provider and - * see if this belongs in the shell's folder list. If so, add - * it. - */ - - iter = e_list_get_iterator ((EList *) accounts); - while (e_iterator_is_valid (iter)) { - EAccountService *service; - EAccount *account; - const char *name; - - account = (EAccount *) e_iterator_get (iter); - service = account->source; - name = account->name; - - /* HACK: mbox url's are handled by the local store setup above, - any that come through as account sources are really movemail sources! */ - if (account->enabled - && service->url != NULL - && service->url[0] - && strncmp(service->url, "mbox:", 5) != 0) - mail_component_load_store_by_uri (component, service->url, name); - - e_iterator_next (iter); - } - - g_object_unref (iter); -} - -static void -setup_search_context (MailComponent *component) -{ - MailComponentPrivate *priv = component->priv; - - if (priv->search_context == NULL) { - char *user = g_build_filename(component->priv->base_directory, "searches.xml", NULL); - char *system = g_build_filename (EVOLUTION_PRIVDATADIR, "searchtypes.xml", NULL); - - priv->search_context = (RuleContext *)em_search_context_new (); - g_object_set_data_full (G_OBJECT (priv->search_context), "user", user, g_free); - g_object_set_data_full (G_OBJECT (priv->search_context), "system", system, g_free); - rule_context_load (priv->search_context, system, user); - } -} - -static void -mc_startup(MailComponent *mc) -{ - static int started = 0; - GConfClient *gconf; - - if (started) - return; - started = 1; - - mc_setup_local_store(mc); - load_accounts(mc, mail_config_get_accounts()); - - gconf = mail_config_get_gconf_client(); - - if (gconf_client_get_bool (gconf, "/apps/evolution/mail/display/enable_vfolders", NULL)) - vfolder_load_storage(); -} - -static void -folder_selected_cb (EMFolderTree *emft, const char *path, const char *uri, guint32 flags, EMFolderView *view) -{ - EMFolderTreeModel *model; - - if ((flags & CAMEL_FOLDER_NOSELECT) || !path) { - em_folder_view_set_folder (view, NULL, NULL); - } else { - model = em_folder_tree_get_model (emft); - em_folder_tree_model_set_selected (model, uri); - em_folder_tree_model_save_state (model); - - em_folder_view_set_folder_uri (view, uri); - } -} - -static int -check_autosave(void *data) -{ - e_msg_composer_check_autosave(NULL); - - return FALSE; -} - -static void -view_control_activate_cb (BonoboControl *control, gboolean activate, EMFolderView *view) -{ - BonoboUIComponent *uic; - static int recover = 0; - - uic = bonobo_control_get_ui_component (control); - g_return_if_fail (uic != NULL); - - if (activate) { - Bonobo_UIContainer container; - - container = bonobo_control_get_remote_ui_container (control, NULL); - bonobo_ui_component_set_container (uic, container, NULL); - bonobo_object_release_unref (container, NULL); - - g_return_if_fail (container == bonobo_ui_component_get_container(uic)); - g_return_if_fail (container != CORBA_OBJECT_NIL); - - em_folder_view_activate (view, uic, activate); - e_user_creatable_items_handler_activate(g_object_get_data((GObject *)view, "e-creatable-items-handler"), uic); - } else { - em_folder_view_activate (view, uic, activate); - bonobo_ui_component_unset_container (uic, NULL); - } - - /* This is a weird place to put it, but createControls does it too early. - I also think we should wait to do it until we actually visit the mailer. - The delay is arbitrary - without it it shows up before the main window */ - if (!recover) { - recover = 1; - g_timeout_add(1000, check_autosave, NULL); - } -} - /* GObject methods. */ static void @@ -467,8 +141,6 @@ impl_dispose (GObject *object) priv->mail_sync_id = 0; } - view_changed_timeout_remove ((EComponentView *)object); - if (priv->activity_handler != NULL) { g_object_unref (priv->activity_handler); priv->activity_handler = NULL; @@ -521,157 +193,6 @@ view_on_url (GObject *emitter, const char *url, const char *nice_url, MailCompon } static void -view_changed(EMFolderView *emfv, EComponentView *component_view) -{ - EInfoLabel *el = g_object_get_data((GObject *)component_view, "info-label"); - CORBA_Environment ev; - - CORBA_exception_init(&ev); - - if (emfv->folder) { - char *name, *title; - const char *use_name; /* will contain localized name, if necessary */ - guint32 visible, unread, deleted, junked, junked_not_deleted; - GPtrArray *selected; - GString *tmp = g_string_new(""); - - camel_object_get(emfv->folder, NULL, - CAMEL_FOLDER_NAME, &name, - CAMEL_FOLDER_DELETED, &deleted, - CAMEL_FOLDER_VISIBLE, &visible, - CAMEL_FOLDER_JUNKED, &junked, - CAMEL_FOLDER_JUNKED_NOT_DELETED, &junked_not_deleted, - CAMEL_FOLDER_UNREAD, &unread, NULL); - - selected = message_list_get_selected(emfv->list); - - /* This is so that if any of these are - * shared/reused, we fallback to the standard - * display behaviour */ - if (selected->len > 1) - g_string_append_printf(tmp, ngettext ("%d selected, ", "%d selected, ", selected->len), selected->len); - - if (CAMEL_IS_VTRASH_FOLDER(emfv->folder)) { - if (((CamelVTrashFolder *)emfv->folder)->type == CAMEL_VTRASH_FOLDER_TRASH) { - g_string_append_printf(tmp, ngettext ("%d deleted", "%d deleted", deleted), deleted); - } else { - guint32 num = junked_not_deleted; - - if (!emfv->hide_deleted) - num = junked; - - g_string_append_printf (tmp, ngettext ("%d junk", "%d junk", num), num); - } - } else if (em_utils_folder_is_drafts(emfv->folder, emfv->folder_uri)) { - g_string_append_printf(tmp, ngettext ("%d draft", "%d drafts", visible), visible); - } else if (em_utils_folder_is_sent(emfv->folder, emfv->folder_uri)) { - g_string_append_printf(tmp, ngettext ("%d sent", "%d sent", visible), visible); - } else if (em_utils_folder_is_outbox(emfv->folder, emfv->folder_uri)) { - g_string_append_printf(tmp, ngettext ("%d unsent", "%d unsent", visible), visible); - /* HACK: hardcoded inbox or maildir '.' folder */ - } else { - if (!emfv->hide_deleted) - visible += deleted - junked + junked_not_deleted; - if (unread && selected->len <= 1) - g_string_append_printf(tmp, ngettext ("%d unread, ", "%d unread, ", unread), unread); - g_string_append_printf(tmp, ngettext ("%d total", "%d total", visible), visible); - } - - message_list_free_uids(emfv->list, selected); - - if (emfv->folder->parent_store == mail_component_peek_local_store(NULL) - && (!strcmp (name, "Drafts") || !strcmp (name, "Inbox") - || !strcmp (name, "Outbox") || !strcmp (name, "Sent") || !strcmp (name, "Templates"))) - use_name = _(name); - else if (!strcmp (name, "INBOX")) - use_name = _("Inbox"); - else - use_name = name; - - e_info_label_set_info (el, use_name, tmp->str); - title = g_strdup_printf ("%s (%s)", use_name, tmp->str); - e_component_view_set_title(component_view, title); - g_free(title); - - g_string_free(tmp, TRUE); - camel_object_free(emfv->folder, CAMEL_FOLDER_NAME, name); - } else { - e_info_label_set_info(el, _("Mail"), ""); - e_component_view_set_title(component_view, _("Mail")); - } -} - -static void -view_changed_timeout_remove (EComponentView *component_view) -{ - gpointer v; - EInfoLabel *el; - EMFolderView *emfv; - - v = g_object_get_data((GObject *)component_view, "view-changed-timeout"); - if (v) { - g_source_remove(GPOINTER_TO_INT(v)); - g_object_set_data((GObject *)component_view, "view-changed-timeout", NULL); - - el = g_object_get_data((GObject *)component_view, "info-label"); - emfv = g_object_get_data((GObject *)el, "folderview"); - g_object_unref(el); - g_object_unref(emfv); - } -} - -static int -view_changed_timeout(void *d) -{ - EComponentView *component_view = d; - EInfoLabel *el = g_object_get_data((GObject *)component_view, "info-label"); - EMFolderView *emfv = g_object_get_data((GObject *)el, "folderview"); - - view_changed(emfv, component_view); - - g_object_set_data((GObject *)component_view, "view-changed-timeout", NULL); - - g_object_unref(el); - g_object_unref(emfv); - - return 0; -} - -static void -view_changed_cb(EMFolderView *emfv, EComponentView *component_view) -{ - MailComponent *mc = mail_component_peek (); - void *v; - EInfoLabel *el = g_object_get_data((GObject *)component_view, "info-label"); - - v = g_object_get_data((GObject *)component_view, "view-changed-timeout"); - - if (mc->priv->quit_state != -1) { - if (v) { - g_source_remove(GPOINTER_TO_INT(v)); - g_object_set_data((GObject *)component_view, "view-changed-timeout", NULL); - g_object_unref (emfv); - g_object_unref (el); - } - - return; - - } - /* This can get called 3 times every cursor move, so - we don't need to/want to run it immediately */ - - /* NB: we should have a 'view' struct/object to manage this crap, but this'll do for now */ - if (v) { - g_source_remove(GPOINTER_TO_INT(v)); - } else { - g_object_ref(emfv); - g_object_ref(el); - } - - g_object_set_data((GObject *)component_view, "view-changed-timeout", GINT_TO_POINTER(g_timeout_add(250, view_changed_timeout, component_view))); -} - -static void disable_folder_tree (gpointer *emfb, GtkWidget *widget) { gtk_widget_set_sensitive (widget, FALSE); @@ -735,60 +256,60 @@ impl_createView (PortableServer_Servant servant, em_folder_browser_suppress_message_selection ( (EMFolderBrowser *) view_widget); - tree_widget = (GtkWidget *) em_folder_tree_new_with_model (priv->model); - em_folder_tree_set_excluded ((EMFolderTree *) tree_widget, 0); - em_folder_tree_enable_drag_and_drop ((EMFolderTree *) tree_widget); - - if ((uri = em_folder_tree_model_get_selected (priv->model))) { - gboolean expanded; - - expanded = em_folder_tree_model_get_expanded_uri (priv->model, uri); - em_folder_tree_set_selected ((EMFolderTree *) tree_widget, uri, FALSE); - em_folder_view_set_folder_uri ((EMFolderView *) view_widget, uri); - - if (!expanded) - em_folder_tree_model_set_expanded_uri (priv->model, uri, expanded); - - g_free (uri); - } +// tree_widget = (GtkWidget *) em_folder_tree_new_with_model (priv->model); +// em_folder_tree_set_excluded ((EMFolderTree *) tree_widget, 0); +// em_folder_tree_enable_drag_and_drop ((EMFolderTree *) tree_widget); + +// if ((uri = em_folder_tree_model_get_selected (priv->model))) { +// gboolean expanded; +// +// expanded = em_folder_tree_model_get_expanded_uri (priv->model, uri); +// em_folder_tree_set_selected ((EMFolderTree *) tree_widget, uri, FALSE); +// em_folder_view_set_folder_uri ((EMFolderView *) view_widget, uri); +// +// if (!expanded) +// em_folder_tree_model_set_expanded_uri (priv->model, uri, expanded); +// +// g_free (uri); +// } em_format_set_session ((EMFormat *) ((EMFolderView *) view_widget)->preview, session); g_signal_connect (view_widget, "on-url", G_CALLBACK (view_on_url), mail_component); em_folder_view_set_statusbar ((EMFolderView*)view_widget, FALSE); - statusbar_widget = e_task_bar_new (); - e_activity_handler_attach_task_bar (priv->activity_handler, E_TASK_BAR (statusbar_widget)); +// statusbar_widget = e_task_bar_new (); +// e_activity_handler_attach_task_bar (priv->activity_handler, E_TASK_BAR (statusbar_widget)); gtk_widget_show (tree_widget); gtk_widget_show (view_widget); gtk_widget_show (statusbar_widget); - vbox = gtk_vbox_new(FALSE, 0); - info = e_info_label_new("evolution-mail"); - e_info_label_set_info((EInfoLabel *)info, _("Mail"), ""); - gtk_box_pack_start((GtkBox *)vbox, info, FALSE, TRUE, 0); - gtk_box_pack_start((GtkBox *)vbox, tree_widget, TRUE, TRUE, 0); +// vbox = gtk_vbox_new(FALSE, 0); +// info = e_info_label_new("evolution-mail"); +// e_info_label_set_info((EInfoLabel *)info, _("Mail"), ""); +// gtk_box_pack_start((GtkBox *)vbox, info, FALSE, TRUE, 0); +// gtk_box_pack_start((GtkBox *)vbox, tree_widget, TRUE, TRUE, 0); gtk_widget_show(info); gtk_widget_show(vbox); - component_view = e_component_view_new(parent, "mail", vbox, view_widget, statusbar_widget); - - g_object_set_data((GObject *)component_view, "info-label", info); - - g_object_set_data_full((GObject *)view_widget, "e-creatable-items-handler", - e_user_creatable_items_handler_new("mail", create_local_item_cb, tree_widget), - (GDestroyNotify)g_object_unref); +// component_view = e_component_view_new(parent, "mail", vbox, view_widget, statusbar_widget); +// +// g_object_set_data((GObject *)component_view, "info-label", info); +// +// g_object_set_data_full((GObject *)view_widget, "e-creatable-items-handler", +// e_user_creatable_items_handler_new("mail", create_local_item_cb, tree_widget), +// (GDestroyNotify)g_object_unref); g_signal_connect (component_view->view_control, "activate", G_CALLBACK (view_control_activate_cb), view_widget); - g_signal_connect (tree_widget, "folder-selected", G_CALLBACK (folder_selected_cb), view_widget); +// g_signal_connect (tree_widget, "folder-selected", G_CALLBACK (folder_selected_cb), view_widget); g_signal_connect((EMFolderBrowser *)view_widget, "account_search_cleared", G_CALLBACK (enable_folder_tree), tree_widget); g_signal_connect(((EMFolderBrowser *)view_widget), "account_search_activated", G_CALLBACK (disable_folder_tree), tree_widget); - g_signal_connect(view_widget, "changed", G_CALLBACK(view_changed_cb), component_view); - g_signal_connect(view_widget, "loaded", G_CALLBACK(view_changed_cb), component_view); +// g_signal_connect(view_widget, "changed", G_CALLBACK(view_changed_cb), component_view); +// g_signal_connect(view_widget, "loaded", G_CALLBACK(view_changed_cb), component_view); g_object_set_data((GObject*)info, "folderview", view_widget); g_object_set_data((GObject*)view_widget, "foldertree", tree_widget); @@ -856,11 +377,14 @@ static CORBA_boolean impl_quit(PortableServer_Servant servant, CORBA_Environment *ev) { MailComponent *mc = MAIL_COMPONENT(bonobo_object_from_servant(servant)); + EAccountList *account_list; if (mc->priv->quit_state == -1) mc->priv->quit_state = MC_QUIT_START; - mail_config_prune_proxies (); + account_list = e_get_account_list (); + e_account_list_prune_proxies (account_list); + switch (mc->priv->quit_state) { case MC_QUIT_START: { extern int camel_application_is_exiting; @@ -914,325 +438,6 @@ impl_quit(PortableServer_Servant servant, CORBA_Environment *ev) return TRUE; } -static GNOME_Evolution_CreatableItemTypeList * -impl__get_userCreatableItems (PortableServer_Servant servant, CORBA_Environment *ev) -{ - GNOME_Evolution_CreatableItemTypeList *list = GNOME_Evolution_CreatableItemTypeList__alloc (); - - list->_length = 2; - list->_maximum = list->_length; - list->_buffer = GNOME_Evolution_CreatableItemTypeList_allocbuf (list->_length); - - CORBA_sequence_set_release (list, FALSE); - - list->_buffer[0].id = "message"; - list->_buffer[0].description = _("New Mail Message"); - list->_buffer[0].menuDescription = (char *) C_("New", "_Mail Message"); - list->_buffer[0].tooltip = _("Compose a new mail message"); - list->_buffer[0].menuShortcut = 'm'; - list->_buffer[0].iconName = "mail-message-new"; - list->_buffer[0].type = GNOME_Evolution_CREATABLE_OBJECT; - - list->_buffer[1].id = "folder"; - list->_buffer[1].description = _("New Mail Folder"); - list->_buffer[1].menuDescription = (char *) C_("New", "Mail _Folder"); - list->_buffer[1].tooltip = _("Create a new mail folder"); - list->_buffer[1].menuShortcut = '\0'; - list->_buffer[1].iconName = "folder-new"; - list->_buffer[1].type = GNOME_Evolution_CREATABLE_FOLDER; - - return list; -} - -static int -create_item(const char *type, EMFolderTreeModel *model, const char *uri, gpointer tree) -{ - if (strcmp(type, "message") == 0) { - if (!em_utils_check_user_can_send_mail(NULL)) - return 0; - - em_utils_compose_new_message(uri); - } else if (strcmp(type, "folder") == 0) { - em_folder_utils_create_folder (NULL, tree, NULL); - } else - return -1; - - return 0; -} - -static void -create_local_item_cb(EUserCreatableItemsHandler *handler, const char *item_type_name, void *data) -{ - EMFolderTree *tree = data; - char *uri = em_folder_tree_get_selected_uri(tree); - - create_item(item_type_name, em_folder_tree_get_model(tree), uri, (gpointer) tree); - g_free(uri); -} - -static void -impl_requestCreateItem (PortableServer_Servant servant, - const CORBA_char *item_type_name, - CORBA_Environment *ev) -{ - MailComponent *mc = MAIL_COMPONENT(bonobo_object_from_servant(servant)); - - if (create_item(item_type_name, mc->priv->model, NULL, NULL) == -1) { - CORBA_exception_set (ev, CORBA_USER_EXCEPTION, - ex_GNOME_Evolution_Component_UnknownType, NULL); - } -} - -static void -handleuri_got_folder(char *uri, CamelFolder *folder, void *data) -{ - CamelURL *url = data; - EMMessageBrowser *emmb; - - if (folder != NULL) { - const char *reply = camel_url_get_param(url, "reply"); - const char *forward = camel_url_get_param(url, "forward"); - int mode; - - if (reply) { - - if (!strcmp(reply, "all")) - mode = REPLY_MODE_ALL; - else if (!strcmp(reply, "list")) - mode = REPLY_MODE_LIST; - else /* if "sender" or anything else */ - mode = REPLY_MODE_SENDER; - - em_utils_reply_to_message(folder, camel_url_get_param(url, "uid"), NULL, mode, NULL); - } else if (forward) { - GPtrArray *uids; - const char* uid; - - uid = camel_url_get_param(url, "uid"); - if (uid == NULL) - g_warning("Could not forward the message. UID is NULL."); - else { - uids = g_ptr_array_new(); - g_ptr_array_add(uids, g_strdup(uid)); - - if (!strcmp(forward, "attached")) - em_utils_forward_attached(folder, uids, uri); - else if (!strcmp(forward, "inline")) - em_utils_forward_inline(folder, uids, uri); - else if (!strcmp(forward, "quoted")) - em_utils_forward_quoted(folder, uids, uri); - else { /* Just the default forward */ - em_utils_forward_messages(folder, uids, uri); - } - } - } else { - emmb = (EMMessageBrowser *)em_message_browser_window_new(); - /*message_list_set_threaded(((EMFolderView *)emmb)->list, emfv->list->threaded);*/ - /* FIXME: session needs to be passed easier than this */ - em_format_set_session((EMFormat *)((EMFolderView *)emmb)->preview, session); - em_folder_view_set_folder((EMFolderView *)emmb, folder, uri); - em_folder_view_set_message((EMFolderView *)emmb, camel_url_get_param(url, "uid"), FALSE); - gtk_widget_show(emmb->window); - } - } else { - g_warning("Couldn't open folder '%s'", uri); - } - camel_url_free(url); -} - -static void -impl_handleURI (PortableServer_Servant servant, const char *uri, CORBA_Environment *ev) -{ - if (!strncmp (uri, "mailto:", 7)) { - if (!em_utils_check_user_can_send_mail(NULL)) - return; - - em_utils_compose_new_message_with_mailto (uri, NULL); - } else if (!strncmp(uri, "email:", 6)) { - CamelURL *url = camel_url_new(uri, NULL); - - if (camel_url_get_param(url, "uid") != NULL) { - char *curi = em_uri_to_camel(uri); - - mail_get_folder(curi, 0, handleuri_got_folder, url, mail_msg_unordered_push); - g_free(curi); - } else { - g_warning("email uri's must include a uid parameter"); - camel_url_free(url); - } - } -} - -static void -impl_sendAndReceive (PortableServer_Servant servant, CORBA_Environment *ev) -{ - em_utils_clear_get_password_canceled_accounts_flag (); - mail_send_receive (); -} - -static void -impl_upgradeFromVersion (PortableServer_Servant servant, const short major, const short minor, const short revision, CORBA_Environment *ev) -{ - MailComponent *component; - CamelException ex; - - component = mail_component_peek (); - - camel_exception_init (&ex); - if (em_migrate (e_get_user_data_dir (), major, minor, revision, &ex) == -1) { - GNOME_Evolution_Component_UpgradeFailed *failedex; - - failedex = GNOME_Evolution_Component_UpgradeFailed__alloc(); - failedex->what = CORBA_string_dup(_("Failed upgrading Mail settings or folders.")); - failedex->why = CORBA_string_dup(ex.desc); - CORBA_exception_set(ev, CORBA_USER_EXCEPTION, ex_GNOME_Evolution_Component_UpgradeFailed, failedex); - } - - camel_exception_clear (&ex); -} - -static void -mc_sync_store_done (CamelStore *store, void *data) -{ - MailComponent *mc = (MailComponent *) data; - - mc->priv->mail_sync_in_progress--; -} - -static void -mc_sync_store (gpointer key, gpointer value, gpointer user_data) -{ - extern int camel_application_is_exiting; - MailComponent *mc = (MailComponent *) user_data; - - mc->priv->mail_sync_in_progress++; - - if (!camel_application_is_exiting) - mail_sync_store (CAMEL_STORE (key), FALSE, mc_sync_store_done, mc); - else - mc_sync_store_done (CAMEL_STORE (key), mc); -} - -static gboolean -call_mail_sync (gpointer user_data) -{ - extern int camel_application_is_exiting; - MailComponent *mc = (MailComponent *)user_data; - - if (camel_application_is_exiting) - return FALSE; - - if (!mc->priv->mail_sync_in_progress && session && camel_session_is_online (session)) - mail_component_stores_foreach (mc, mc_sync_store, mc); - - return !camel_application_is_exiting; -} - -struct _setline_data { - GNOME_Evolution_Listener listener; - CORBA_boolean status; - int pending; -}; - -static void -setline_done(CamelStore *store, void *data) -{ - struct _setline_data *sd = data; - - g_return_if_fail (sd->pending > 0); - - sd->pending--; - if (sd->pending == 0) { - CORBA_Environment ev = { NULL }; - - GNOME_Evolution_Listener_complete(sd->listener, &ev); - CORBA_exception_free(&ev); - CORBA_Object_release(sd->listener, &ev); - CORBA_exception_free(&ev); - if (!sd->status) - camel_session_set_online(session, sd->status); - g_free(sd); - } -} - -static void -setline_check(void *key, void *value, void *data) -{ - CamelService *service = key; - struct _setline_data *sd = data; - - if (CAMEL_IS_DISCO_STORE(service) - || CAMEL_IS_OFFLINE_STORE(service)) { - sd->pending++; - mail_store_set_offline((CamelStore *)service, !sd->status, setline_done, sd); - } -} - -int -status_check (GNOME_Evolution_ShellState shell_state) -{ - int status = 0; - - switch (shell_state) - { - case GNOME_Evolution_USER_OFFLINE: - status = OFFLINE; - if (em_utils_prompt_user (NULL, "/apps/evolution/mail/prompts/quick_offline", "mail:ask-quick-offline", NULL)) - break; - case GNOME_Evolution_FORCED_OFFLINE: - /*Network is down so change network state on the camel session*/ - status = OFFLINE; - /* Cancel all operations as they wont happen anyway cos Network is down*/ - mail_cancel_all (); - camel_session_set_network_state (session, FALSE); - break; - case GNOME_Evolution_USER_ONLINE: - camel_session_set_network_state (session, TRUE); - status = ONLINE; - } - - return status; -} - -static void -impl_setLineStatus(PortableServer_Servant servant, GNOME_Evolution_ShellState shell_state, GNOME_Evolution_Listener listener, CORBA_Environment *ev) -{ - struct _setline_data *sd; - int status = status_check(shell_state); - - /* This will dis/enable further auto-mail-check action. */ - /* FIXME: If send/receive active, wait for it to finish? */ - if (status) - camel_session_set_online(session, status); - - sd = g_malloc0(sizeof(*sd)); - sd->status = status; - sd->listener = CORBA_Object_duplicate(listener, ev); - if (ev->_major == CORBA_NO_EXCEPTION) - mail_component_stores_foreach(mail_component_peek(), setline_check, sd); - else - CORBA_exception_free(ev); - - if (sd->pending == 0) { - if (sd->listener) { - CORBA_Object_release(sd->listener, ev); - CORBA_exception_free(ev); - } - - g_free(sd); - - if (!status) - camel_session_set_online(session, status); - GNOME_Evolution_Listener_complete(listener, ev); - } -} - -static void -impl_mail_test(PortableServer_Servant servant, CORBA_Environment *ev) -{ - printf("*** Testing mail interface!! ***\n"); -} - /* Initialization. */ static void @@ -1253,25 +458,22 @@ mail_component_class_init (MailComponentClass *class) epv->createView = impl_createView; epv->requestQuit = impl_requestQuit; epv->quit = impl_quit; - epv->_get_userCreatableItems = impl__get_userCreatableItems; - epv->requestCreateItem = impl_requestCreateItem; - epv->handleURI = impl_handleURI; - epv->sendAndReceive = impl_sendAndReceive; - epv->upgradeFromVersion = impl_upgradeFromVersion; - epv->setLineStatus = impl_setLineStatus; +// epv->_get_userCreatableItems = impl__get_userCreatableItems; +// epv->requestCreateItem = impl_requestCreateItem; +// epv->handleURI = impl_handleURI; +// epv->sendAndReceive = impl_sendAndReceive; +// epv->upgradeFromVersion = impl_upgradeFromVersion; +// epv->setLineStatus = impl_setLineStatus; - mepv->test = impl_mail_test; - - /* Register attachment handler types. */ - e_attachment_handler_mail_get_type (); +// mepv->test = impl_mail_test; } -static void -store_hash_free (struct _store_info *si) -{ - si->removed = 1; - store_info_unref(si); -} +//static void +//store_hash_free (struct _store_info *si) +//{ +// si->removed = 1; +// store_info_unref(si); +//} static void mail_component_init (MailComponent *component) @@ -1284,318 +486,42 @@ mail_component_init (MailComponent *component) priv->lock = g_mutex_new(); priv->quit_state = -1; - /* FIXME This is used as both a filename and URI path throughout - * the mail code. Need to clean this up; maybe provide a - * mail_component_get_base_uri() function. */ - priv->base_directory = g_build_filename (e_get_user_data_dir (), "mail", NULL); -#ifdef G_OS_WIN32 - { - char *p = priv->base_directory; - while ((p = strchr(p, '\\'))) - *p++ = '/'; - } -#endif - - if (g_mkdir_with_parents (e_get_user_data_dir (), 0777) == -1 && errno != EEXIST) - abort (); - - priv->model = em_folder_tree_model_new (e_get_user_data_dir ()); +// /* FIXME This is used as both a filename and URI path throughout +// * the mail code. Need to clean this up; maybe provide a +// * mail_component_get_base_uri() function. */ +// priv->base_directory = g_build_filename (e_get_user_data_dir (), "mail", NULL); +//#ifdef G_OS_WIN32 +// { +// char *p = priv->base_directory; +// while ((p = strchr(p, '\\'))) +// *p++ = '/'; +// } +//#endif + +// if (g_mkdir_with_parents (e_get_user_data_dir (), 0777) == -1 && errno != EEXIST) +// abort (); + +// priv->model = em_folder_tree_model_new (e_get_user_data_dir ()); priv->logger = e_logger_create ("mail"); priv->activity_handler = e_activity_handler_new (); e_activity_handler_set_logger (priv->activity_handler, priv->logger); e_activity_handler_set_error_flush_time (priv->activity_handler, mail_config_get_error_timeout ()*1000); - mail_session_init (e_get_user_data_dir ()); - - priv->async_event = mail_async_event_new(); - priv->store_hash = g_hash_table_new_full ( - NULL, NULL, - (GDestroyNotify) NULL, - (GDestroyNotify) store_hash_free); - - mail_autoreceive_init (session); - - priv->mail_sync_in_progress = 0; - if (g_getenv("CAMEL_FLUSH_CHANGES")) - priv->mail_sync_id = g_timeout_add_seconds (mail_config_get_sync_timeout (), call_mail_sync, component); - else - priv->mail_sync_id = 0; -} - -/* Public API. */ -MailComponent * -mail_component_peek (void) -{ - static MailComponent *component = NULL; - - if (component == NULL) - component = g_object_new(mail_component_get_type(), NULL); - - return component; -} - -const char * -mail_component_peek_base_directory (MailComponent *component) -{ - MAIL_COMPONENT_DEFAULT(component); - - return component->priv->base_directory; -} - -RuleContext * -mail_component_peek_search_context (MailComponent *component) -{ - MAIL_COMPONENT_DEFAULT(component); - - setup_search_context(component); - - return component->priv->search_context; -} - -EActivityHandler * -mail_component_peek_activity_handler (MailComponent *component) -{ - MAIL_COMPONENT_DEFAULT(component); - - return component->priv->activity_handler; -} - -struct _CamelSession *mail_component_peek_session(MailComponent *component) -{ - MAIL_COMPONENT_DEFAULT(component); - - return session; -} - -void -mail_component_add_store (MailComponent *component, CamelStore *store, const char *name) -{ - mc_add_store(component, store, name, NULL); -} - -/** - * mail_component_load_store_by_uri: - * @component: mail component - * @uri: uri of store - * @name: name of store (used for display purposes) - * - * Return value: Pointer to the newly added CamelStore. The caller is supposed - * to ref the object if it wants to store it. - **/ -CamelStore * -mail_component_load_store_by_uri (MailComponent *component, const char *uri, const char *name) -{ - CamelException ex; - CamelStore *store; - CamelProvider *prov; - - MAIL_COMPONENT_DEFAULT(component); - - camel_exception_init (&ex); - - /* Load the service (don't connect!). Check its provider and - * see if this belongs in the shell's folder list. If so, add - * it. - */ - - prov = camel_provider_get(uri, &ex); - if (prov == NULL) { - /* EPFIXME: real error dialog */ - g_warning ("couldn't get service %s: %s\n", uri, - camel_exception_get_description (&ex)); - camel_exception_clear (&ex); - return NULL; - } - - if (!(prov->flags & CAMEL_PROVIDER_IS_STORAGE)) - return NULL; - - store = (CamelStore *) camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, &ex); - if (store == NULL) { - /* EPFIXME: real error dialog */ - g_warning ("couldn't get service %s: %s\n", uri, - camel_exception_get_description (&ex)); - camel_exception_clear (&ex); - return NULL; - } - - mail_component_add_store(component, store, name); - camel_object_unref (store); - - return store; -} - -static void -store_disconnect (CamelStore *store, void *event_data, void *user_data) -{ - camel_service_disconnect (CAMEL_SERVICE (store), TRUE, NULL); - camel_object_unref (store); -} - -void -mail_component_remove_store (MailComponent *component, CamelStore *store) -{ - MailComponentPrivate *priv; - - MAIL_COMPONENT_DEFAULT(component); - - priv = component->priv; - - /* Because the store_hash holds a reference to each store - * used as a key in it, none of them will ever be gc'ed, meaning - * any call to camel_session_get_{service,store} with the same - * URL will always return the same object. So this works. - */ - - if (g_hash_table_lookup (priv->store_hash, store) == NULL) - return; - - camel_object_ref (store); - g_hash_table_remove (priv->store_hash, store); - - /* so i guess potentially we could have a race, add a store while one - being removed. ?? */ - mail_note_store_remove (store); - - em_folder_tree_model_remove_store (priv->model, store); - - mail_async_event_emit (priv->async_event, MAIL_ASYNC_THREAD, (MailAsyncFunc) store_disconnect, store, NULL, NULL); -} - -void -mail_component_remove_store_by_uri (MailComponent *component, const char *uri) -{ - CamelProvider *prov; - CamelStore *store; - - MAIL_COMPONENT_DEFAULT(component); - - if (!(prov = camel_provider_get(uri, NULL))) - return; - - if (!(prov->flags & CAMEL_PROVIDER_IS_STORAGE)) - return; - - store = (CamelStore *) camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, NULL); - if (store != NULL) { - mail_component_remove_store (component, store); - camel_object_unref (store); - } -} - -int -mail_component_get_store_count (MailComponent *component) -{ - MAIL_COMPONENT_DEFAULT(component); - - return g_hash_table_size (component->priv->store_hash); -} - -/* need to map from internal struct to external api */ -struct _store_foreach_data { - GHFunc func; - void *data; -}; - -static void -mc_stores_foreach(CamelStore *store, struct _store_info *si, struct _store_foreach_data *data) -{ - data->func((void *)store, (void *)si->name, data->data); -} - -void -mail_component_stores_foreach (MailComponent *component, GHFunc func, void *user_data) -{ - struct _store_foreach_data data = { func, user_data }; - - MAIL_COMPONENT_DEFAULT(component); - - g_hash_table_foreach (component->priv->store_hash, (GHFunc)mc_stores_foreach, &data); -} - -void -mail_component_remove_folder (MailComponent *component, CamelStore *store, const char *path) -{ - MAIL_COMPONENT_DEFAULT(component); - - /* FIXME: implement me. but first, am I really even needed? */ -} - -EMFolderTreeModel * -mail_component_peek_tree_model (MailComponent *component) -{ - MAIL_COMPONENT_DEFAULT(component); - - return component->priv->model; -} - -CamelStore * -mail_component_peek_local_store (MailComponent *mc) -{ - MAIL_COMPONENT_DEFAULT (mc); - mc_setup_local_store (mc); - - return mc->priv->local_store; -} +// mail_session_init (e_get_user_data_dir ()); -/** - * mail_component_get_folder: - * @mc: - * @id: - * - * Get a standard/default folder by id. This call is thread-safe. - * - * Return value: - **/ -struct _CamelFolder * -mail_component_get_folder(MailComponent *mc, enum _mail_component_folder_t id) -{ - g_return_val_if_fail (id <= MAIL_COMPONENT_FOLDER_LOCAL_INBOX, NULL); +// priv->async_event = mail_async_event_new(); +// priv->store_hash = g_hash_table_new_full ( +// NULL, NULL, +// (GDestroyNotify) NULL, +// (GDestroyNotify) store_hash_free); - MAIL_COMPONENT_DEFAULT(mc); - mc_setup_local_store(mc); +// mail_autoreceive_init (session); - return mc_default_folders[id].folder; -} - -/** - * mail_component_get_folder_uri: - * @mc: - * @id: - * - * Get a standard/default folder's uri. This call is thread-safe. - * - * Return value: - **/ -const char * -mail_component_get_folder_uri(MailComponent *mc, enum _mail_component_folder_t id) -{ - g_return_val_if_fail (id <= MAIL_COMPONENT_FOLDER_LOCAL_INBOX, NULL); - - MAIL_COMPONENT_DEFAULT(mc); - mc_setup_local_store(mc); - - return mc_default_folders[id].uri; -} - -/** - * mail_indicate_new_mail - * Indicates new mail in a shell window. - * @param have_new_mail TRUE when have new mail, false otherwise. - **/ -void -mail_indicate_new_mail (gboolean have_new_mail) -{ - const char *icon = NULL; - MailComponent *mc = mail_component_peek (); - - g_return_if_fail (mc != NULL); - - if (have_new_mail) - icon = "mail-unread"; - - if (mc->priv->component_view) - e_component_view_set_button_icon (mc->priv->component_view, icon); +// priv->mail_sync_in_progress = 0; +// if (g_getenv("CAMEL_FLUSH_CHANGES")) +// priv->mail_sync_id = g_timeout_add_seconds (mail_config_get_sync_timeout (), call_mail_sync, component); +// else +// priv->mail_sync_id = 0; } void @@ -1606,5 +532,3 @@ mail_component_show_logger (gpointer top) eni_show_logger(logger, top, MAILER_ERROR_TIME_OUT_KEY, MAILER_ERROR_LEVEL_KEY); } - -BONOBO_TYPE_FUNC_FULL (MailComponent, GNOME_Evolution_MailComponent, PARENT_TYPE, mail_component) diff --git a/mail/mail-component.h b/mail/mail-component.h index 3aa088c890..41f331d812 100644 --- a/mail/mail-component.h +++ b/mail/mail-component.h @@ -71,8 +71,6 @@ const char *mail_component_peek_base_directory (MailComponent *componen struct _RuleContext *mail_component_peek_search_context (MailComponent *component); struct _EActivityHandler *mail_component_peek_activity_handler (MailComponent *component); -struct _CamelSession *mail_component_peek_session(MailComponent *); - void mail_component_add_store (MailComponent *component, struct _CamelStore *store, const char *name); diff --git a/mail/mail-config-factory.c b/mail/mail-config-factory.c deleted file mode 100644 index 74c05ec8fc..0000000000 --- a/mail/mail-config-factory.c +++ /dev/null @@ -1,63 +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: - * 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 "em-account-prefs.h" -#include "em-composer-prefs.h" -#include "em-mailer-prefs.h" -#include "em-network-prefs.h" - -#include "mail-config-factory.h" - -#define CONFIG_CONTROL_FACTORY_ID "OAFIID:GNOME_Evolution_Mail_ConfigControlFactory:" BASE_VERSION - -BonoboObject * -mail_config_control_factory_cb (BonoboGenericFactory *factory, const char *component_id, void *user_data) -{ - GNOME_Evolution_Shell shell = (GNOME_Evolution_Shell) user_data; - EvolutionConfigControl *control; - GtkWidget *prefs = NULL; - - if (!strcmp (component_id, EM_ACCOUNT_PREFS_CONTROL_ID)) { - prefs = em_account_prefs_new (shell); - } else if (!strcmp (component_id, EM_MAILER_PREFS_CONTROL_ID)) { - prefs = em_mailer_prefs_new (); - } else if (!strcmp (component_id, EM_COMPOSER_PREFS_CONTROL_ID)) { - prefs = em_composer_prefs_new (); - } else if (!strcmp (component_id, EM_NETWORK_PREFS_CONTROL_ID)) { - prefs = em_network_prefs_new (); - } else { - g_return_val_if_reached(NULL); - } - - gtk_widget_show_all (prefs); - - control = evolution_config_control_new (prefs); - - return BONOBO_OBJECT (control); -} diff --git a/mail/mail-config-factory.h b/mail/mail-config-factory.h deleted file mode 100644 index f3a4b5fd29..0000000000 --- a/mail/mail-config-factory.h +++ /dev/null @@ -1,44 +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: - * Jeffrey Stedfast <fejj@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __MAIL_CONFIG_FACTORY_H__ -#define __MAIL_CONFIG_FACTORY_H__ - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include <bonobo/bonobo-generic-factory.h> -#include "evolution-config-control.h" - -#include <shell/Evolution.h> - -gboolean mail_config_register_factory (GNOME_Evolution_Shell shell); - -BonoboObject *mail_config_control_factory_cb (BonoboGenericFactory *factory, const char *component_id, void *user_data); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __MAIL_CONFIG_FACTORY_H__ */ diff --git a/mail/mail-config.c b/mail/mail-config.c index 5fa562e399..be5b0164ee 100644 --- a/mail/mail-config.c +++ b/mail/mail-config.c @@ -37,10 +37,7 @@ #include <gtk/gtk.h> #include <glib/gstdio.h> - -#ifndef G_OS_WIN32 -#include <sys/wait.h> -#endif +#include <glib/gi18n-lib.h> #include <gtkhtml/gtkhtml.h> #include <glade/glade.h> @@ -48,19 +45,11 @@ #include <libxml/tree.h> #include <libxml/parser.h> -#include <bonobo/bonobo-object.h> -#include <bonobo/bonobo-generic-factory.h> -#include <bonobo/bonobo-context.h> -#include <bonobo/bonobo-moniker-util.h> -#include <bonobo/bonobo-exception.h> - #include <libedataserver/e-data-server-util.h> #include <e-util/e-util.h> #include <misc/e-gui-utils.h> -#include "e-util/e-util-labels.h" - -#include <libedataserver/e-account-list.h> -#include <e-util/e-signature-list.h> +#include "e-util/e-account-utils.h" +#include "e-util/e-signature-utils.h" #include <camel/camel-service.h> #include <camel/camel-stream-mem.h> @@ -70,22 +59,18 @@ #include <libedataserverui/e-passwords.h> -#include "mail-component.h" #include "mail-session.h" #include "mail-config.h" #include "mail-mt.h" #include "mail-tools.h" +#include "e-mail-shell-module.h" + typedef struct { GConfClient *gconf; - gboolean corrupt; - char *gtkrc; - EAccountList *accounts; - ESignatureList *signatures; - GSList *labels; gboolean address_compress; @@ -109,18 +94,6 @@ static MailConfig *config = NULL; static guint config_write_timeout = 0; -void -mail_config_save_accounts (void) -{ - e_account_list_save (config->accounts); -} - -void -mail_config_save_signatures (void) -{ - e_signature_list_save (config->signatures); -} - static void config_clear_mime_types (void) { @@ -214,33 +187,6 @@ config_write_style (void) } static void -config_clear_labels (void) -{ - if (!config) - return; - - e_util_labels_free (config->labels); - config->labels = NULL; -} - -static void -config_cache_labels (GConfClient *client) -{ - if (!config) - return; - - config->labels = e_util_labels_parse (client); -} - -static void -gconf_labels_changed (GConfClient *client, guint cnxn_id, - GConfEntry *entry, gpointer user_data) -{ - config_clear_labels (); - config_cache_labels (client); -} - -static void gconf_style_changed (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data) { @@ -369,9 +315,6 @@ mail_config_init (void) mail_config_clear (); - config->accounts = e_account_list_new (config->gconf); - config->signatures = e_signature_list_new (config->gconf); - gtk_rc_parse (config->gtkrc); /* Composer Configuration */ @@ -474,18 +417,6 @@ mail_config_init (void) gconf_client_notify_add ( config->gconf, key, func, NULL, NULL, NULL); - /* Label Configuration */ - - gconf_client_add_dir ( - config->gconf, E_UTIL_LABELS_GCONF_KEY, - GCONF_CLIENT_PRELOAD_ONELEVEL, NULL); - - gconf_client_notify_add ( - config->gconf, E_UTIL_LABELS_GCONF_KEY, - gconf_labels_changed, NULL, NULL, NULL); - - config_cache_labels (config->gconf); - /* MIME Type Configuration */ gconf_client_add_dir ( @@ -550,17 +481,6 @@ mail_config_clear (void) if (!config) return; - if (config->accounts) { - g_object_unref (config->accounts); - config->accounts = NULL; - } - - if (config->signatures) { - g_object_unref (config->signatures); - config->signatures = NULL; - } - - config_clear_labels (); config_clear_mime_types (); } @@ -568,11 +488,17 @@ mail_config_clear (void) void mail_config_write (void) { + EAccountList *account_list; + ESignatureList *signature_list; + if (!config) return; - e_account_list_save (config->accounts); - e_signature_list_save (config->signatures); + account_list = e_get_account_list (); + signature_list = e_get_signature_list (); + + e_account_list_save (account_list); + e_signature_list_save (signature_list); gconf_client_suggest_sync (config->gconf, NULL); } @@ -580,6 +506,7 @@ mail_config_write (void) void mail_config_write_on_exit (void) { + EAccountList *account_list; EAccount *account; EIterator *iter; @@ -593,7 +520,8 @@ mail_config_write_on_exit (void) /* then we make sure the ones we want to remember are in the session cache */ - iter = e_list_get_iterator ((EList *) config->accounts); + account_list = e_get_account_list (); + iter = e_list_get_iterator ((EList *) account_list); while (e_iterator_is_valid (iter)) { char *passwd; @@ -622,7 +550,7 @@ mail_config_write_on_exit (void) e_passwords_clear_passwords ("Mail"); /* then we remember them */ - iter = e_list_get_iterator ((EList *) config->accounts); + iter = e_list_get_iterator ((EList *) account_list); while (e_iterator_is_valid (iter)) { account = (EAccount *) e_iterator_get (iter); @@ -656,18 +584,6 @@ mail_config_get_gconf_client (void) return config->gconf; } -gboolean -mail_config_is_configured (void) -{ - return e_list_length ((EList *) config->accounts) > 0; -} - -gboolean -mail_config_is_corrupt (void) -{ - return config->corrupt; -} - int mail_config_get_address_count (void) { @@ -735,74 +651,16 @@ mail_config_get_enable_magic_spacebar () return config->magic_spacebar; } -/** - * mail_config_get_labels - * - * @return list of known labels, each member data is EUtilLabel structure. - * Returned list should not be freed, neither data inside it. - **/ -GSList * -mail_config_get_labels (void) -{ - return config->labels; -} - const char ** mail_config_get_allowable_mime_types (void) { return (const char **) config->mime_types->pdata; } -gboolean -mail_config_find_account (EAccount *account) -{ - EAccount *acnt; - EIterator *iter; - - iter = e_list_get_iterator ((EList *) config->accounts); - while (e_iterator_is_valid (iter)) { - acnt = (EAccount *) e_iterator_get (iter); - if (acnt == account) { - g_object_unref (iter); - return TRUE; - } - - e_iterator_next (iter); - } - - g_object_unref (iter); - - return FALSE; -} - -EAccount * -mail_config_get_default_account (void) -{ - if (config == NULL) - mail_config_init (); - - if (!config->accounts) - return NULL; - - /* should probably return const */ - return (EAccount *)e_account_list_get_default(config->accounts); -} - -EAccount * -mail_config_get_account_by_name (const char *account_name) -{ - return (EAccount *)e_account_list_find(config->accounts, E_ACCOUNT_FIND_NAME, account_name); -} - -EAccount * -mail_config_get_account_by_uid (const char *uid) -{ - return (EAccount *) e_account_list_find (config->accounts, E_ACCOUNT_FIND_UID, uid); -} - static EAccount * mc_get_account_by (const char *given_url, const char * (get_url_string)(EAccount *account)) { + EAccountList *account_list; EAccount *account = NULL; EIterator *iter; CamelURL *url; @@ -817,7 +675,8 @@ mc_get_account_by (const char *given_url, const char * (get_url_string)(EAccount provider = camel_provider_get (given_url, NULL); g_return_val_if_fail (provider != NULL && provider->url_equal != NULL, NULL); - iter = e_list_get_iterator ((EList *) config->accounts); + account_list = e_get_account_list (); + iter = e_list_get_iterator ((EList *) account_list); while (account == NULL && e_iterator_is_valid (iter)) { CamelURL *account_url; const char *account_url_string; @@ -879,77 +738,21 @@ mail_config_get_account_by_transport_url (const char *transport_url) return mc_get_account_by (transport_url, get_transport_url_string); } -int -mail_config_has_proxies (EAccount *account) -{ - return e_account_list_account_has_proxies (config->accounts, account); -} - -void -mail_config_remove_account_proxies (EAccount *account) -{ - e_account_list_remove_account_proxies (config->accounts, account); -} - -void -mail_config_prune_proxies (void) -{ - e_account_list_prune_proxies (config->accounts); -} - -EAccountList * -mail_config_get_accounts (void) -{ - if (config == NULL) - mail_config_init (); - - return config->accounts; -} - -void -mail_config_add_account (EAccount *account) -{ - e_account_list_add(config->accounts, account); - mail_config_save_accounts (); -} - -void -mail_config_remove_account (EAccount *account) -{ - e_account_list_remove(config->accounts, account); - mail_config_save_accounts (); -} - -void -mail_config_set_default_account (EAccount *account) -{ - e_account_list_set_default(config->accounts, account); -} - -EAccountIdentity * -mail_config_get_default_identity (void) -{ - EAccount *account; - - account = mail_config_get_default_account (); - if (account) - return account->id; - else - return NULL; -} - EAccountService * mail_config_get_default_transport (void) { + EAccountList *account_list; EAccount *account; EIterator *iter; - account = mail_config_get_default_account (); + account_list = e_get_account_list (); + account = e_get_default_account (); + if (account && account->enabled && account->transport && account->transport->url && account->transport->url[0]) return account->transport; /* return the first account with a transport? */ - iter = e_list_get_iterator ((EList *) config->accounts); + iter = e_list_get_iterator ((EList *) account_list); while (e_iterator_is_valid (iter)) { account = (EAccount *) e_iterator_get (iter); @@ -970,17 +773,19 @@ mail_config_get_default_transport (void) static char * uri_to_evname (const char *uri, const char *prefix) { - const char *base_directory = mail_component_peek_base_directory (mail_component_peek ()); + const gchar *data_dir; char *safe; char *tmp; + data_dir = e_shell_module_get_data_dir (mail_shell_module); + safe = g_strdup (uri); e_filename_make_safe (safe); /* blah, easiest thing to do */ if (prefix[0] == '*') - tmp = g_strdup_printf ("%s/%s%s.xml", base_directory, prefix + 1, safe); + tmp = g_strdup_printf ("%s/%s%s.xml", data_dir, prefix + 1, safe); else - tmp = g_strdup_printf ("%s/%s%s", base_directory, prefix, safe); + tmp = g_strdup_printf ("%s/%s%s", data_dir, prefix, safe); g_free (safe); return tmp; } @@ -988,6 +793,7 @@ uri_to_evname (const char *uri, const char *prefix) void mail_config_uri_renamed (GCompareFunc uri_cmp, const char *old, const char *new) { + EAccountList *account_list; EAccount *account; EIterator *iter; int i, work = 0; @@ -999,7 +805,8 @@ mail_config_uri_renamed (GCompareFunc uri_cmp, const char *old, const char *new) "*views/custom_view-", NULL }; - iter = e_list_get_iterator ((EList *) config->accounts); + account_list = e_get_account_list (); + iter = e_list_get_iterator ((EList *) account_list); while (e_iterator_is_valid (iter)) { account = (EAccount *) e_iterator_get (iter); @@ -1040,26 +847,33 @@ mail_config_uri_renamed (GCompareFunc uri_cmp, const char *old, const char *new) void mail_config_uri_deleted (GCompareFunc uri_cmp, const char *uri) { + EAccountList *account_list; EAccount *account; EIterator *iter; int work = 0; + const gchar *local_drafts_folder_uri; + const gchar *local_sent_folder_uri; + /* assumes these can't be removed ... */ - const char *default_sent_folder_uri = mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_SENT); - const char *default_drafts_folder_uri = mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_DRAFTS); + local_drafts_folder_uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, E_MAIL_FOLDER_DRAFTS); + local_sent_folder_uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, E_MAIL_FOLDER_SENT); - iter = e_list_get_iterator ((EList *) config->accounts); + account_list = e_get_account_list (); + iter = e_list_get_iterator ((EList *) account_list); while (e_iterator_is_valid (iter)) { account = (EAccount *) e_iterator_get (iter); if (account->sent_folder_uri && uri_cmp (account->sent_folder_uri, uri)) { g_free (account->sent_folder_uri); - account->sent_folder_uri = g_strdup (default_sent_folder_uri); + account->sent_folder_uri = g_strdup (local_sent_folder_uri); work = 1; } if (account->drafts_folder_uri && uri_cmp (account->drafts_folder_uri, uri)) { g_free (account->drafts_folder_uri); - account->drafts_folder_uri = g_strdup (default_drafts_folder_uri); + account->drafts_folder_uri = g_strdup (local_drafts_folder_uri); work = 1; } @@ -1092,114 +906,19 @@ char * mail_config_folder_to_cachename (CamelFolder *folder, const char *prefix) { char *url, *basename, *filename; - const char *evolution_dir; + const gchar *config_dir; - evolution_dir = mail_component_peek_base_directory (mail_component_peek ()); + config_dir = e_shell_module_get_config_dir (mail_shell_module); url = mail_config_folder_to_safe_url (folder); basename = g_strdup_printf ("%s%s", prefix, url); - filename = g_build_filename (evolution_dir, "config", basename, NULL); + filename = g_build_filename (config_dir, basename, NULL); g_free (basename); g_free (url); return filename; } -ESignatureList * -mail_config_get_signatures (void) -{ - return config->signatures; -} - -static char * -get_new_signature_filename (void) -{ - const char *base_directory; - char *filename, *id; - struct stat st; - int i; - - base_directory = e_get_user_data_dir (); - filename = g_build_filename (base_directory, "signatures", NULL); - if (g_lstat (filename, &st)) { - if (errno == ENOENT) { - if (g_mkdir (filename, 0700)) - g_warning ("Fatal problem creating %s directory.", filename); - } else - g_warning ("Fatal problem with %s directory.", filename); - } - g_free (filename); - - filename = g_malloc (strlen (base_directory) + sizeof ("/signatures/signature-") + 12); - id = g_stpcpy (filename, base_directory); - id = g_stpcpy (id, "/signatures/signature-"); - - for (i = 0; i < (INT_MAX - 1); i++) { - sprintf (id, "%d", i); - if (g_lstat (filename, &st) == -1 && errno == ENOENT) { - int fd; - - fd = g_creat (filename, 0600); - if (fd >= 0) { - close (fd); - return filename; - } - } - } - - g_free (filename); - - return NULL; -} - - -ESignature * -mail_config_signature_new (const char *filename, gboolean script, gboolean html) -{ - ESignature *sig; - - sig = e_signature_new (); - sig->name = g_strdup (_("Unnamed")); - sig->script = script; - sig->html = html; - - if (filename == NULL) - sig->filename = get_new_signature_filename (); - else - sig->filename = g_strdup (filename); - - return sig; -} - -ESignature * -mail_config_get_signature_by_uid (const char *uid) -{ - return (ESignature *) e_signature_list_find (config->signatures, E_SIGNATURE_FIND_UID, uid); -} - -ESignature * -mail_config_get_signature_by_name (const char *name) -{ - return (ESignature *) e_signature_list_find (config->signatures, E_SIGNATURE_FIND_NAME, name); -} - -void -mail_config_add_signature (ESignature *signature) -{ - e_signature_list_add (config->signatures, signature); - mail_config_save_signatures (); -} - -void -mail_config_remove_signature (ESignature *signature) -{ - if (signature->filename && !signature->script) - g_unlink (signature->filename); - - e_signature_list_remove (config->signatures, signature); - mail_config_save_signatures (); -} - void mail_config_reload_junk_headers (void) { @@ -1230,131 +949,3 @@ mail_config_get_lookup_book_local_only (void) return config->book_lookup_local_only; } - -gboolean -mail_config_scripts_disabled (void) -{ - if (config == NULL) - mail_config_init (); - - return config->scripts_disabled; -} - -char * -mail_config_signature_run_script (const char *script) -{ -#ifndef G_OS_WIN32 - int result, status; - int in_fds[2]; - pid_t pid; - - if (mail_config_scripts_disabled ()) - return NULL; - - if (pipe (in_fds) == -1) { - g_warning ("Failed to create pipe to '%s': %s", script, g_strerror (errno)); - return NULL; - } - - if (!(pid = fork ())) { - /* child process */ - int maxfd, i; - - close (in_fds [0]); - if (dup2 (in_fds[1], STDOUT_FILENO) < 0) - _exit (255); - close (in_fds [1]); - - setsid (); - - maxfd = sysconf (_SC_OPEN_MAX); - for (i = 3; i < maxfd; i++) { - if (i != STDIN_FILENO && i != STDOUT_FILENO && i != STDERR_FILENO) - fcntl (i, F_SETFD, FD_CLOEXEC); - } - - execlp("/bin/sh", "/bin/sh", "-c", script, NULL); - g_warning ("Could not execute %s: %s\n", script, g_strerror (errno)); - _exit (255); - } else if (pid < 0) { - g_warning ("Failed to create create child process '%s': %s", script, g_strerror (errno)); - close (in_fds [0]); - close (in_fds [1]); - return NULL; - } else { - CamelStreamFilter *filtered_stream; - CamelStreamMem *memstream; - CamelMimeFilter *charenc; - CamelStream *stream; - GByteArray *buffer; - char *charset; - char *content; - - /* parent process */ - close (in_fds[1]); - - stream = camel_stream_fs_new_with_fd (in_fds[0]); - - memstream = (CamelStreamMem *) camel_stream_mem_new (); - buffer = g_byte_array_new (); - camel_stream_mem_set_byte_array (memstream, buffer); - - camel_stream_write_to_stream (stream, (CamelStream *) memstream); - camel_object_unref (stream); - - /* signature scripts are supposed to generate UTF-8 content, but because users - are known to not ever read the manual... we try to do our best if the - content isn't valid UTF-8 by assuming that the content is in the user's - preferred charset. */ - if (!g_utf8_validate ((char *)buffer->data, buffer->len, NULL)) { - stream = (CamelStream *) memstream; - memstream = (CamelStreamMem *) camel_stream_mem_new (); - camel_stream_mem_set_byte_array (memstream, g_byte_array_new ()); - - filtered_stream = camel_stream_filter_new_with_stream (stream); - camel_object_unref (stream); - - charset = gconf_client_get_string (config->gconf, "/apps/evolution/mail/composer/charset", NULL); - if (charset && *charset) { - if ((charenc = (CamelMimeFilter *) camel_mime_filter_charset_new_convert (charset, "utf-8"))) { - camel_stream_filter_add (filtered_stream, charenc); - camel_object_unref (charenc); - } - } - g_free (charset); - - camel_stream_write_to_stream ((CamelStream *) filtered_stream, (CamelStream *) memstream); - camel_object_unref (filtered_stream); - g_byte_array_free (buffer, TRUE); - - buffer = memstream->buffer; - } - - camel_object_unref (memstream); - - g_byte_array_append (buffer, (const unsigned char *)"", 1); - content = (char *)buffer->data; - g_byte_array_free (buffer, FALSE); - - /* wait for the script process to terminate */ - result = waitpid (pid, &status, 0); - - if (result == -1 && errno == EINTR) { - /* child process is hanging... */ - kill (pid, SIGTERM); - sleep (1); - result = waitpid (pid, &status, WNOHANG); - if (result == 0) { - /* ...still hanging, set phasers to KILL */ - kill (pid, SIGKILL); - sleep (1); - result = waitpid (pid, &status, WNOHANG); - } - } - - return content; - } -#else - return NULL; -#endif -} diff --git a/mail/mail-config.glade b/mail/mail-config.glade index f435b95a63..42c691fb82 100644 --- a/mail/mail-config.glade +++ b/mail/mail-config.glade @@ -1,9671 +1,5589 @@ -<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> -<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> - +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> +<!--*- mode: xml -*--> <glade-interface> -<requires lib="gnome"/> - -<widget class="GtkWindow" id="account_druid"> - <property name="title" translatable="yes">Evolution Account Assistant</property> - <property name="type">GTK_WINDOW_TOPLEVEL</property> - <property name="window_position">GTK_WIN_POS_NONE</property> - <property name="modal">False</property> - <property name="resizable">True</property> - <property name="destroy_with_parent">False</property> - <property name="decorated">True</property> - <property name="skip_taskbar_hint">False</property> - <property name="skip_pager_hint">False</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> - <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> - <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> - - <child> - <widget class="GnomeDruid" id="druid"> - <property name="border_width">4</property> - <property name="visible">True</property> - <property name="show_help">False</property> - - <child> - <widget class="GnomeDruidPageEdge" id="start_page"> - <property name="visible">True</property> - <property name="position">GNOME_EDGE_START</property> - <property name="title" translatable="yes">Mail Configuration</property> - <property name="text" translatable="yes">Welcome to the Evolution Mail Configuration Assistant. - -Click "Forward" to begin. </property> - </widget> - </child> - - <child> - <widget class="GnomeDruidPageStandard" id="identity_page"> - <property name="visible">True</property> - <property name="title" translatable="yes">Identity</property> - - <child internal-child="vbox"> - <widget class="GtkVBox" id="druid_identity_vbox"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="identity_help"> - <property name="visible">True</property> - <property name="label" translatable="yes">Please enter your name and email address below. The "optional" fields below do not need to be filled in, unless you wish to include this information in email you send.</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">True</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <placeholder/> - </child> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GnomeDruidPageStandard" id="source_page"> - <property name="visible">True</property> - <property name="title" translatable="yes">Receiving Email</property> - - <child internal-child="vbox"> - <widget class="GtkVBox" id="druid_source_vbox"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="extra_help"> - <property name="visible">True</property> - <property name="label" translatable="yes">Please select among the following options</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">True</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <placeholder/> - </child> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GnomeDruidPageStandard" id="transport_page"> - <property name="visible">True</property> - <property name="title" translatable="yes">Sending Email</property> - - <child internal-child="vbox"> - <widget class="GtkVBox" id="druid_transport_vbox"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="transport_help"> - <property name="visible">True</property> - <property name="label" translatable="yes">Please enter information about the way you will send mail. If you are not sure, ask your system administrator or Internet Service Provider.</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">True</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <placeholder/> - </child> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GnomeDruidPageStandard" id="management_page"> - <property name="visible">True</property> - <property name="title" translatable="yes">Account Management</property> - - <child internal-child="vbox"> - <widget class="GtkVBox" id="druid_management_vbox"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="management_help"> - <property name="visible">True</property> - <property name="label" translatable="yes">Please enter a descriptive name for this account in the space below. + <requires lib="gnome"/> + <widget class="GtkWindow" id="account_druid"> + <property name="title" translatable="yes">Evolution Account Assistant</property> + <child> + <widget class="GnomeDruid" id="druid"> + <property name="visible">True</property> + <property name="border_width">4</property> + <child> + <widget class="GnomeDruidPageEdge" id="start_page"> + <property name="visible">True</property> + <property name="position">GNOME_EDGE_START</property> + <property name="title" translatable="yes">Mail Configuration</property> + <property name="text" translatable="yes">Welcome to the Evolution Mail Configuration Assistant. + +Click "Forward" to begin. </property> + </widget> + </child> + <child> + <widget class="GnomeDruidPageStandard" id="identity_page"> + <property name="visible">True</property> + <property name="title" translatable="yes">Identity</property> + <child internal-child="vbox"> + <widget class="GtkVBox" id="druid_identity_vbox"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="identity_help"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Please enter your name and email address below. The "optional" fields below do not need to be filled in, unless you wish to include this information in email you send.</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="expand">False</property> + </packing> + </child> + <child> + <placeholder/> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GnomeDruidPageStandard" id="source_page"> + <property name="visible">True</property> + <property name="title" translatable="yes">Receiving Email</property> + <child internal-child="vbox"> + <widget class="GtkVBox" id="druid_source_vbox"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="extra_help"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Please select among the following options</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="expand">False</property> + </packing> + </child> + <child> + <placeholder/> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GnomeDruidPageStandard" id="transport_page"> + <property name="visible">True</property> + <property name="title" translatable="yes">Sending Email</property> + <child internal-child="vbox"> + <widget class="GtkVBox" id="druid_transport_vbox"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="transport_help"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Please enter information about the way you will send mail. If you are not sure, ask your system administrator or Internet Service Provider.</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="expand">False</property> + </packing> + </child> + <child> + <placeholder/> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GnomeDruidPageStandard" id="management_page"> + <property name="visible">True</property> + <property name="title" translatable="yes">Account Management</property> + <child internal-child="vbox"> + <widget class="GtkVBox" id="druid_management_vbox"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="management_help"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Please enter a descriptive name for this account in the space below. This name will be used for display purposes only.</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">True</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <placeholder/> - </child> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GnomeDruidPageEdge" id="finish_page"> - <property name="visible">True</property> - <property name="position">GNOME_EDGE_FINISH</property> - <property name="title" translatable="yes">Done</property> - <property name="text" translatable="yes">Congratulations, your mail configuration is complete. + <property name="wrap">True</property> + </widget> + <packing> + <property name="expand">False</property> + </packing> + </child> + <child> + <placeholder/> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GnomeDruidPageEdge" id="finish_page"> + <property name="visible">True</property> + <property name="position">GNOME_EDGE_FINISH</property> + <property name="title" translatable="yes">Done</property> + <property name="text" translatable="yes">Congratulations, your mail configuration is complete. You are now ready to send and receive email using Evolution. -Click "Apply" to save your settings.</property> - </widget> - </child> - </widget> - </child> -</widget> - -<widget class="GtkWindow" id="account_editor"> - <property name="title" translatable="yes">Account Editor</property> - <property name="type">GTK_WINDOW_TOPLEVEL</property> - <property name="window_position">GTK_WIN_POS_NONE</property> - <property name="modal">False</property> - <property name="resizable">True</property> - <property name="destroy_with_parent">False</property> - <property name="decorated">True</property> - <property name="skip_taskbar_hint">False</property> - <property name="skip_pager_hint">False</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> - <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> - <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> - - <child> - <widget class="GtkNotebook" id="account_editor_notebook"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="show_tabs">True</property> - <property name="show_border">True</property> - <property name="tab_pos">GTK_POS_TOP</property> - <property name="scrollable">False</property> - <property name="enable_popup">False</property> - - <child> - <widget class="GtkVBox" id="vboxIdentityBorder"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkVBox" id="management_frame"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label470"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Account Information</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox172"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label568"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="table12"> - <property name="visible">True</property> - <property name="n_rows">1</property> - <property name="n_columns">1</property> - <property name="homogeneous">False</property> - <property name="row_spacing">2</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkVBox" id="account_vbox"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="management_description_label"> - <property name="visible">True</property> - <property name="label" translatable="yes">Type the name by which you would like to refer to this account. -For example: "Work" or "Personal"</property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hboxIdentityName"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="management_name_label"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Name:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_RIGHT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">management_name</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="management_name"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="has_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="identity_required_frame"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label464"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Required Information</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox170"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label569"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="table10"> - <property name="visible">True</property> - <property name="n_rows">1</property> - <property name="n_columns">1</property> - <property name="homogeneous">False</property> - <property name="row_spacing">2</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkTable" id="identity_required_table"> - <property name="visible">True</property> - <property name="n_rows">2</property> - <property name="n_columns">2</property> - <property name="homogeneous">False</property> - <property name="row_spacing">6</property> - <property name="column_spacing">12</property> - - <child> - <widget class="GtkEntry" id="identity_address"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - <accessibility> - <atkrelation target="identity_address_label" type="labelled-by"/> - <atkrelation target="label464" type="labelled-by"/> - </accessibility> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="identity_address_label"> - <property name="visible">True</property> - <property name="label" translatable="yes">Email _Address:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">identity_address</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="identity_full_name_label"> - <property name="visible">True</property> - <property name="label" translatable="yes">Full Nam_e:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">identity_full_name</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="identity_full_name"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - <accessibility> - <atkrelation target="label464" type="labelled-by"/> - <atkrelation target="identity_full_name_label" type="labelled-by"/> - </accessibility> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="y_options"></property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="identity_optional_frame"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label466"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Optional Information</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox171"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label570"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="identity_optional_table"> - <property name="visible">True</property> - <property name="n_rows">4</property> - <property name="n_columns">2</property> - <property name="homogeneous">False</property> - <property name="row_spacing">6</property> - <property name="column_spacing">12</property> - - <child> - <widget class="GtkLabel" id="sigLabel"> - <property name="visible">True</property> - <property name="label" translatable="yes">Signat_ure:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">signature_dropdown</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox169"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="Custom" id="signature_dropdown"> - <property name="visible">True</property> - <property name="creation_function">em_account_editor_dropdown_new</property> - <property name="int1">0</property> - <property name="int2">0</property> - <property name="last_modification_time">Mon, 06 Sep 2004 01:00:22 GMT</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="sigAddNew"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Add Ne_w Signature...</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="sigAddNewClicked"/> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="pack_type">GTK_PACK_END</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="x_options">fill</property> - <property name="y_options">fill</property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="identity_organization"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - <accessibility> - <atkrelation target="identity_organization_label" type="labelled-by"/> - <atkrelation target="label466" type="labelled-by"/> - </accessibility> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="identity_organization_label"> - <property name="visible">True</property> - <property name="label" translatable="yes">Or_ganization:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">identity_organization</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="identity_reply_to"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - <accessibility> - <atkrelation target="label466" type="labelled-by"/> - <atkrelation target="reply_to_label" type="labelled-by"/> - </accessibility> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="reply_to_label"> - <property name="visible">True</property> - <property name="label" translatable="yes">Re_ply-To:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">identity_reply_to</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="management_default"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">_Make this my default account</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options">fill</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="tab_expand">False</property> - <property name="tab_fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label31"> - <property name="visible">True</property> - <property name="label" translatable="yes">Identity</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">tab</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vboxSourceBorder"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkVBox" id="source_vbox"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkTable" id="source_type_table"> - <property name="visible">True</property> - <property name="n_rows">2</property> - <property name="n_columns">3</property> - <property name="homogeneous">False</property> - <property name="row_spacing">6</property> - <property name="column_spacing">12</property> - - <child> - <widget class="GtkLabel" id="source_type_label"> - <property name="visible">True</property> - <property name="label" translatable="yes">Server _Type: </property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_RIGHT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">source_type_dropdown</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label442"> - <property name="visible">True</property> - <property name="label" translatable="yes">Description:</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="source_description"> - <property name="visible">True</property> - <property name="label" translatable="yes">description</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">True</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">3</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="Custom" id="source_type_dropdown"> - <property name="visible">True</property> - <property name="creation_function">em_account_editor_dropdown_new</property> - <property name="int1">0</property> - <property name="int2">0</property> - <property name="last_modification_time">Thu, 29 Jul 2004 05:31:24 GMT</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">3</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHSeparator" id="hseparator2"> - <property name="visible">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="source_frame"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label472"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Configuration</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox173"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label565"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="table13"> - <property name="visible">True</property> - <property name="n_rows">1</property> - <property name="n_columns">1</property> - <property name="homogeneous">False</property> - <property name="row_spacing">2</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkTable" id="table4"> - <property name="visible">True</property> - <property name="n_rows">3</property> - <property name="n_columns">2</property> - <property name="homogeneous">False</property> - <property name="row_spacing">6</property> - <property name="column_spacing">12</property> - - <child> - <widget class="GtkLabel" id="source_host_label"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Server:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">source_host</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="source_user_label"> - <property name="visible">True</property> - <property name="label" translatable="yes">User_name:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">source_user</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="source_host"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="source_user"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="source_path_label"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Path:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkFileChooserButton" id="source_path_entry"> - <property name="visible">True</property> - <property name="title" translatable="yes">Mailbox location</property> - <property name="action">GTK_FILE_CHOOSER_ACTION_OPEN</property> - <property name="local_only">True</property> - <property name="show_hidden">False</property> - <property name="do_overwrite_confirmation">False</property> - <property name="width_chars">-1</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="y_options"></property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="source_security_frame"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label515"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Security</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">source_auth_dropdown</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox201"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label567"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox181"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkHBox" id="source_ssl_hbox"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="lblSourceUseSSL"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Use Secure Connection:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">source_use_ssl</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="Custom" id="source_use_ssl"> - <property name="visible">True</property> - <property name="creation_function">em_account_editor_ssl_selector_new</property> - <property name="int1">0</property> - <property name="int2">0</property> - <property name="last_modification_time">Tue, 03 Aug 2004 07:22:52 GMT</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="source_ssl_disabled"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkImage" id="image2"> - <property name="visible">True</property> - <property name="stock">gtk-dialog-warning</property> - <property name="icon_size">4</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label514"> - <property name="visible">True</property> - <property name="label" translatable="yes"><b>SSL is not supported in this build of Evolution</b></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="source_auth_frame"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label474"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">_Authentication Type</span></property> - <property name="use_underline">True</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">source_auth_dropdown</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox174"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label566"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox179"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkHBox" id="hbox199"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="Custom" id="source_auth_dropdown"> - <property name="visible">True</property> - <property name="creation_function">em_account_editor_dropdown_new</property> - <property name="int1">0</property> - <property name="int2">0</property> - <property name="last_modification_time">Thu, 29 Jul 2004 08:38:30 GMT</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="source_check_supported"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes"> Ch_eck for Supported Types </property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="source_remember_password"> - <property name="visible">True</property> - <property name="tooltip" translatable="yes">Note: you will not be prompted for a password until you connect for the first time</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Re_member password</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="tab_expand">False</property> - <property name="tab_fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label33"> - <property name="visible">True</property> - <property name="label" translatable="yes">Receiving Email</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">tab</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vboxTransportBorder"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkVBox" id="transport_vbox"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkTable" id="transport_type_table"> - <property name="visible">True</property> - <property name="n_rows">2</property> - <property name="n_columns">3</property> - <property name="homogeneous">False</property> - <property name="row_spacing">6</property> - <property name="column_spacing">12</property> - - <child> - <widget class="GtkLabel" id="transport_type_label"> - <property name="visible">True</property> - <property name="label" translatable="yes">Server _Type: </property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_RIGHT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">transport_type_dropdown</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label50"> - <property name="visible">True</property> - <property name="label" translatable="yes">Description:</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_RIGHT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - </packing> - </child> - - <child> - <widget class="Custom" id="transport_type_dropdown"> - <property name="visible">True</property> - <property name="creation_function">em_account_editor_dropdown_new</property> - <property name="int1">0</property> - <property name="int2">0</property> - <property name="last_modification_time">Thu, 29 Jul 2004 05:42:00 GMT</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">3</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="transport_description"> - <property name="visible">True</property> - <property name="label" translatable="yes">description</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">True</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">3</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkHSeparator" id="hseparator3"> - <property name="visible">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="transport_frame"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkVBox" id="transport_server_frame"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label476"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Server Configuration</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox175"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label562"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="table15"> - <property name="visible">True</property> - <property name="n_rows">1</property> - <property name="n_columns">1</property> - <property name="homogeneous">False</property> - <property name="row_spacing">2</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkVBox" id="vbox12"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkTable" id="table6"> - <property name="visible">True</property> - <property name="n_rows">1</property> - <property name="n_columns">2</property> - <property name="homogeneous">False</property> - <property name="row_spacing">6</property> - <property name="column_spacing">12</property> - - <child> - <widget class="GtkLabel" id="transport_host_label"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Server:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_RIGHT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">1</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">transport_host</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="transport_host"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="y_options"></property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="transport_needs_auth"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Ser_ver requires authentication</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="transport_security_frame"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label517"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Security</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox203"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label564"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox183"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkHBox" id="transport_ssl_hbox"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="lblTransportUseSSL"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Use Secure Connection:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">transport_use_ssl</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="Custom" id="transport_use_ssl"> - <property name="visible">True</property> - <property name="creation_function">em_account_editor_ssl_selector_new</property> - <property name="int1">0</property> - <property name="int2">0</property> - <property name="last_modification_time">Tue, 03 Aug 2004 07:23:50 GMT</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="transport_ssl_disabled"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkImage" id="image1"> - <property name="visible">True</property> - <property name="stock">gtk-dialog-warning</property> - <property name="icon_size">4</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="transport_ssl_disabled_label"> - <property name="visible">True</property> - <property name="label" translatable="yes"><b>SSL is not supported in this build of Evolution</b></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="transport_auth_frame"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label478"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Authentication</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox176"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label563"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="table16"> - <property name="visible">True</property> - <property name="n_rows">1</property> - <property name="n_columns">1</property> - <property name="homogeneous">False</property> - <property name="row_spacing">2</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkVBox" id="vbox61"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkTable" id="table31"> - <property name="visible">True</property> - <property name="n_rows">2</property> - <property name="n_columns">2</property> - <property name="homogeneous">False</property> - <property name="row_spacing">6</property> - <property name="column_spacing">12</property> - - <child> - <widget class="GtkLabel" id="transport_auth_label"> - <property name="visible">True</property> - <property name="label" translatable="yes">T_ype: </property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">transport_auth_dropdown</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="transport_user_label"> - <property name="visible">True</property> - <property name="label" translatable="yes">User_name:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_RIGHT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">transport_user</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="transport_user"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox195"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="Custom" id="transport_auth_dropdown"> - <property name="visible">True</property> - <property name="creation_function">em_account_editor_dropdown_new</property> - <property name="int1">0</property> - <property name="int2">0</property> - <property name="last_modification_time">Thu, 29 Jul 2004 08:37:13 GMT</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="transport_check_supported"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Ch_eck for Supported Types </property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkFixed" id="fixed5"> - <property name="visible">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="y_options">fill</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="transport_remember_password"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Remember _password</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="tab_expand">False</property> - <property name="tab_fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label34"> - <property name="visible">True</property> - <property name="label" translatable="yes">Sending Mail</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">tab</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vboxFoldersBorder"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkVBox" id="folders_frame"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label482"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Sent and Draft Messages</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox177"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label560"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="table17"> - <property name="visible">True</property> - <property name="n_rows">1</property> - <property name="n_columns">1</property> - <property name="homogeneous">False</property> - <property name="row_spacing">2</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkVBox" id="vbox184"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkTable" id="folders_table"> - <property name="visible">True</property> - <property name="n_rows">3</property> - <property name="n_columns">3</property> - <property name="homogeneous">False</property> - <property name="row_spacing">6</property> - <property name="column_spacing">12</property> - - <child> - <widget class="GtkLabel" id="drafts_label"> - <property name="visible">True</property> - <property name="label" translatable="yes">Drafts _Folder:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">drafts_button</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="sent_label"> - <property name="visible">True</property> - <property name="label" translatable="yes">Sent _Messages Folder:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">sent_button</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="Custom" id="sent_button"> - <property name="visible">True</property> - <property name="creation_function">em_account_editor_folder_selector_button_new</property> - <property name="string1">Select Sent Folder</property> - <property name="int1">0</property> - <property name="int2">0</property> - <property name="last_modification_time">Tue, 14 Dec 2004 17:07:09 GMT</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options">fill</property> - </packing> - </child> - - <child> - <widget class="Custom" id="drafts_button"> - <property name="visible">True</property> - <property name="creation_function">em_account_editor_folder_selector_button_new</property> - <property name="string1">Select Drafts Folder</property> - <property name="int1">0</property> - <property name="int2">0</property> - <property name="last_modification_time">Tue, 14 Dec 2004 17:07:02 GMT</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="y_options">fill</property> - </packing> - </child> - - <child> - <widget class="GtkFixed" id="fixed9"> - <property name="visible">True</property> - </widget> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="y_options">fill</property> - </packing> - </child> - - <child> - <widget class="GtkFixed" id="fixed8"> - <property name="visible">True</property> - </widget> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options">fill</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox216"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkButton" id="default_folders_button"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label">gtk-revert-to-saved</property> - <property name="use_stock">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkFixed" id="fixed12"> - <property name="visible">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">3</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="frame2"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label484"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Composing Messages</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox178"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label561"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="table18"> - <property name="visible">True</property> - <property name="n_rows">1</property> - <property name="n_columns">1</property> - <property name="homogeneous">False</property> - <property name="row_spacing">2</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkTable" id="table8"> - <property name="visible">True</property> - <property name="n_rows">2</property> - <property name="n_columns">1</property> - <property name="homogeneous">False</property> - <property name="row_spacing">6</property> - <property name="column_spacing">12</property> - - <child> - <widget class="GtkVBox" id="vbox186"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkCheckButton" id="always_cc"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Alway_s carbon-copy (cc) to:</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox210"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkLabel" id="label522"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">12</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="table32"> - <property name="visible">True</property> - <property name="n_rows">1</property> - <property name="n_columns">1</property> - <property name="homogeneous">False</property> - <property name="row_spacing">2</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkVBox" id="vbox187"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkEntry" id="cc_addrs"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox188"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkCheckButton" id="always_bcc"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Always _blind carbon-copy (bcc) to:</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox211"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkLabel" id="label523"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">12</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="table33"> - <property name="visible">True</property> - <property name="n_rows">1</property> - <property name="n_columns">1</property> - <property name="homogeneous">False</property> - <property name="row_spacing">2</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkVBox" id="vbox189"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkEntry" id="bcc_addrs"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox205"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label578"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Message Receipts</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox231"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label581"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox232"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label583"> - <property name="visible">True</property> - <property name="label" translatable="yes">S_end message receipts:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">receipt_policy_dropdown</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkComboBox" id="receipt_policy_dropdown"> - <property name="visible">True</property> - <property name="items" translatable="yes"></property> - <property name="add_tearoffs">False</property> - <property name="focus_on_click">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="tab_expand">False</property> - <property name="tab_fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label35"> - <property name="visible">True</property> - <property name="label" translatable="yes">Defaults</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">tab</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vboxSecurityBorder"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkVBox" id="pgp_frame"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label486"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Pretty Good Privacy (PGP/GPG)</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox179"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label558"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="table19"> - <property name="visible">True</property> - <property name="n_rows">1</property> - <property name="n_columns">1</property> - <property name="homogeneous">False</property> - <property name="row_spacing">2</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkVBox" id="vboxPGP"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkHBox" id="hbox63"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="pgp_key_id_label"> - <property name="visible">True</property> - <property name="label" translatable="yes">PGP/GPG _Key ID:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">pgp_key</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="pgp_key"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="pgp_always_sign"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Al_ways sign outgoing messages when using this account</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="pgp_no_imip_sign"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">_Do not sign meeting requests (for Outlook compatibility)</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="pgp_encrypt_to_self"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Always encrypt to _myself when sending encrypted messages</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">True</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="pgp_always_trust"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Always _trust keys in my keyring when encrypting</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="smime_vbox"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label519"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Secure MIME (S/MIME)</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox206"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label559"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="smime_table"> - <property name="visible">True</property> - <property name="n_rows">6</property> - <property name="n_columns">3</property> - <property name="homogeneous">False</property> - <property name="row_spacing">6</property> - <property name="column_spacing">12</property> - - <child> - <widget class="GtkEntry" id="smime_sign_key"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="smime_encrypt_key"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">5</property> - <property name="bottom_attach">6</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="smime_encrypt_to_self"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Also encrypt to sel_f when sending encrypted messages</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">3</property> - <property name="top_attach">4</property> - <property name="bottom_attach">5</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="smime_encrypt_default"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Encrypt out_going messages (by default)</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">3</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="smime_sign_default"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Digitally sign o_utgoing messages (by default)</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">3</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkHSeparator" id="hseparator3"> - <property name="visible">True</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">3</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="y_padding">6</property> - <property name="x_options">fill</property> - <property name="y_options">fill</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label470"> - <property name="visible">True</property> - <property name="label" translatable="yes">Encry_ption certificate:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">smime_encrypt_key</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">5</property> - <property name="bottom_attach">6</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label469"> - <property name="visible">True</property> - <property name="label" translatable="yes">Sig_ning certificate:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">smime_sign_key</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox208"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkButton" id="smime_encrypt_key_select"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - - <child> - <widget class="GtkAlignment" id="alignment28"> - <property name="visible">True</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xscale">0</property> - <property name="yscale">0</property> - <property name="top_padding">0</property> - <property name="bottom_padding">0</property> - <property name="left_padding">0</property> - <property name="right_padding">0</property> - - <child> - <widget class="GtkHBox" id="hbox175"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">2</property> - - <child> - <widget class="GtkImage" id="image3"> - <property name="visible">True</property> - <property name="stock">gtk-open</property> - <property name="icon_size">4</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="button98"> - <property name="visible">True</property> - <property name="label" translatable="yes">S_elect...</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - </child> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="smime_encrypt_key_clear"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - - <child> - <widget class="GtkAlignment" id="alignment35"> - <property name="visible">True</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xscale">0</property> - <property name="yscale">0</property> - <property name="top_padding">0</property> - <property name="bottom_padding">0</property> - <property name="left_padding">0</property> - <property name="right_padding">0</property> - - <child> - <widget class="GtkHBox" id="hbox230"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">2</property> - - <child> - <widget class="GtkImage" id="image10"> - <property name="visible">True</property> - <property name="stock">gtk-clear</property> - <property name="icon_size">4</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label577"> - <property name="visible">True</property> - <property name="label" translatable="yes">Clea_r</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - </child> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">5</property> - <property name="bottom_attach">6</property> - <property name="x_options">fill</property> - <property name="y_options">fill</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox209"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkButton" id="smime_sign_key_select"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - - <child> - <widget class="GtkAlignment" id="alignment29"> - <property name="visible">True</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xscale">0</property> - <property name="yscale">0</property> - <property name="top_padding">0</property> - <property name="bottom_padding">0</property> - <property name="left_padding">0</property> - <property name="right_padding">0</property> - - <child> - <widget class="GtkHBox" id="hbox176"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">2</property> - - <child> - <widget class="GtkImage" id="image4"> - <property name="visible">True</property> - <property name="stock">gtk-open</property> - <property name="icon_size">4</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label472"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Select...</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - </child> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="smime_sign_key_clear"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - - <child> - <widget class="GtkAlignment" id="alignment34"> - <property name="visible">True</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xscale">0</property> - <property name="yscale">0</property> - <property name="top_padding">0</property> - <property name="bottom_padding">0</property> - <property name="left_padding">0</property> - <property name="right_padding">0</property> - - <child> - <widget class="GtkHBox" id="hbox229"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">2</property> - - <child> - <widget class="GtkImage" id="image9"> - <property name="visible">True</property> - <property name="stock">gtk-clear</property> - <property name="icon_size">4</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label576"> - <property name="visible">True</property> - <property name="label" translatable="yes">Cle_ar</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - </child> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options">fill</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="tab_expand">False</property> - <property name="tab_fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="lblSecurity"> - <property name="visible">True</property> - <property name="label" translatable="yes">Security</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">tab</property> - </packing> - </child> - </widget> - </child> -</widget> - -<widget class="GtkWindow" id="accounts_tab"> - <property name="title" translatable="yes">Email Accounts</property> - <property name="type">GTK_WINDOW_TOPLEVEL</property> - <property name="window_position">GTK_WIN_POS_NONE</property> - <property name="modal">False</property> - <property name="resizable">True</property> - <property name="destroy_with_parent">False</property> - <property name="decorated">True</property> - <property name="skip_taskbar_hint">False</property> - <property name="skip_pager_hint">False</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> - <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> - <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> - - <child> - <widget class="GtkHBox" id="toplevel"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="Custom" id="etableMailAccounts"> - <property name="visible">True</property> - <property name="creation_function">em_account_prefs_treeview_new</property> - <property name="int1">0</property> - <property name="int2">0</property> - <property name="last_modification_time">Wed, 29 Oct 2003 17:47:08 GMT</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vboxMailFunctions"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkVButtonBox" id="vbuttonboxMailAccounts"> - <property name="visible">True</property> - <property name="layout_style">GTK_BUTTONBOX_START</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkButton" id="cmdAccountAdd"> - <property name="visible">True</property> - <property name="can_default">True</property> - <property name="can_focus">True</property> - <property name="label">gtk-add</property> - <property name="use_stock">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - </widget> - </child> - - <child> - <widget class="GtkButton" id="cmdAccountEdit"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="can_default">True</property> - <property name="can_focus">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - - <child> - <widget class="GtkAlignment" id="alignment33"> - <property name="visible">True</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xscale">0</property> - <property name="yscale">0</property> - <property name="top_padding">0</property> - <property name="bottom_padding">0</property> - <property name="left_padding">0</property> - <property name="right_padding">0</property> - - <child> - <widget class="GtkHBox" id="hbox224"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">2</property> - - <child> - <widget class="GtkImage" id="image8"> - <property name="visible">True</property> - <property name="stock">gtk-properties</property> - <property name="icon_size">4</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label557"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Edit</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - </child> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GtkButton" id="cmdAccountDelete"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="can_default">True</property> - <property name="can_focus">True</property> - <property name="label">gtk-delete</property> - <property name="use_stock">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - </widget> - </child> - - <child> - <widget class="GtkButton" id="cmdAccountDefault"> - <property name="width_request">89</property> - <property name="height_request">36</property> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="can_default">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">De_fault</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - </child> -</widget> - -<widget class="GtkWindow" id="preferences_tab"> - <property name="title" translatable="yes">Mail Preferences</property> - <property name="type">GTK_WINDOW_TOPLEVEL</property> - <property name="window_position">GTK_WIN_POS_NONE</property> - <property name="modal">False</property> - <property name="resizable">True</property> - <property name="destroy_with_parent">False</property> - <property name="decorated">True</property> - <property name="skip_taskbar_hint">False</property> - <property name="skip_pager_hint">False</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> - <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> - <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> - - <child> - <widget class="GtkNotebook" id="preferences_toplevel"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="show_tabs">True</property> - <property name="show_border">True</property> - <property name="tab_pos">GTK_POS_TOP</property> - <property name="scrollable">True</property> - <property name="enable_popup">False</property> - - <child> - <widget class="GtkVBox" id="vboxGeneral"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkVBox" id="FontsFrame"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label492"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Message Fonts</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox182"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label540"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="table22"> - <property name="visible">True</property> - <property name="n_rows">1</property> - <property name="n_columns">1</property> - <property name="homogeneous">False</property> - <property name="row_spacing">2</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkVBox" id="vboxMessageFonts"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkCheckButton" id="radFontUseSame"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">_Use the same fonts as other applications</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="tblScreen"> - <property name="visible">True</property> - <property name="n_rows">2</property> - <property name="n_columns">2</property> - <property name="homogeneous">False</property> - <property name="row_spacing">6</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkLabel" id="lblScreenVariable"> - <property name="visible">True</property> - <property name="label" translatable="yes">S_tandard Font:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_RIGHT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">FontVariable</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkFontButton" id="FontFixed"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="title" translatable="yes">Select HTML fixed width font</property> - <property name="show_style">True</property> - <property name="show_size">True</property> - <property name="use_font">False</property> - <property name="use_size">False</property> - <property name="focus_on_click">True</property> - <signal name="font_set" handler="changed"/> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkFontButton" id="FontVariable"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="title" translatable="yes">Select HTML variable width font</property> - <property name="show_style">True</property> - <property name="show_size">True</property> - <property name="use_font">False</property> - <property name="use_size">False</property> - <property name="focus_on_click">True</property> - <signal name="font_set" handler="changed"/> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label444"> - <property name="visible">True</property> - <property name="label" translatable="yes">Fix_ed width Font:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_RIGHT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">FontFixed</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="MessageDisplayFrame"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label494"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Message Display</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox183"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label541"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="table23"> - <property name="visible">True</property> - <property name="n_rows">1</property> - <property name="n_columns">1</property> - <property name="homogeneous">False</property> - <property name="row_spacing">2</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkVBox" id="vboxMessageDisplay"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkHBox" id="hboxReadTimeout"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkCheckButton" id="chkMarkTimeout"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">_Mark messages as read after</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkSpinButton" id="spinMarkTimeout"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="climb_rate">1</property> - <property name="digits">1</property> - <property name="numeric">True</property> - <property name="update_policy">GTK_UPDATE_IF_VALID</property> - <property name="snap_to_ticks">False</property> - <property name="wrap">False</property> - <property name="adjustment">1.5 0 10 1 1 0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="lblSeconds"> - <property name="visible">True</property> - <property name="label" translatable="yes">seconds</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox234"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">4</property> - - <child> - <widget class="GtkCheckButton" id="mlimit_checkbutton"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Do not format messages when text si_ze exceeds</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkSpinButton" id="mlimit_spin"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="climb_rate">1</property> - <property name="digits">0</property> - <property name="numeric">False</property> - <property name="update_policy">GTK_UPDATE_ALWAYS</property> - <property name="snap_to_ticks">False</property> - <property name="wrap">False</property> - <property name="adjustment">0 0 30000 1 10 0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label585"> - <property name="visible">True</property> - <property name="label" translatable="yes">KB</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox233"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkCheckButton" id="address_checkbox"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">_Shrink To / Cc / Bcc headers to </property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkSpinButton" id="address_spin"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="climb_rate">1</property> - <property name="digits">0</property> - <property name="numeric">False</property> - <property name="update_policy">GTK_UPDATE_ALWAYS</property> - <property name="snap_to_ticks">False</property> - <property name="wrap">False</property> - <property name="adjustment">5 1 100 1 10 0</property> - </widget> - <packing> - <property name="padding">2</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label584"> - <property name="visible">True</property> - <property name="label" translatable="yes">addresses</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">2</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="magic_spacebar_checkbox"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Enable Magic S_pacebar</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hboxHighlightColor"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkCheckButton" id="chkHighlightCitations"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Highlight _quotations with</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">True</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkColorButton" id="colorButtonHighlightCitations"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="use_alpha">False</property> - <property name="title" translatable="yes">Pick a color</property> - <property name="focus_on_click">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="lblColor"> - <property name="visible">True</property> - <property name="label" translatable="yes">color</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hboxDefaultCharset"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="lblDefaultCharset"> - <property name="visible">True</property> - <property name="label" translatable="yes">Default character e_ncoding:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">omenuCharset</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkOptionMenu" id="omenuCharset"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="history">0</property> - - <child internal-child="menu"> - <widget class="GtkMenu" id="convertwidget26"> - <property name="visible">True</property> - - <child> - <widget class="GtkMenuItem" id="convertwidget27"> - <property name="visible">True</property> - <property name="label" translatable="yes">Baltic (ISO-8859-13)</property> - <property name="use_underline">True</property> - </widget> - </child> - - <child> - <widget class="GtkMenuItem" id="convertwidget28"> - <property name="visible">True</property> - <property name="label" translatable="yes">Baltic (ISO-8859-4)</property> - <property name="use_underline">True</property> - </widget> - </child> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hboxEnableSearchFolders"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkCheckButton" id="chkEnableSearchFolders"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Enable Sea_rch Folders</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">True</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="lblEnableSFRestart"> - <property name="visible">True</property> - <property name="label" translatable="yes">(Note: Requires restart of the application)</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="DeleteMailFrame"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label496"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Delete Mail</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox184"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label542"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="table24"> - <property name="visible">True</property> - <property name="n_rows">1</property> - <property name="n_columns">1</property> - <property name="homogeneous">False</property> - <property name="row_spacing">2</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkVBox" id="vboxDeletingMail"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkHBox" id="hbox220"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">4</property> - - <child> - <widget class="GtkCheckButton" id="chkEmptyTrashOnExit"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Empty trash folders on e_xit</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkComboBox" id="comboboxEmptyTrashDays"> - <property name="visible">True</property> - <property name="items" translatable="yes">a -b</property> - <property name="add_tearoffs">False</property> - <property name="focus_on_click">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="chkConfirmExpunge"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Confirm _when expunging a folder</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="tab_expand">False</property> - <property name="tab_fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="lblGeneral"> - <property name="visible">True</property> - <property name="label" translatable="yes">General</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">tab</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vboxHtmlMail"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label530"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">General</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox215"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label538"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox173"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkCheckButton" id="chkShowAnimatedImages"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes" comments="If enabled, show animation; if disabled, only display a static image without any animation">_Show image animations</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="chkPromptWantHTML"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">_Prompt on sending HTML mail to contacts that do not want them</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vboxLoadingImages"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label500"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Loading Images</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox186"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label539"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox190"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkRadioButton" id="radImagesNever"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">_Never load images from the Internet</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkRadioButton" id="radImagesSometimes"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">_Load images in messages from contacts</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - <property name="group">radImagesNever</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkRadioButton" id="radImagesAlways"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">_Always load images from the Internet</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - <property name="group">radImagesNever</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="tab_expand">False</property> - <property name="tab_fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="lblHtmlMail"> - <property name="visible">True</property> - <property name="label" translatable="yes">HTML Messages</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">tab</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="frameColours"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label502"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Labels</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox187"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label537"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox242"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkVBox" id="vbox209"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkScrolledWindow" id="scrolledwindow50"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="shadow_type">GTK_SHADOW_IN</property> - <property name="window_placement">GTK_CORNER_TOP_LEFT</property> - - <child> - <widget class="GtkTreeView" id="labelTree"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="headers_visible">True</property> - <property name="rules_hint">False</property> - <property name="reorderable">False</property> - <property name="enable_search">True</property> - <property name="fixed_height_mode">False</property> - <property name="hover_selection">False</property> - <property name="hover_expand">False</property> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label589"> - <property name="visible">True</property> - <property name="label" translatable="yes">Note: Underscore in the label name is used as mnemonic identifier in menu.</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">True</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">10</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox208"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">2</property> - - <child> - <widget class="GtkButton" id="labelAdd"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label">gtk-add</property> - <property name="use_stock">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">False</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="labelEdit"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label">gtk-edit</property> - <property name="use_stock">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="labelRemove"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label">gtk-remove</property> - <property name="use_stock">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <placeholder/> - </child> - </widget> - <packing> - <property name="padding">6</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="tab_expand">False</property> - <property name="tab_fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="lblColours"> - <property name="visible">True</property> - <property name="label" translatable="yes">Labels</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">tab</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vboxHeaderTab"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkVBox" id="vbox206"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">3</property> - - <child> - <widget class="GtkHBox" id="hbox238"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkLabel" id="label587"> - <property name="visible">True</property> - <property name="label" translatable="yes"><b>Sender Photograph</b></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox206"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkHBox" id="hbox239"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkCheckButton" id="photo_show"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">_Show the photograph of sender in the message preview</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">10</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox240"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkCheckButton" id="photo_local"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">S_earch for sender photograph only in local address books</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">10</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label524"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Displayed Message _Headers</span></property> - <property name="use_underline">True</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">txtHeaders</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox212"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label536"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox199"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkEntry" id="txtHeaders"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkScrolledWindow" id="scrolledwindow49"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="shadow_type">GTK_SHADOW_IN</property> - <property name="window_placement">GTK_CORNER_TOP_LEFT</property> - - <child> - <widget class="GtkTreeView" id="treeHeaders"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="headers_visible">False</property> - <property name="rules_hint">False</property> - <property name="reorderable">False</property> - <property name="enable_search">True</property> - <property name="fixed_height_mode">False</property> - <property name="hover_selection">False</property> - <property name="hover_expand">False</property> - <accessibility> - <atkproperty name="AtkObject::accessible_name" translatable="yes">Mail Headers Table</atkproperty> - </accessibility> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox200"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkButton" id="cmdHeadersAdd"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="can_focus">True</property> - <property name="label">gtk-add</property> - <property name="use_stock">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="cmdHeadersRemove"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label">gtk-remove</property> - <property name="use_stock">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="tab_expand">False</property> - <property name="tab_fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="lblHeaders"> - <property name="visible">True</property> - <property name="label" translatable="yes">Headers</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">tab</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox161"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkVBox" id="vbox192"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkLabel" id="label526"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">General</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="table34"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="n_rows">9</property> - <property name="n_columns">1</property> - <property name="homogeneous">False</property> - <property name="row_spacing">3</property> - <property name="column_spacing">0</property> - - <child> - <widget class="GtkHBox" id="hbox235"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label586"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Default junk plugin:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">default_junk_plugin</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">6</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="Custom" id="default_junk_plugin"> - <property name="visible">True</property> - <property name="creation_function">create_combo_text_widget</property> - <property name="int1">0</property> - <property name="int2">0</property> - <property name="last_modification_time">Fri, 23 Mar 2007 09:28:55 GMT</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">7</property> - <property name="bottom_attach">8</property> - <property name="x_options">fill</property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="chkCheckIncomingMail"> - <property name="visible">True</property> - <property name="tooltip" translatable="yes">Checks incoming mail messages to be Junk</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Check incoming _messages for junk</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_padding">4</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox236"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">3</property> - - <child> - <widget class="GtkImage" id="plugin_image"> - <property name="visible">True</property> - <property name="icon_size">4</property> - <property name="icon_name">gtk-info</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="plugin_status"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">8</property> - <property name="bottom_attach">9</property> - <property name="x_padding">15</property> - <property name="x_options">fill</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox237"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">4</property> - - <child> - <widget class="GtkCheckButton" id="junk_empty_check"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Delete junk messages on e_xit</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkComboBox" id="junk_empty_combobox"> - <property name="visible">True</property> - <property name="items" translatable="yes">a -b</property> - <property name="add_tearoffs">False</property> - <property name="focus_on_click">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_padding">4</property> - <property name="x_options">fill</property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="junk_header_check"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Check cu_stom headers for junk</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_padding">4</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox243"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkScrolledWindow" id="scrolledwindow51"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="shadow_type">GTK_SHADOW_IN</property> - <property name="window_placement">GTK_CORNER_TOP_LEFT</property> - - <child> - <widget class="GtkTreeView" id="junk_header_tree"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="headers_visible">True</property> - <property name="rules_hint">False</property> - <property name="reorderable">False</property> - <property name="enable_search">True</property> - <property name="fixed_height_mode">False</property> - <property name="hover_selection">False</property> - <property name="hover_expand">False</property> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkVButtonBox" id="vbuttonbox26"> - <property name="visible">True</property> - <property name="layout_style">GTK_BUTTONBOX_SPREAD</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkButton" id="junk_header_add"> - <property name="visible">True</property> - <property name="can_default">True</property> - <property name="can_focus">True</property> - <property name="label">gtk-add</property> - <property name="use_stock">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - </widget> - </child> - - <child> - <widget class="GtkButton" id="junk_header_remove"> - <property name="visible">True</property> - <property name="can_default">True</property> - <property name="can_focus">True</property> - <property name="label">gtk-remove</property> - <property name="use_stock">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="x_padding">22</property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="lookup_book"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Do not mar_k messages as junk if sender is in my address book</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">4</property> - <property name="bottom_attach">5</property> - <property name="x_padding">4</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="junk_lookup_local_only"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">_Lookup in local address book only</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">5</property> - <property name="bottom_attach">6</property> - <property name="x_padding">25</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox244"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkImage" id="image11"> - <property name="visible">True</property> - <property name="stock">gtk-info</property> - <property name="icon_size">4</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label590"> - <property name="visible">True</property> - <property name="label" translatable="yes">Option is ignored if a match for custom junk headers is found.</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">6</property> - <property name="bottom_attach">7</property> - <property name="x_options">fill</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox195"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="tab_expand">False</property> - <property name="tab_fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label473"> - <property name="visible">True</property> - <property name="label" translatable="yes">Junk</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">tab</property> - </packing> - </child> - </widget> - </child> -</widget> - -<widget class="GtkWindow" id="composer_tab"> - <property name="title" translatable="yes">Message Composer</property> - <property name="type">GTK_WINDOW_TOPLEVEL</property> - <property name="window_position">GTK_WIN_POS_NONE</property> - <property name="modal">False</property> - <property name="resizable">True</property> - <property name="destroy_with_parent">False</property> - <property name="decorated">True</property> - <property name="skip_taskbar_hint">False</property> - <property name="skip_pager_hint">False</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> - <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> - <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> - - <child> - <widget class="GtkNotebook" id="composer_toplevel"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="show_tabs">True</property> - <property name="show_border">True</property> - <property name="tab_pos">GTK_POS_TOP</property> - <property name="scrollable">False</property> - <property name="enable_popup">False</property> - - <child> - <widget class="GtkVBox" id="vboxGeneral"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">18</property> - - <child> - <widget class="GtkVBox" id="frameBehavior"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label504"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Default Behavior</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox189"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkLabel" id="label505"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">12</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="table28"> - <property name="visible">True</property> - <property name="n_rows">1</property> - <property name="n_columns">1</property> - <property name="homogeneous">False</property> - <property name="row_spacing">2</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkVBox" id="vboxBehavior"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">8</property> - - <child> - <widget class="GtkCheckButton" id="chkSendHTML"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Format messages in _HTML</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="chkAutoSmileys"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Automatically insert _emoticon images</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="chkRequestReceipt"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Always request rea_d receipt</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="chkReplyStartBottom"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Start _typing at the bottom on replying</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="chkOutlookFilenames"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Encode file names in an Outlook/GMail way</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="tableForwardsReplies"> - <property name="visible">True</property> - <property name="n_rows">3</property> - <property name="n_columns">2</property> - <property name="homogeneous">False</property> - <property name="row_spacing">6</property> - <property name="column_spacing">12</property> - - <child> - <widget class="GtkLabel" id="lblReplyStyle"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Reply style:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkAlignment" id="alignment25"> - <property name="visible">True</property> - <property name="xalign">7.45058015283e-09</property> - <property name="yalign">0.5</property> - <property name="xscale">0</property> - <property name="yscale">1</property> - <property name="top_padding">0</property> - <property name="bottom_padding">0</property> - <property name="left_padding">0</property> - <property name="right_padding">0</property> - - <child> - <widget class="GtkHBox" id="hboxReplyStyle"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkComboBox" id="comboboxReplyStyle"> - <property name="visible">True</property> - <property name="items" translatable="yes">Attachment -Inline (Outlook style) -Quoted -Do not quote</property> - <property name="add_tearoffs">False</property> - <property name="focus_on_click">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - </child> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hboxForwardStyle"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkComboBox" id="comboboxForwardStyle"> - <property name="visible">True</property> - <property name="items" translatable="yes">Attachment +Click "Apply" to save your settings.</property> + </widget> + </child> + </widget> + </child> + </widget> + <widget class="GtkWindow" id="account_editor"> + <property name="title" translatable="yes">Account Editor</property> + <child> + <widget class="GtkNotebook" id="account_editor_notebook"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="border_width">12</property> + <child> + <widget class="GtkVBox" id="vboxIdentityBorder"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="spacing">12</property> + <child> + <widget class="GtkVBox" id="management_frame"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label470"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Account Information</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox172"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label568"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="table12"> + <property name="visible">True</property> + <property name="column_spacing">6</property> + <property name="row_spacing">2</property> + <child> + <widget class="GtkVBox" id="account_vbox"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="management_description_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Type the name by which you would like to refer to this account. +For example: "Work" or "Personal"</property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hboxIdentityName"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="management_name_label"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Name:</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_RIGHT</property> + <property name="mnemonic_widget">management_name</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="management_name"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="has_focus">True</property> + <property name="invisible_char">*</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="identity_required_frame"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label464"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Required Information</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox170"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label569"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="table10"> + <property name="visible">True</property> + <property name="column_spacing">6</property> + <property name="row_spacing">2</property> + <child> + <widget class="GtkTable" id="identity_required_table"> + <property name="visible">True</property> + <property name="n_rows">2</property> + <property name="n_columns">2</property> + <property name="column_spacing">12</property> + <property name="row_spacing">6</property> + <child> + <widget class="GtkEntry" id="identity_address"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + <accessibility> + <atkrelation target="label464" type="labelled-by"/> + <atkrelation target="identity_address_label" type="labelled-by"/> + </accessibility> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="identity_address_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Email _Address:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">identity_address</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="identity_full_name_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Full Nam_e:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">identity_full_name</property> + </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="identity_full_name"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + <accessibility> + <atkrelation target="identity_full_name_label" type="labelled-by"/> + <atkrelation target="label464" type="labelled-by"/> + </accessibility> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="identity_optional_frame"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label466"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Optional Information</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox171"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label570"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="identity_optional_table"> + <property name="visible">True</property> + <property name="n_rows">4</property> + <property name="n_columns">2</property> + <property name="column_spacing">12</property> + <property name="row_spacing">6</property> + <child> + <widget class="GtkLabel" id="sigLabel"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Signat_ure:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">signature_dropdown</property> + </widget> + <packing> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox169"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="Custom" id="signature_dropdown"> + <property name="visible">True</property> + <property name="creation_function">em_account_editor_dropdown_new</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="sigAddNew"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Add Ne_w Signature...</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <signal name="clicked" handler="sigAddNewClicked"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="pack_type">GTK_PACK_END</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="identity_organization"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + <accessibility> + <atkrelation target="label466" type="labelled-by"/> + <atkrelation target="identity_organization_label" type="labelled-by"/> + </accessibility> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="identity_organization_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Or_ganization:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">identity_organization</property> + </widget> + <packing> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="identity_reply_to"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + <accessibility> + <atkrelation target="reply_to_label" type="labelled-by"/> + <atkrelation target="label466" type="labelled-by"/> + </accessibility> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="reply_to_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Re_ply-To:</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="mnemonic_widget">identity_reply_to</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="management_default"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Make this my default account</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="right_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkLabel" id="label31"> + <property name="visible">True</property> + <property name="label" translatable="yes">Identity</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="type">tab</property> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vboxSourceBorder"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="spacing">12</property> + <child> + <widget class="GtkVBox" id="source_vbox"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkTable" id="source_type_table"> + <property name="visible">True</property> + <property name="n_rows">2</property> + <property name="n_columns">3</property> + <property name="column_spacing">12</property> + <property name="row_spacing">6</property> + <child> + <widget class="GtkLabel" id="source_type_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Server _Type: </property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_RIGHT</property> + <property name="mnemonic_widget">source_type_dropdown</property> + </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label442"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="label" translatable="yes">Description:</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="source_description"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="label" translatable="yes">description</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">3</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="Custom" id="source_type_dropdown"> + <property name="visible">True</property> + <property name="creation_function">em_account_editor_dropdown_new</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHSeparator" id="hseparator2"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="source_frame"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label472"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Configuration</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox173"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label565"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="table13"> + <property name="visible">True</property> + <property name="column_spacing">6</property> + <property name="row_spacing">2</property> + <child> + <widget class="GtkTable" id="table4"> + <property name="visible">True</property> + <property name="n_rows">3</property> + <property name="n_columns">2</property> + <property name="column_spacing">12</property> + <property name="row_spacing">6</property> + <child> + <widget class="GtkLabel" id="source_host_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">_Server:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">source_host</property> + </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="source_user_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">User_name:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">source_user</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="source_host"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="source_user"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="source_path_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">_Path:</property> + <property name="use_underline">True</property> + </widget> + <packing> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkFileChooserButton" id="source_path_entry"> + <property name="visible">True</property> + <property name="title" translatable="yes">Mailbox location</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="source_security_frame"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label515"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Security</span></property> + <property name="use_markup">True</property> + <property name="mnemonic_widget">source_auth_dropdown</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox201"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label567"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox181"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkHBox" id="source_ssl_hbox"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="lblSourceUseSSL"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Use Secure Connection:</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="mnemonic_widget">source_use_ssl</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="Custom" id="source_use_ssl"> + <property name="visible">True</property> + <property name="creation_function">em_account_editor_ssl_selector_new</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="source_ssl_disabled"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkImage" id="image2"> + <property name="visible">True</property> + <property name="stock">gtk-dialog-warning</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label514"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><b>SSL is not supported in this build of Evolution</b></property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">3</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="source_auth_frame"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label474"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">_Authentication Type</span></property> + <property name="use_markup">True</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">source_auth_dropdown</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox174"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label566"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox179"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkHBox" id="hbox199"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="Custom" id="source_auth_dropdown"> + <property name="visible">True</property> + <property name="creation_function">em_account_editor_dropdown_new</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="source_check_supported"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes"> Ch_eck for Supported Types </property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkCheckButton" id="source_remember_password"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="tooltip" translatable="yes">Note: you will not be prompted for a password until you connect for the first time</property> + <property name="label" translatable="yes">Re_member password</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">4</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label33"> + <property name="visible">True</property> + <property name="label" translatable="yes">Receiving Email</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="type">tab</property> + <property name="position">1</property> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vboxTransportBorder"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="spacing">12</property> + <child> + <widget class="GtkVBox" id="transport_vbox"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkTable" id="transport_type_table"> + <property name="visible">True</property> + <property name="n_rows">2</property> + <property name="n_columns">3</property> + <property name="column_spacing">12</property> + <property name="row_spacing">6</property> + <child> + <widget class="GtkLabel" id="transport_type_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="label" translatable="yes">Server _Type: </property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_RIGHT</property> + <property name="mnemonic_widget">transport_type_dropdown</property> + </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label50"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="label" translatable="yes">Description:</property> + <property name="justify">GTK_JUSTIFY_RIGHT</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="Custom" id="transport_type_dropdown"> + <property name="visible">True</property> + <property name="creation_function">em_account_editor_dropdown_new</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="transport_description"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="label" translatable="yes">description</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">3</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkHSeparator" id="hseparator3"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="transport_frame"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkVBox" id="transport_server_frame"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label476"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Server Configuration</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox175"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label562"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="table15"> + <property name="visible">True</property> + <property name="column_spacing">6</property> + <property name="row_spacing">2</property> + <child> + <widget class="GtkVBox" id="vbox12"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkTable" id="table6"> + <property name="visible">True</property> + <property name="n_columns">2</property> + <property name="column_spacing">12</property> + <property name="row_spacing">6</property> + <child> + <widget class="GtkLabel" id="transport_host_label"> + <property name="visible">True</property> + <property name="xalign">1</property> + <property name="label" translatable="yes">_Server:</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_RIGHT</property> + <property name="mnemonic_widget">transport_host</property> + </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="transport_host"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="transport_needs_auth"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Ser_ver requires authentication</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkVBox" id="transport_security_frame"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label517"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Security</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox203"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label564"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox183"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkHBox" id="transport_ssl_hbox"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="lblTransportUseSSL"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Use Secure Connection:</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="mnemonic_widget">transport_use_ssl</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="Custom" id="transport_use_ssl"> + <property name="visible">True</property> + <property name="creation_function">em_account_editor_ssl_selector_new</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkHBox" id="transport_ssl_disabled"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkImage" id="image1"> + <property name="visible">True</property> + <property name="stock">gtk-dialog-warning</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="transport_ssl_disabled_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><b>SSL is not supported in this build of Evolution</b></property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="transport_auth_frame"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label478"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Authentication</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox176"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label563"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="table16"> + <property name="visible">True</property> + <property name="column_spacing">6</property> + <property name="row_spacing">2</property> + <child> + <widget class="GtkVBox" id="vbox61"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkTable" id="table31"> + <property name="visible">True</property> + <property name="n_rows">2</property> + <property name="n_columns">2</property> + <property name="column_spacing">12</property> + <property name="row_spacing">6</property> + <child> + <widget class="GtkLabel" id="transport_auth_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">T_ype: </property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="mnemonic_widget">transport_auth_dropdown</property> + </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="transport_user_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">User_name:</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_RIGHT</property> + <property name="mnemonic_widget">transport_user</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="transport_user"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox195"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="Custom" id="transport_auth_dropdown"> + <property name="visible">True</property> + <property name="creation_function">em_account_editor_dropdown_new</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="transport_check_supported"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Ch_eck for Supported Types </property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkFixed" id="fixed5"> + <property name="visible">True</property> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="transport_remember_password"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Remember _password</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label34"> + <property name="visible">True</property> + <property name="label" translatable="yes">Sending Mail</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="type">tab</property> + <property name="position">2</property> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vboxFoldersBorder"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="spacing">12</property> + <child> + <widget class="GtkVBox" id="folders_frame"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label482"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Sent and Draft Messages</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox177"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label560"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="table17"> + <property name="visible">True</property> + <property name="column_spacing">6</property> + <property name="row_spacing">2</property> + <child> + <widget class="GtkVBox" id="vbox184"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkTable" id="folders_table"> + <property name="visible">True</property> + <property name="n_rows">3</property> + <property name="n_columns">3</property> + <property name="column_spacing">12</property> + <property name="row_spacing">6</property> + <child> + <placeholder/> + </child> + <child> + <widget class="GtkLabel" id="drafts_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Drafts _Folder:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">drafts_button</property> + </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="sent_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Sent _Messages Folder:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">sent_button</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="Custom" id="sent_button"> + <property name="visible">True</property> + <property name="creation_function">em_account_editor_folder_selector_button_new</property> + <property name="string1">Select Sent Folder</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="Custom" id="drafts_button"> + <property name="visible">True</property> + <property name="creation_function">em_account_editor_folder_selector_button_new</property> + <property name="string1">Select Drafts Folder</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkFixed" id="fixed9"> + <property name="visible">True</property> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkFixed" id="fixed8"> + <property name="visible">True</property> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox216"> + <property name="visible">True</property> + <child> + <widget class="GtkButton" id="default_folders_button"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-revert-to-saved</property> + <property name="use_stock">True</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkFixed" id="fixed12"> + <property name="visible">True</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">3</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="frame2"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label484"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Composing Messages</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox178"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label561"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="table18"> + <property name="visible">True</property> + <property name="column_spacing">6</property> + <property name="row_spacing">2</property> + <child> + <widget class="GtkTable" id="table8"> + <property name="visible">True</property> + <property name="n_rows">2</property> + <property name="column_spacing">12</property> + <property name="row_spacing">6</property> + <child> + <widget class="GtkVBox" id="vbox186"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkCheckButton" id="always_cc"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Alway_s carbon-copy (cc) to:</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox210"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="label522"> + <property name="visible">True</property> + <property name="xpad">12</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="table32"> + <property name="visible">True</property> + <property name="column_spacing">6</property> + <property name="row_spacing">2</property> + <child> + <widget class="GtkVBox" id="vbox187"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkEntry" id="cc_addrs"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkVBox" id="vbox188"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkCheckButton" id="always_bcc"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Always _blind carbon-copy (bcc) to:</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox211"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="label523"> + <property name="visible">True</property> + <property name="xpad">12</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="table33"> + <property name="visible">True</property> + <property name="column_spacing">6</property> + <property name="row_spacing">2</property> + <child> + <widget class="GtkVBox" id="vbox189"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkEntry" id="bcc_addrs"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox205"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label578"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Message Receipts</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox231"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label581"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox232"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label583"> + <property name="visible">True</property> + <property name="label" translatable="yes">S_end message receipts:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">receipt_policy_dropdown</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkComboBox" id="receipt_policy_dropdown"> + <property name="visible">True</property> + <property name="items" translatable="yes"></property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="position">3</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label35"> + <property name="visible">True</property> + <property name="label" translatable="yes">Defaults</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="type">tab</property> + <property name="position">3</property> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vboxSecurityBorder"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="spacing">12</property> + <child> + <widget class="GtkVBox" id="pgp_frame"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label486"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Pretty Good Privacy (PGP/GPG)</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox179"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label558"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="table19"> + <property name="visible">True</property> + <property name="column_spacing">6</property> + <property name="row_spacing">2</property> + <child> + <widget class="GtkVBox" id="vboxPGP"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkHBox" id="hbox63"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="pgp_key_id_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">PGP/GPG _Key ID:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">pgp_key</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="pgp_key"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="pgp_always_sign"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Al_ways sign outgoing messages when using this account</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="pgp_no_imip_sign"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Do not sign meeting requests (for Outlook compatibility)</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="pgp_encrypt_to_self"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Always encrypt to _myself when sending encrypted messages</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">3</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="pgp_always_trust"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Always _trust keys in my keyring when encrypting</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">4</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="smime_vbox"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label519"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Secure MIME (S/MIME)</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox206"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label559"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="smime_table"> + <property name="visible">True</property> + <property name="n_rows">6</property> + <property name="n_columns">3</property> + <property name="column_spacing">12</property> + <property name="row_spacing">6</property> + <child> + <widget class="GtkEntry" id="smime_sign_key"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="smime_encrypt_key"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">5</property> + <property name="bottom_attach">6</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="smime_encrypt_to_self"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Also encrypt to sel_f when sending encrypted messages</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="right_attach">3</property> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="smime_encrypt_default"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Encrypt out_going messages (by default)</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="right_attach">3</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="smime_sign_default"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Digitally sign o_utgoing messages (by default)</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="right_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkHSeparator" id="hseparator1"> + <property name="visible">True</property> + </widget> + <packing> + <property name="right_attach">3</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options">GTK_FILL</property> + <property name="y_padding">6</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Encry_ption certificate:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">smime_encrypt_key</property> + </widget> + <packing> + <property name="top_attach">5</property> + <property name="bottom_attach">6</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label469"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Sig_ning certificate:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">smime_sign_key</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox208"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkButton" id="smime_encrypt_key_select"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="response_id">0</property> + <child> + <widget class="GtkAlignment" id="alignment28"> + <property name="visible">True</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + <child> + <widget class="GtkHBox" id="hbox2"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <widget class="GtkImage" id="image3"> + <property name="visible">True</property> + <property name="stock">gtk-open</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="button98"> + <property name="visible">True</property> + <property name="label" translatable="yes">S_elect...</property> + <property name="use_underline">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="smime_encrypt_key_clear"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="response_id">0</property> + <child> + <widget class="GtkAlignment" id="alignment35"> + <property name="visible">True</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + <child> + <widget class="GtkHBox" id="hbox230"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <widget class="GtkImage" id="image10"> + <property name="visible">True</property> + <property name="stock">gtk-clear</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label577"> + <property name="visible">True</property> + <property name="label" translatable="yes">Clea_r</property> + <property name="use_underline">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">5</property> + <property name="bottom_attach">6</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox209"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkButton" id="smime_sign_key_select"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="response_id">0</property> + <child> + <widget class="GtkAlignment" id="alignment29"> + <property name="visible">True</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + <child> + <widget class="GtkHBox" id="hbox1"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <widget class="GtkImage" id="image4"> + <property name="visible">True</property> + <property name="stock">gtk-open</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Select...</property> + <property name="use_underline">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="smime_sign_key_clear"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="response_id">0</property> + <child> + <widget class="GtkAlignment" id="alignment34"> + <property name="visible">True</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + <child> + <widget class="GtkHBox" id="hbox229"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <widget class="GtkImage" id="image9"> + <property name="visible">True</property> + <property name="stock">gtk-clear</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label576"> + <property name="visible">True</property> + <property name="label" translatable="yes">Cle_ar</property> + <property name="use_underline">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">4</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="lblSecurity"> + <property name="visible">True</property> + <property name="label" translatable="yes">Security</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="type">tab</property> + <property name="position">4</property> + <property name="tab_fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + <widget class="GtkWindow" id="accounts_tab"> + <property name="title" translatable="yes">Email Accounts</property> + <child> + <widget class="GtkHBox" id="toplevel"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="Custom" id="etableMailAccounts"> + <property name="visible">True</property> + <property name="creation_function">em_account_prefs_treeview_new</property> + </widget> + </child> + <child> + <widget class="GtkVBox" id="vboxMailFunctions"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkVButtonBox" id="vbuttonboxMailAccounts"> + <property name="visible">True</property> + <property name="spacing">6</property> + <property name="layout_style">GTK_BUTTONBOX_START</property> + <child> + <widget class="GtkButton" id="cmdAccountAdd"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="label">gtk-add</property> + <property name="use_stock">True</property> + <property name="response_id">0</property> + </widget> + </child> + <child> + <widget class="GtkButton" id="cmdAccountEdit"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="response_id">0</property> + <child> + <widget class="GtkAlignment" id="alignment33"> + <property name="visible">True</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + <child> + <widget class="GtkHBox" id="hbox224"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <widget class="GtkImage" id="image8"> + <property name="visible">True</property> + <property name="stock">gtk-properties</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label557"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Edit</property> + <property name="use_underline">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="cmdAccountDelete"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="label">gtk-delete</property> + <property name="use_stock">True</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="cmdAccountDefault"> + <property name="width_request">89</property> + <property name="height_request">36</property> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="label" translatable="yes">De_fault</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="position">3</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + <widget class="GtkWindow" id="preferences_tab"> + <property name="title" translatable="yes">Mail Preferences</property> + <child> + <widget class="GtkNotebook" id="preferences_toplevel"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="scrollable">True</property> + <child> + <widget class="GtkVBox" id="vboxGeneral"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="spacing">12</property> + <child> + <widget class="GtkVBox" id="FontsFrame"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label492"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Message Fonts</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox182"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label540"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="table22"> + <property name="visible">True</property> + <property name="column_spacing">6</property> + <property name="row_spacing">2</property> + <child> + <widget class="GtkVBox" id="vboxMessageFonts"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkCheckButton" id="radFontUseSame"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Use the same fonts as other applications</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="tblScreen"> + <property name="visible">True</property> + <property name="n_rows">2</property> + <property name="n_columns">2</property> + <property name="column_spacing">6</property> + <property name="row_spacing">6</property> + <child> + <widget class="GtkLabel" id="lblScreenVariable"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">S_tandard Font:</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_RIGHT</property> + <property name="mnemonic_widget">FontVariable</property> + </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkFontButton" id="FontFixed"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="response_id">0</property> + <property name="title" translatable="yes">Select HTML fixed width font</property> + <signal name="font_set" handler="changed"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkFontButton" id="FontVariable"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="response_id">0</property> + <property name="title" translatable="yes">Select HTML variable width font</property> + <signal name="font_set" handler="changed"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label444"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Fix_ed width Font:</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_RIGHT</property> + <property name="mnemonic_widget">FontFixed</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="MessageDisplayFrame"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label494"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Message Display</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox183"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label541"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="table23"> + <property name="visible">True</property> + <property name="column_spacing">6</property> + <property name="row_spacing">2</property> + <child> + <widget class="GtkVBox" id="vboxMessageDisplay"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkHBox" id="hboxReadTimeout"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkCheckButton" id="chkMarkTimeout"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Mark messages as read after</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkSpinButton" id="spinMarkTimeout"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="adjustment">1.5 0 10 1 1 0</property> + <property name="climb_rate">1</property> + <property name="digits">1</property> + <property name="numeric">True</property> + <property name="update_policy">GTK_UPDATE_IF_VALID</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="lblSeconds"> + <property name="visible">True</property> + <property name="label" translatable="yes">seconds</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkHBox" id="hbox234"> + <property name="visible">True</property> + <property name="spacing">4</property> + <child> + <widget class="GtkCheckButton" id="mlimit_checkbutton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Do not format messages when text si_ze exceeds</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkSpinButton" id="mlimit_spin"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="adjustment">0 0 30000 1 10 0</property> + <property name="climb_rate">1</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label585"> + <property name="visible">True</property> + <property name="label" translatable="yes">KB</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox233"> + <property name="visible">True</property> + <child> + <widget class="GtkCheckButton" id="address_checkbox"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Shrink To / Cc / Bcc headers to </property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkSpinButton" id="address_spin"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="adjustment">5 1 100 1 10 0</property> + <property name="climb_rate">1</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">2</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label584"> + <property name="visible">True</property> + <property name="label" translatable="yes">addresses</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">2</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="magic_spacebar_checkbox"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Enable Magic S_pacebar</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">3</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hboxHighlightColor"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkCheckButton" id="chkHighlightCitations"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Highlight _quotations with</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkColorButton" id="colorButtonHighlightCitations"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="response_id">0</property> + <property name="title" translatable="yes">Pick a color</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="lblColor"> + <property name="visible">True</property> + <property name="label" translatable="yes">color</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="position">4</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hboxDefaultCharset"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="lblDefaultCharset"> + <property name="visible">True</property> + <property name="label" translatable="yes">Default character e_ncoding:</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="mnemonic_widget">omenuCharset</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkOptionMenu" id="omenuCharset"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">5</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hboxEnableSearchFolders"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkCheckButton" id="chkEnableSearchFolders"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Enable Sea_rch Folders</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="lblEnableSFRestart"> + <property name="visible">True</property> + <property name="label" translatable="yes">(Note: Requires restart of the application)</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">6</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="DeleteMailFrame"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label496"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Delete Mail</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox184"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label542"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="table24"> + <property name="visible">True</property> + <property name="column_spacing">6</property> + <property name="row_spacing">2</property> + <child> + <widget class="GtkVBox" id="vboxDeletingMail"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkHBox" id="hbox220"> + <property name="visible">True</property> + <property name="spacing">4</property> + <child> + <widget class="GtkCheckButton" id="chkEmptyTrashOnExit"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Empty trash folders on e_xit</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkOptionMenu" id="omenuEmptyTrashDays"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkCheckButton" id="chkConfirmExpunge"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Confirm _when expunging a folder</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkLabel" id="lblGeneral"> + <property name="visible">True</property> + <property name="label" translatable="yes">General</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="type">tab</property> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vboxHtmlMail"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label530"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">General</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox215"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label538"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox173"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkCheckButton" id="chkShowAnimatedImages"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes" comments="If enabled, show animation; if disabled, only display a static image without any animation">_Show image animations</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="chkPromptWantHTML"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Prompt on sending HTML mail to contacts that do not want them</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vboxLoadingImages"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label500"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Loading Images</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox186"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label539"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox190"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkRadioButton" id="radImagesNever"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Never load images from the Internet</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkRadioButton" id="radImagesSometimes"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Load images in messages from contacts</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + <property name="group">radImagesNever</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkRadioButton" id="radImagesAlways"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Always load images from the Internet</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + <property name="group">radImagesNever</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="lblHtmlMail"> + <property name="visible">True</property> + <property name="label" translatable="yes">HTML Messages</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="type">tab</property> + <property name="position">1</property> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="frameColours"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label502"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Labels</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkAlignment" id="labels-alignment"> + <property name="visible">True</property> + <property name="left_padding">12</property> + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="lblColours"> + <property name="visible">True</property> + <property name="label" translatable="yes">Labels</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="type">tab</property> + <property name="position">2</property> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vboxHeaderTab"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="spacing">6</property> + <child> + <widget class="GtkVBox" id="vbox206"> + <property name="visible">True</property> + <property name="spacing">3</property> + <child> + <widget class="GtkHBox" id="hbox238"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="label587"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Sender Photograph</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox206"> + <property name="visible">True</property> + <child> + <widget class="GtkHBox" id="hbox239"> + <property name="visible">True</property> + <child> + <widget class="GtkCheckButton" id="photo_show"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Show the photograph of sender in the message preview</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">10</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox240"> + <property name="visible">True</property> + <child> + <widget class="GtkCheckButton" id="photo_local"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">S_earch for sender photograph only in local address books</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">10</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label524"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Displayed Message _Headers</span></property> + <property name="use_markup">True</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">txtHeaders</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox212"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label536"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox199"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkEntry" id="txtHeaders"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow49"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <child> + <widget class="GtkTreeView" id="treeHeaders"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">False</property> + <accessibility> + <atkproperty name="AtkObject::accessible_name" translatable="yes">Mail Headers Table</atkproperty> + </accessibility> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox200"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkButton" id="cmdHeadersAdd"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_focus">True</property> + <property name="label">gtk-add</property> + <property name="use_stock">True</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="cmdHeadersRemove"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-remove</property> + <property name="use_stock">True</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="position">3</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="lblHeaders"> + <property name="visible">True</property> + <property name="label" translatable="yes">Headers</property> + <property name="use_underline">True</property> + </widget> + <packing> + <property name="type">tab</property> + <property name="position">3</property> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox161"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="spacing">6</property> + <child> + <widget class="GtkVBox" id="vbox192"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="label526"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">General</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="table34"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="n_rows">9</property> + <property name="row_spacing">3</property> + <child> + <widget class="GtkHBox" id="hbox235"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label586"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Default junk plugin:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">default_junk_plugin</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">6</property> + </packing> + </child> + <child> + <widget class="Custom" id="default_junk_plugin"> + <property name="visible">True</property> + <property name="creation_function">create_combo_text_widget</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="top_attach">7</property> + <property name="bottom_attach">8</property> + <property name="x_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="chkCheckIncomingMail"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="tooltip" translatable="yes">Checks incoming mail messages to be Junk</property> + <property name="label" translatable="yes">Check incoming _messages for junk</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + <property name="x_padding">4</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox236"> + <property name="visible">True</property> + <property name="spacing">3</property> + <child> + <widget class="GtkImage" id="plugin_image"> + <property name="visible">True</property> + <property name="icon_name">gtk-info</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="plugin_status"> + <property name="visible">True</property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="top_attach">8</property> + <property name="bottom_attach">9</property> + <property name="x_options">GTK_FILL</property> + <property name="x_padding">15</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox237"> + <property name="visible">True</property> + <property name="spacing">4</property> + <child> + <widget class="GtkCheckButton" id="junk_empty_check"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Delete junk messages on e_xit</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkOptionMenu" id="junk_empty_combo"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="x_padding">4</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="junk_header_check"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Check cu_stom headers for junk</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + <property name="x_padding">4</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox243"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow51"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <child> + <widget class="GtkTreeView" id="junk_header_tree"> + <property name="visible">True</property> + <property name="can_focus">True</property> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkVButtonBox" id="vbuttonbox26"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_SPREAD</property> + <child> + <widget class="GtkButton" id="junk_header_add"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="label">gtk-add</property> + <property name="use_stock">True</property> + <property name="response_id">0</property> + </widget> + </child> + <child> + <widget class="GtkButton" id="junk_header_remove"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="label">gtk-remove</property> + <property name="use_stock">True</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="x_padding">22</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="lookup_book"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Do not mar_k messages as junk if sender is in my address book</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + <property name="x_padding">4</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="junk_lookup_local_only"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Lookup in local address book only</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="top_attach">5</property> + <property name="bottom_attach">6</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + <property name="x_padding">25</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox244"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkImage" id="image11"> + <property name="visible">True</property> + <property name="stock">gtk-info</property> + </widget> + <packing> + <property name="expand">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label590"> + <property name="visible">True</property> + <property name="label" translatable="yes">Option is ignored if a match for custom junk headers is found.</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="top_attach">6</property> + <property name="bottom_attach">7</property> + <property name="x_options">GTK_FILL</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox195"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">4</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label473"> + <property name="visible">True</property> + <property name="label" translatable="yes">Junk</property> + <property name="use_underline">True</property> + </widget> + <packing> + <property name="type">tab</property> + <property name="position">4</property> + <property name="tab_fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + <widget class="GtkWindow" id="composer_tab"> + <property name="title" translatable="yes">Message Composer</property> + <child> + <widget class="GtkNotebook" id="composer_toplevel"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <child> + <widget class="GtkVBox" id="vboxGeneral1"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="spacing">18</property> + <child> + <widget class="GtkVBox" id="frameBehavior"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label504"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Default Behavior</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox189"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="label505"> + <property name="visible">True</property> + <property name="xpad">12</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="table28"> + <property name="visible">True</property> + <property name="column_spacing">6</property> + <property name="row_spacing">2</property> + <child> + <widget class="GtkVBox" id="vboxBehavior"> + <property name="visible">True</property> + <property name="spacing">8</property> + <child> + <widget class="GtkCheckButton" id="chkSendHTML"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Format messages in _HTML</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="chkAutoSmileys"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Automatically insert _emoticon images</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="chkRequestReceipt"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Always request rea_d receipt</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="chkReplyStartBottom"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Start _typing at the bottom on replying</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">3</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="chkOutlookFilenames"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Encode file names in an Outlook/GMail way</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">4</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="tableForwardsReplies"> + <property name="visible">True</property> + <property name="n_rows">3</property> + <property name="n_columns">2</property> + <property name="column_spacing">12</property> + <property name="row_spacing">6</property> + <child> + <widget class="GtkLabel" id="lblReplyStyle"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">_Reply style:</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkOptionMenu" id="omenuCharset1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="lblForwardStyle"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">_Forward style:</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="lblCharset"> + <property name="visible">True</property> + <property name="label" translatable="yes">C_haracter set:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">omenuCharset1</property> + </widget> + <packing> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkComboBox" id="comboboxForwardStyle"> + <property name="visible">True</property> + <property name="items" translatable="yes">Attachment Inline Quoted</property> - <property name="add_tearoffs">False</property> - <property name="focus_on_click">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options">fill</property> - </packing> - </child> - - <child> - <widget class="GtkOptionMenu" id="omenuCharset1"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="history">0</property> - - <child internal-child="menu"> - <widget class="GtkMenu" id="convertwidget41"> - <property name="visible">True</property> - - <child> - <widget class="GtkMenuItem" id="convertwidget42"> - <property name="visible">True</property> - <property name="label" translatable="yes">Baltic (ISO-8859-13)</property> - <property name="use_underline">True</property> - </widget> - </child> - - <child> - <widget class="GtkMenuItem" id="convertwidget43"> - <property name="visible">True</property> - <property name="label" translatable="yes">Baltic (ISO-8859-4)</property> - <property name="use_underline">True</property> - </widget> - </child> - </widget> - </child> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="lblForwardStyle"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Forward style:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="lblCharset"> - <property name="visible">True</property> - <property name="label" translatable="yes">C_haracter set:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">omenuCharset1</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox241"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">2</property> - - <child> - <widget class="GtkVBox" id="vbox207"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">8</property> - - <child> - <widget class="GtkLabel" id="label588"> - <property name="visible">True</property> - <property name="label" translatable="yes"><b>Top Posting Option</b> (Not Recommended)</property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.479999989271</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="chkTopSignature"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">_Keep Signature above the original message on replying</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <placeholder/> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label506"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Alerts</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox190"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkLabel" id="label507"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">12</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="table29"> - <property name="visible">True</property> - <property name="n_rows">1</property> - <property name="n_columns">1</property> - <property name="homogeneous">False</property> - <property name="row_spacing">2</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkVBox" id="vboxAlerts"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkCheckButton" id="chkPromptEmptySubject"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">_Prompt when sending messages with an empty subject line</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="chkPromptBccOnly"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Pr_ompt when sending messages with only Bcc recipients defined</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="tab_expand">False</property> - <property name="tab_fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="lblGeneral"> - <property name="visible">True</property> - <property name="label" translatable="yes">General</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">tab</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vboxSignatures"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkVBox" id="vbox201"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label548"> - <property name="visible">True</property> - <property name="label" translatable="yes"><b>Sig_natures</b></property> - <property name="use_underline">True</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">listSignatures</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hboxSignatures"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label550"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label549"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkScrolledWindow" id="scrolledwindow46"> - <property name="visible">True</property> - <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="shadow_type">GTK_SHADOW_IN</property> - <property name="window_placement">GTK_CORNER_TOP_LEFT</property> - - <child> - <widget class="GtkTreeView" id="listSignatures"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="headers_visible">False</property> - <property name="rules_hint">False</property> - <property name="reorderable">False</property> - <property name="enable_search">True</property> - <property name="fixed_height_mode">False</property> - <property name="hover_selection">False</property> - <property name="hover_expand">False</property> - <accessibility> - <atkproperty name="AtkObject::accessible_name" translatable="yes">Signatures Table</atkproperty> - </accessibility> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vboxSignatureButtons"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">3</property> - - <child> - <widget class="GtkVButtonBox" id="vbuttonbox25"> - <property name="visible">True</property> - <property name="layout_style">GTK_BUTTONBOX_START</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkButton" id="cmdSignatureAdd"> - <property name="visible">True</property> - <property name="can_default">True</property> - <property name="can_focus">True</property> - <property name="label">gtk-add</property> - <property name="use_stock">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - </widget> - </child> - - <child> - <widget class="GtkButton" id="cmdSignatureAddScript"> - <property name="visible">True</property> - <property name="can_default">True</property> - <property name="can_focus">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="cmdSignatureAddScriptClicked"/> - - <child> - <widget class="GtkAlignment" id="alignment32"> - <property name="visible">True</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xscale">0</property> - <property name="yscale">0</property> - <property name="top_padding">0</property> - <property name="bottom_padding">0</property> - <property name="left_padding">0</property> - <property name="right_padding">0</property> - - <child> - <widget class="GtkHBox" id="hbox223"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">2</property> - - <child> - <widget class="GtkImage" id="image7"> - <property name="visible">True</property> - <property name="stock">gtk-execute</property> - <property name="icon_size">4</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label554"> - <property name="visible">True</property> - <property name="label" translatable="yes">Add _Script</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - </child> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GtkButton" id="cmdSignatureEdit"> - <property name="visible">True</property> - <property name="can_default">True</property> - <property name="can_focus">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - - <child> - <widget class="GtkAlignment" id="alignment31"> - <property name="visible">True</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xscale">0</property> - <property name="yscale">0</property> - <property name="top_padding">0</property> - <property name="bottom_padding">0</property> - <property name="left_padding">0</property> - <property name="right_padding">0</property> - - <child> - <widget class="GtkHBox" id="hbox222"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">2</property> - - <child> - <widget class="GtkImage" id="image6"> - <property name="visible">True</property> - <property name="stock">gtk-properties</property> - <property name="icon_size">4</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label553"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Edit</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - </child> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GtkButton" id="cmdSignatureDelete"> - <property name="visible">True</property> - <property name="can_default">True</property> - <property name="can_focus">True</property> - <property name="label">gtk-remove</property> - <property name="use_stock">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox202"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label551"> - <property name="visible">True</property> - <property name="label" translatable="yes"><b>Preview</b></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox162"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label552"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkScrolledWindow" id="scrolled-sig"> - <property name="visible">True</property> - <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="shadow_type">GTK_SHADOW_IN</property> - <property name="window_placement">GTK_CORNER_TOP_LEFT</property> - - <child> - <placeholder/> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="tab_expand">False</property> - <property name="tab_fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="lblSignatures"> - <property name="visible">True</property> - <property name="label" translatable="yes">Signatures</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">tab</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vboxSpellChecking"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkVBox" id="vbox196"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label534"> - <property name="visible">True</property> - <property name="label" translatable="yes"><b>_Languages</b></property> - <property name="use_underline">True</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">listSpellCheckLanguage</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox218"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label555"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox197"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkVBox" id="vbox178"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkHBox" id="hbox192"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkHBox" id="hboxLanguages"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkScrolledWindow" id="scrolledwindow48"> - <property name="visible">True</property> - <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="shadow_type">GTK_SHADOW_IN</property> - <property name="window_placement">GTK_CORNER_TOP_LEFT</property> - - <child> - <widget class="GtkTreeView" id="listSpellCheckLanguage"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="headers_visible">False</property> - <property name="rules_hint">False</property> - <property name="reorderable">False</property> - <property name="enable_search">True</property> - <property name="fixed_height_mode">False</property> - <property name="hover_selection">False</property> - <property name="hover_expand">False</property> - <accessibility> - <atkproperty name="AtkObject::accessible_name" translatable="yes">Languages Table</atkproperty> - </accessibility> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hboxImageAndHelp"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkImage" id="pixmapSpellInfo"> - <property name="visible">True</property> - <property name="stock">gtk-dialog-info</property> - <property name="icon_size">4</property> - <property name="xalign">0.5</property> - <property name="yalign">0</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="lblSpellChecking"> - <property name="visible">True</property> - <property name="label" translatable="yes">The list of languages here reflects only the languages for which you have a dictionary installed.</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">True</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="frameSpellChecking"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label508"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Options</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox191"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label556"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vboxOptions"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkCheckButton" id="chkEnableSpellChecking"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Check spelling while I _type</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hboxSpellCheckColor"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="lblSpellCheckColor"> - <property name="visible">True</property> - <property name="label" translatable="yes">Color for _misspelled words:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">colorButtonSpellCheckColor</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkColorButton" id="colorButtonSpellCheckColor"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="use_alpha">False</property> - <property name="title" translatable="yes">Pick a color</property> - <property name="focus_on_click">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="tab_expand">False</property> - <property name="tab_fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label450"> - <property name="visible">True</property> - <property name="label" translatable="yes">Spell Checking</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">tab</property> - </packing> - </child> - </widget> - </child> -</widget> - -<widget class="GtkWindow" id="font_tab"> - <property name="title" translatable="yes">Font Properties</property> - <property name="type">GTK_WINDOW_TOPLEVEL</property> - <property name="window_position">GTK_WIN_POS_NONE</property> - <property name="modal">False</property> - <property name="resizable">True</property> - <property name="destroy_with_parent">False</property> - <property name="decorated">True</property> - <property name="skip_taskbar_hint">False</property> - <property name="skip_pager_hint">False</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> - <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> - <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> - - <child> - <widget class="GtkVBox" id="toplevel"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <placeholder/> - </child> - - <child> - <widget class="GtkVBox" id="frame4"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label512"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Printed Fonts</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox194"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkLabel" id="label513"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">12</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="tblPrint"> - <property name="visible">True</property> - <property name="n_rows">2</property> - <property name="n_columns">2</property> - <property name="homogeneous">False</property> - <property name="row_spacing">6</property> - <property name="column_spacing">12</property> - - <child> - <widget class="GtkLabel" id="lblPrintVariable"> - <property name="visible">True</property> - <property name="label" translatable="yes">V_ariable-width:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">print_variable</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="lblPrintFixed"> - <property name="visible">True</property> - <property name="label" translatable="yes">Fi_xed-width:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">print_fixed</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkFontButton" id="print_fixed"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="title" translatable="yes">Select HTML fixed width font for printing</property> - <property name="show_style">True</property> - <property name="show_size">True</property> - <property name="use_font">False</property> - <property name="use_size">False</property> - <property name="focus_on_click">True</property> - <signal name="font_set" handler="changed"/> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkFontButton" id="print_variable"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="title" translatable="yes">Select HTML variable width font for printing</property> - <property name="show_style">True</property> - <property name="show_size">True</property> - <property name="use_font">False</property> - <property name="use_size">False</property> - <property name="focus_on_click">True</property> - <signal name="font_set" handler="changed"/> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - </child> -</widget> - -<widget class="GtkDialog" id="add_script_signature"> - <property name="title" translatable="yes"></property> - <property name="type">GTK_WINDOW_TOPLEVEL</property> - <property name="window_position">GTK_WIN_POS_NONE</property> - <property name="modal">False</property> - <property name="resizable">True</property> - <property name="destroy_with_parent">False</property> - <property name="decorated">True</property> - <property name="skip_taskbar_hint">False</property> - <property name="skip_pager_hint">False</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> - <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> - <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> - <property name="has_separator">False</property> - - <child internal-child="vbox"> - <widget class="GtkVBox" id="dialog-vbox1"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child internal-child="action_area"> - <widget class="GtkHButtonBox" id="dialog-action_area1"> - <property name="visible">True</property> - <property name="layout_style">GTK_BUTTONBOX_END</property> - - <child> - <widget class="GtkButton" id="button_add_script_add"> - <property name="visible">True</property> - <property name="can_default">True</property> - <property name="can_focus">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="response_id">0</property> - - <child> - <widget class="GtkAlignment" id="alignment30"> - <property name="visible">True</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xscale">0</property> - <property name="yscale">0</property> - <property name="top_padding">0</property> - <property name="bottom_padding">0</property> - <property name="left_padding">0</property> - <property name="right_padding">0</property> - - <child> - <widget class="GtkHBox" id="hbox221"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">2</property> - - <child> - <widget class="GtkImage" id="image5"> - <property name="visible">True</property> - <property name="stock">gtk-add</property> - <property name="icon_size">4</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label547"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Add Signature</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - </child> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GtkButton" id="button_add_script_cancel"> - <property name="visible">True</property> - <property name="can_default">True</property> - <property name="can_focus">True</property> - <property name="label">gtk-cancel</property> - <property name="use_stock">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="response_id">0</property> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="pack_type">GTK_PACK_END</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox160"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkVBox" id="vbox_add_script_signature"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkHBox" id="hboxImageAndHelp"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkImage" id="pixmap1"> - <property name="visible">True</property> - <property name="stock">gtk-dialog-info</property> - <property name="icon_size">6</property> - <property name="xalign">0.5</property> - <property name="yalign">0</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label456"> - <property name="visible">True</property> - <property name="label" translatable="yes">The output of this script will be used as your + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + </packing> + </child> + <child> + <widget class="GtkComboBox" id="comboboxReplyStyle"> + <property name="visible">True</property> + <property name="items" translatable="yes">Attachment +Inline (Outlook style) +Quoted +Do Not Quote</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + </packing> + </child> + </widget> + <packing> + <property name="position">5</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox241"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <widget class="GtkVBox" id="vbox207"> + <property name="visible">True</property> + <property name="spacing">8</property> + <child> + <widget class="GtkLabel" id="label588"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0.47999998927116394</property> + <property name="label" translatable="yes"><b>Top Posting Option</b> (Not Recommended)</property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="chkTopSignature"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Keep Signature above the original message on replying</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <placeholder/> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">6</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label506"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Alerts</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox190"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="label507"> + <property name="visible">True</property> + <property name="xpad">12</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="table29"> + <property name="visible">True</property> + <property name="column_spacing">6</property> + <property name="row_spacing">2</property> + <child> + <widget class="GtkVBox" id="vboxAlerts"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkCheckButton" id="chkPromptEmptySubject"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Prompt when sending messages with an empty subject line</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="chkPromptBccOnly"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Pr_ompt when sending messages with only Bcc recipients defined</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">3</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkLabel" id="lblGeneral1"> + <property name="visible">True</property> + <property name="label" translatable="yes">General</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="type">tab</property> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vboxSignatures"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="spacing">12</property> + <child> + <widget class="GtkVBox" id="vbox201"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label548"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><b>Sig_natures</b></property> + <property name="use_markup">True</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">listSignatures</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkAlignment" id="alignSignatures"> + <property name="visible">True</property> + <property name="left_padding">12</property> + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkVBox" id="vbox202"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label551"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><b>Preview</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox162"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label552"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkScrolledWindow" id="scrolled-sig"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="lblSignatures"> + <property name="visible">True</property> + <property name="label" translatable="yes">Signatures</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="type">tab</property> + <property name="position">1</property> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vboxSpellChecking"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="spacing">12</property> + <child> + <widget class="GtkVBox" id="vbox196"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label534"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><b>_Languages</b></property> + <property name="use_markup">True</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">listSpellCheckLanguage</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox218"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label555"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox197"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkVBox" id="vbox178"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkHBox" id="hbox192"> + <property name="visible">True</property> + <child> + <widget class="GtkHBox" id="hboxLanguages"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow48"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <child> + <widget class="GtkTreeView" id="listSpellCheckLanguage"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">False</property> + <accessibility> + <atkproperty name="AtkObject::accessible_name" translatable="yes">Languages Table</atkproperty> + </accessibility> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkHBox" id="hboxImageAndHelp"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkImage" id="pixmapSpellInfo"> + <property name="visible">True</property> + <property name="yalign">0</property> + <property name="stock">gtk-dialog-info</property> + </widget> + <packing> + <property name="expand">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="lblSpellChecking"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">The list of languages here reflects only the languages for which you have a dictionary installed.</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkVBox" id="frameSpellChecking"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label508"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Options</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox191"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label556"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vboxOptions"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkCheckButton" id="chkEnableSpellChecking"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Check spelling while I _type</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hboxSpellCheckColor"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="lblSpellCheckColor"> + <property name="visible">True</property> + <property name="label" translatable="yes">Color for _misspelled words:</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="mnemonic_widget">colorButtonSpellCheckColor</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkColorButton" id="colorButtonSpellCheckColor"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="response_id">0</property> + <property name="title" translatable="yes">Pick a color</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label450"> + <property name="visible">True</property> + <property name="label" translatable="yes">Spell Checking</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + </widget> + <packing> + <property name="type">tab</property> + <property name="position">2</property> + <property name="tab_fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + <widget class="GtkWindow" id="font_tab"> + <property name="title" translatable="yes">Font Properties</property> + <child> + <widget class="GtkVBox" id="toplevel1"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <placeholder/> + </child> + <child> + <widget class="GtkVBox" id="frame4"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label512"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Printed Fonts</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox194"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="label513"> + <property name="visible">True</property> + <property name="xpad">12</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="tblPrint"> + <property name="visible">True</property> + <property name="n_rows">2</property> + <property name="n_columns">2</property> + <property name="column_spacing">12</property> + <property name="row_spacing">6</property> + <child> + <widget class="GtkLabel" id="lblPrintVariable"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">V_ariable-width:</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="mnemonic_widget">print_variable</property> + </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="lblPrintFixed"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Fi_xed-width:</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="mnemonic_widget">print_fixed</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkFontButton" id="print_fixed"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="response_id">0</property> + <property name="title" translatable="yes">Select HTML fixed width font for printing</property> + <signal name="font_set" handler="changed"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkFontButton" id="print_variable"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="response_id">0</property> + <property name="title" translatable="yes">Select HTML variable width font for printing</property> + <signal name="font_set" handler="changed"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + <widget class="GtkDialog" id="add_script_signature"> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> + <property name="has_separator">False</property> + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox1"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkVBox" id="vbox160"> + <property name="visible">True</property> + <child> + <widget class="GtkVBox" id="vbox_add_script_signature"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="spacing">6</property> + <child> + <widget class="GtkHBox" id="hboxImageAndHelp1"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkImage" id="pixmap1"> + <property name="visible">True</property> + <property name="yalign">0</property> + <property name="stock">gtk-dialog-info</property> + <property name="icon_size">6</property> + </widget> + </child> + <child> + <widget class="GtkLabel" id="label456"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">The output of this script will be used as your signature. The name you specify will be used for display purposes only. </property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">True</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="tblNameScript"> - <property name="visible">True</property> - <property name="n_rows">2</property> - <property name="n_columns">2</property> - <property name="homogeneous">False</property> - <property name="row_spacing">6</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkLabel" id="label459"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Name:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">entry_add_script_name</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label460"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Script:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">filechooserbutton_add_script</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="entry_add_script_name"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkFileChooserButton" id="filechooserbutton_add_script"> - <property name="visible">True</property> - <property name="title" translatable="yes"></property> - <property name="action">GTK_FILE_CHOOSER_ACTION_OPEN</property> - <property name="local_only">True</property> - <property name="show_hidden">False</property> - <property name="do_overwrite_confirmation">False</property> - <property name="width_chars">-1</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - </child> -</widget> - -<widget class="GtkWindow" id="network_prefs_tab"> - <property name="visible">True</property> - <property name="title" translatable="yes">window1</property> - <property name="type">GTK_WINDOW_TOPLEVEL</property> - <property name="window_position">GTK_WIN_POS_NONE</property> - <property name="modal">False</property> - <property name="resizable">True</property> - <property name="destroy_with_parent">False</property> - <property name="decorated">True</property> - <property name="skip_taskbar_hint">False</property> - <property name="skip_pager_hint">False</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> - <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> - <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> - - <child> - <widget class="GtkNotebook" id="network_preferences_toplevel"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="show_tabs">True</property> - <property name="show_border">True</property> - <property name="tab_pos">GTK_POS_TOP</property> - <property name="scrollable">False</property> - <property name="enable_popup">False</property> - - <child> - <widget class="GtkVBox" id="vboxGeneral"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">18</property> - - <child> - <widget class="GtkVBox" id="frameProxy"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label76"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Proxy Settings</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vboxProxy"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">8</property> - - <child> - <widget class="GtkRadioButton" id="rdoSysSettings"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">_Use system defaults</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkRadioButton" id="rdoNoProxy"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">_Direct connection to the Internet</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - <property name="group">rdoSysSettings</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkRadioButton" id="rdoManualProxy"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">_Manual proxy configuration:</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - <property name="group">rdoSysSettings</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkAlignment" id="alignment27"> - <property name="visible">True</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xscale">1</property> - <property name="yscale">1</property> - <property name="top_padding">0</property> - <property name="bottom_padding">0</property> - <property name="left_padding">24</property> - <property name="right_padding">0</property> - - <child> - <widget class="GtkVBox" id="vbox18"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkTable" id="table8"> - <property name="visible">True</property> - <property name="n_rows">4</property> - <property name="n_columns">4</property> - <property name="homogeneous">False</property> - <property name="row_spacing">6</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkLabel" id="lblHttpHost"> - <property name="visible">True</property> - <property name="label" translatable="yes">H_TTP Proxy:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">txtHttpHost</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="lblHttpsHost"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Secure HTTP Proxy:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">txtHttpsHost</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="lblIgnoreHosts"> - <property name="visible">True</property> - <property name="label" translatable="yes">No _Proxy for:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">txtIgnoreHosts</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="txtHttpHost"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="txtHttpsHost"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="lblHttpPort"> - <property name="visible">True</property> - <property name="label" translatable="yes">Port:</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="lblHttpsPort"> - <property name="visible">True</property> - <property name="label" translatable="yes">Port:</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkSpinButton" id="spnHttpPort"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="climb_rate">1</property> - <property name="digits">0</property> - <property name="numeric">False</property> - <property name="update_policy">GTK_UPDATE_ALWAYS</property> - <property name="snap_to_ticks">False</property> - <property name="wrap">False</property> - <property name="adjustment">0 0 65535 1 10 0</property> - </widget> - <packing> - <property name="left_attach">3</property> - <property name="right_attach">4</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkSpinButton" id="spnHttpsPort"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="climb_rate">1</property> - <property name="digits">0</property> - <property name="numeric">False</property> - <property name="update_policy">GTK_UPDATE_ALWAYS</property> - <property name="snap_to_ticks">False</property> - <property name="wrap">False</property> - <property name="adjustment">0 0 65535 1 10 0</property> - </widget> - <packing> - <property name="left_attach">3</property> - <property name="right_attach">4</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="txtIgnoreHosts"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">4</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="y_options"></property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="chkUseAuth"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Use Authe_ntication</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkAlignment" id="alignment26"> - <property name="visible">True</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xscale">1</property> - <property name="yscale">1</property> - <property name="top_padding">0</property> - <property name="bottom_padding">0</property> - <property name="left_padding">24</property> - <property name="right_padding">0</property> - - <child> - <widget class="GtkTable" id="table11"> - <property name="visible">True</property> - <property name="n_rows">2</property> - <property name="n_columns">2</property> - <property name="homogeneous">False</property> - <property name="row_spacing">3</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkLabel" id="lblAuthUser"> - <property name="visible">True</property> - <property name="label" translatable="yes">Us_ername:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">txtAuthUser</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="lblAuthPwd"> - <property name="visible">True</property> - <property name="label" translatable="yes">Pass_word:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">txtAuthPwd</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="txtAuthUser"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="txtAuthPwd"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">False</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - </packing> - </child> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="tab_expand">False</property> - <property name="tab_fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="lblGeneral"> - <property name="visible">True</property> - <property name="label" translatable="yes">General</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">tab</property> - </packing> - </child> - </widget> - </child> -</widget> - + <property name="wrap">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="tblNameScript"> + <property name="visible">True</property> + <property name="n_rows">2</property> + <property name="n_columns">2</property> + <property name="column_spacing">6</property> + <property name="row_spacing">6</property> + <child> + <widget class="GtkLabel" id="label459"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">_Name:</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="mnemonic_widget">entry_add_script_name</property> + </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label460"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">_Script:</property> + <property name="use_underline">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="mnemonic_widget">filechooserbutton_add_script</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="entry_add_script_name"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkFileChooserButton" id="filechooserbutton_add_script"> + <property name="visible">True</property> + <property name="title" translatable="yes"></property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area1"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + <child> + <widget class="GtkButton" id="button_add_script_add"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="response_id">0</property> + <child> + <widget class="GtkAlignment" id="alignment30"> + <property name="visible">True</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + <child> + <widget class="GtkHBox" id="hbox221"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <widget class="GtkImage" id="image5"> + <property name="visible">True</property> + <property name="stock">gtk-add</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label547"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Add Signature</property> + <property name="use_underline">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkButton" id="button_add_script_cancel"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="label">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + </widget> + </child> + </widget> + <widget class="GtkWindow" id="network_prefs_tab"> + <property name="visible">True</property> + <property name="title" translatable="yes">window1</property> + <child> + <widget class="GtkNotebook" id="network_preferences_toplevel"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <child> + <widget class="GtkVBox" id="vboxGeneral2"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="spacing">18</property> + <child> + <widget class="GtkVBox" id="frameProxy"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label76"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><span weight="bold">Proxy Settings</span></property> + <property name="use_markup">True</property> + </widget> + </child> + <child> + <widget class="GtkVBox" id="vboxProxy"> + <property name="visible">True</property> + <property name="border_width">12</property> + <property name="spacing">8</property> + <child> + <widget class="GtkRadioButton" id="rdoSysSettings"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Use system defaults</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + </child> + <child> + <widget class="GtkRadioButton" id="rdoNoProxy"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Direct connection to the Internet</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + <property name="group">rdoSysSettings</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkRadioButton" id="rdoManualProxy"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Manual proxy configuration:</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + <property name="group">rdoSysSettings</property> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkAlignment" id="alignment27"> + <property name="visible">True</property> + <property name="left_padding">24</property> + <child> + <widget class="GtkVBox" id="vbox18"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkTable" id="table1"> + <property name="visible">True</property> + <property name="n_rows">4</property> + <property name="n_columns">4</property> + <property name="column_spacing">6</property> + <property name="row_spacing">6</property> + <child> + <widget class="GtkLabel" id="lblHttpHost"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">H_TTP Proxy:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">txtHttpHost</property> + </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="lblHttpsHost"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">_Secure HTTP Proxy:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">txtHttpsHost</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="lblSocksHost"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">S_OCKS Host:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">txtSocksHost</property> + </widget> + <packing> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="lblIgnoreHosts"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">No _Proxy for:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">txtIgnoreHosts</property> + </widget> + <packing> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="txtHttpHost"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="txtHttpsHost"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="txtSocksHost"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="lblHttpPort"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Port:</property> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="lblHttpsPort"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Port:</property> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="lblSocksPort"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Port:</property> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkSpinButton" id="spnHttpPort"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="adjustment">0 0 65535 1 10 0</property> + <property name="climb_rate">1</property> + </widget> + <packing> + <property name="left_attach">3</property> + <property name="right_attach">4</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkSpinButton" id="spnHttpsPort"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="adjustment">0 0 65535 1 10 0</property> + <property name="climb_rate">1</property> + </widget> + <packing> + <property name="left_attach">3</property> + <property name="right_attach">4</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkSpinButton" id="spnSocksPort"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="adjustment">0 0 65535 1 10 0</property> + <property name="climb_rate">1</property> + </widget> + <packing> + <property name="left_attach">3</property> + <property name="right_attach">4</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="txtIgnoreHosts"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">4</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="chkUseAuth"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Use Authe_ntication</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkAlignment" id="alignment26"> + <property name="visible">True</property> + <property name="left_padding">24</property> + <child> + <widget class="GtkTable" id="table11"> + <property name="visible">True</property> + <property name="n_rows">2</property> + <property name="n_columns">2</property> + <property name="column_spacing">6</property> + <property name="row_spacing">3</property> + <child> + <widget class="GtkLabel" id="lblAuthUser"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Us_ername:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">txtAuthUser</property> + </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="lblAuthPwd"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Pass_word:</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">txtAuthPwd</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="txtAuthUser"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="txtAuthPwd"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="visibility">False</property> + <property name="invisible_char">*</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">3</property> + </packing> + </child> + <child> + <widget class="GtkRadioButton" id="rdoAutoConfig"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Automatic proxy configuration URL:</property> + <property name="use_underline">True</property> + <property name="response_id">0</property> + <property name="draw_indicator">True</property> + <property name="group">rdoSysSettings</property> + </widget> + <packing> + <property name="position">4</property> + </packing> + </child> + <child> + <widget class="GtkAlignment" id="alignment36"> + <property name="visible">True</property> + <property name="left_padding">24</property> + <child> + <widget class="GtkEntry" id="txtAutoConfigUrl"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">*</property> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">5</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkLabel" id="lblGeneral2"> + <property name="visible">True</property> + <property name="label" translatable="yes">General</property> + </widget> + <packing> + <property name="type">tab</property> + <property name="tab_fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> </glade-interface> diff --git a/mail/mail-config.h b/mail/mail-config.h index 81f245170e..9a3386dd1d 100644 --- a/mail/mail-config.h +++ b/mail/mail-config.h @@ -23,10 +23,9 @@ #ifndef MAIL_CONFIG_H #define MAIL_CONFIG_H -#include <glib.h> #include <glib-object.h> - -#include "camel/camel-provider.h" /* can't forward-declare enums, bah */ +#include <camel/camel-folder.h> +#include <camel/camel-provider.h> struct _EAccount; struct _EAccountList; @@ -38,21 +37,7 @@ struct _ESignatureList; struct _GConfClient; struct _GtkWindow; -struct _CamelFolder; - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -typedef struct _MailConfigSignature { - int id; - char *name; - char *filename; - char *script; - gboolean html; -} MailConfigSignature; - +G_BEGIN_DECLS typedef enum { MAIL_CONFIG_HTTP_NEVER, @@ -96,61 +81,27 @@ void mail_config_write_on_exit (void); struct _GConfClient *mail_config_get_gconf_client (void); /* General Accessor functions */ -gboolean mail_config_is_configured (void); -gboolean mail_config_is_corrupt (void); - -GSList *mail_config_get_labels (void); - const char **mail_config_get_allowable_mime_types (void); void mail_config_service_set_save_passwd (struct _EAccountService *service, gboolean save_passwd); /* accounts */ -gboolean mail_config_find_account (struct _EAccount *account); -struct _EAccount *mail_config_get_default_account (void); -struct _EAccount *mail_config_get_account_by_name (const char *account_name); -struct _EAccount *mail_config_get_account_by_uid (const char *uid); struct _EAccount *mail_config_get_account_by_source_url (const char *url); struct _EAccount *mail_config_get_account_by_transport_url (const char *url); -struct _EAccountList *mail_config_get_accounts (void); -void mail_config_add_account (struct _EAccount *account); -void mail_config_remove_account (struct _EAccount *account); -void mail_config_set_default_account (struct _EAccount *account); int mail_config_get_address_count (void); int mail_config_get_message_limit (void); gboolean mail_config_get_enable_magic_spacebar (void); -void mail_config_remove_account_proxies (struct _EAccount *account); -void mail_config_prune_proxies (void); -int mail_config_has_proxies (struct _EAccount *account); - -struct _EAccountIdentity *mail_config_get_default_identity (void); struct _EAccountService *mail_config_get_default_transport (void); -void mail_config_save_accounts (void); - -/* signatures */ -struct _ESignature *mail_config_signature_new (const char *filename, gboolean script, gboolean html); -struct _ESignature *mail_config_get_signature_by_uid (const char *uid); -struct _ESignature *mail_config_get_signature_by_name (const char *name); - -struct _ESignatureList *mail_config_get_signatures (void); -void mail_config_add_signature (struct _ESignature *signature); -void mail_config_remove_signature (struct _ESignature *signature); - -void mail_config_save_signatures (void); - -char *mail_config_signature_run_script (const char *script); - - /* uri's got changed by the store, etc */ void mail_config_uri_renamed (GCompareFunc uri_cmp, const char *old, const char *new); void mail_config_uri_deleted (GCompareFunc uri_cmp, const char *uri); /* static utility functions */ -char *mail_config_folder_to_cachename (struct _CamelFolder *folder, const char *prefix); -char *mail_config_folder_to_safe_url (struct _CamelFolder *folder); +char *mail_config_folder_to_cachename (CamelFolder *folder, const char *prefix); +char *mail_config_folder_to_safe_url (CamelFolder *folder); guint mail_config_get_error_timeout (void); guint mail_config_get_error_level (void); @@ -160,14 +111,8 @@ void mail_config_reload_junk_headers (void); gboolean mail_config_get_lookup_book (void); gboolean mail_config_get_lookup_book_local_only (void); -gboolean mail_config_scripts_disabled (void); - GType evolution_mail_config_get_type (void); -gboolean evolution_mail_config_factory_init (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ +G_END_DECLS #endif /* MAIL_CONFIG_H */ diff --git a/mail/mail-crypto.c b/mail/mail-crypto.c deleted file mode 100644 index d7350eaa2a..0000000000 --- a/mail/mail-crypto.c +++ /dev/null @@ -1,53 +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: - * Jeffrey Stedfast <fejj@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <string.h> - -#include <camel/camel-gpg-context.h> -#include <libedataserver/e-account.h> - -#include "mail-crypto.h" -#include "mail-session.h" - -/** - * mail_crypto_get_pgp_cipher_context: - * @account: Account that will be using this context - * - * Constructs a new GnuPG cipher context with the appropriate - * options set based on the account provided. - **/ -CamelCipherContext * -mail_crypto_get_pgp_cipher_context (EAccount *account) -{ - CamelCipherContext *cipher; - - cipher = camel_gpg_context_new (session); - if (account) - camel_gpg_context_set_always_trust ((CamelGpgContext *) cipher, account->pgp_always_trust); - - return cipher; -} diff --git a/mail/mail-dialogs.glade b/mail/mail-dialogs.glade index 689082792a..1ecf410ed5 100644 --- a/mail/mail-dialogs.glade +++ b/mail/mail-dialogs.glade @@ -19,7 +19,6 @@ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> <property name="has_separator">False</property> <child internal-child="vbox"> @@ -175,6 +174,7 @@ <property name="fill">True</property> </packing> </child> + </widget> <packing> <property name="padding">0</property> @@ -201,7 +201,6 @@ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> <property name="has_separator">False</property> <child internal-child="vbox"> @@ -236,62 +235,31 @@ </packing> </child> - <child> - <widget class="GtkVBox" id="vbox161"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">18</property> - <child> - <widget class="GtkVBox" id="frame5"> + <widget class="GtkVBox" id="vbox161"> + <property name="border_width">12</property> <property name="visible">True</property> <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label464"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Digital Signature</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> + <property name="spacing">18</property> <child> - <widget class="GtkHBox" id="hbox170"> + <widget class="GtkVBox" id="frame5"> <property name="visible">True</property> <property name="homogeneous">False</property> - <property name="spacing">0</property> + <property name="spacing">6</property> <child> - <widget class="GtkLabel" id="label465"> + <widget class="GtkLabel" id="label464"> <property name="visible">True</property> - <property name="label" translatable="yes"></property> + <property name="label" translatable="yes"><span weight="bold">Digital Signature</span></property> <property name="use_underline">False</property> - <property name="use_markup">False</property> + <property name="use_markup">True</property> <property name="justify">GTK_JUSTIFY_LEFT</property> <property name="wrap">False</property> <property name="selectable">False</property> - <property name="xalign">0.5</property> + <property name="xalign">0</property> <property name="yalign">0.5</property> - <property name="xpad">12</property> + <property name="xpad">0</property> <property name="ypad">0</property> <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> <property name="width_chars">-1</property> @@ -306,29 +274,67 @@ </child> <child> - <widget class="GtkTable" id="table10"> + <widget class="GtkHBox" id="hbox170"> <property name="visible">True</property> - <property name="n_rows">1</property> - <property name="n_columns">1</property> <property name="homogeneous">False</property> - <property name="row_spacing">2</property> - <property name="column_spacing">6</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="label465"> + <property name="visible">True</property> + <property name="label" translatable="yes"></property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">12</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> <child> - <widget class="GtkVBox" id="signature_vbox"> + <widget class="GtkTable" id="table10"> <property name="visible">True</property> + <property name="n_rows">1</property> + <property name="n_columns">1</property> <property name="homogeneous">False</property> - <property name="spacing">0</property> + <property name="row_spacing">2</property> + <property name="column_spacing">6</property> <child> - <placeholder/> + <widget class="GtkVBox" id="signature_vbox"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + </packing> </child> </widget> <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> </packing> </child> </widget> @@ -341,67 +347,29 @@ </widget> <packing> <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="frame6"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label477"> - <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Encryption</span></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> <property name="expand">False</property> <property name="fill">False</property> </packing> </child> <child> - <widget class="GtkHBox" id="hbox171"> + <widget class="GtkVBox" id="frame6"> <property name="visible">True</property> <property name="homogeneous">False</property> - <property name="spacing">0</property> + <property name="spacing">6</property> <child> - <widget class="GtkLabel" id="label478"> + <widget class="GtkLabel" id="label477"> <property name="visible">True</property> - <property name="label" translatable="yes"></property> + <property name="label" translatable="yes"><span weight="bold">Encryption</span></property> <property name="use_underline">False</property> - <property name="use_markup">False</property> + <property name="use_markup">True</property> <property name="justify">GTK_JUSTIFY_LEFT</property> <property name="wrap">False</property> <property name="selectable">False</property> - <property name="xalign">0.5</property> + <property name="xalign">0</property> <property name="yalign">0.5</property> - <property name="xpad">12</property> + <property name="xpad">0</property> <property name="ypad">0</property> <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> <property name="width_chars">-1</property> @@ -416,29 +384,67 @@ </child> <child> - <widget class="GtkTable" id="table11"> + <widget class="GtkHBox" id="hbox171"> <property name="visible">True</property> - <property name="n_rows">1</property> - <property name="n_columns">1</property> <property name="homogeneous">False</property> - <property name="row_spacing">2</property> - <property name="column_spacing">6</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="label478"> + <property name="visible">True</property> + <property name="label" translatable="yes"></property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">12</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> <child> - <widget class="GtkVBox" id="encryption_vbox"> + <widget class="GtkTable" id="table11"> <property name="visible">True</property> + <property name="n_rows">1</property> + <property name="n_columns">1</property> <property name="homogeneous">False</property> - <property name="spacing">0</property> + <property name="row_spacing">2</property> + <property name="column_spacing">6</property> <child> - <placeholder/> + <widget class="GtkVBox" id="encryption_vbox"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + </packing> </child> </widget> <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> </packing> </child> </widget> @@ -451,24 +457,13 @@ </widget> <packing> <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> + <property name="expand">False</property> + <property name="fill">False</property> </packing> </child> </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> + </widget> </child> </widget> @@ -488,7 +483,6 @@ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> <property name="has_separator">False</property> <child internal-child="vbox"> @@ -562,6 +556,7 @@ <property name="yalign">0.5</property> <property name="xpad">0</property> <property name="ypad">0</property> + <property name="mnemonic_widget">store_menu</property> <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> <property name="width_chars">-1</property> <property name="single_line_mode">False</property> @@ -575,10 +570,24 @@ </child> <child> - <widget class="GtkComboBox" id="store_combobox"> + <widget class="GtkOptionMenu" id="store_menu"> <property name="visible">True</property> - <property name="add_tearoffs">False</property> - <property name="focus_on_click">True</property> + <property name="can_focus">True</property> + <property name="history">0</property> + + <child> + <widget class="GtkMenu" id="menu1"> + + <child> + <widget class="GtkMenuItem" id="no_imap_server_selected1"> + <property name="visible">True</property> + <property name="label" translatable="yes">None Selected</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_no_imap_server_selected1_activate" last_modification_time="Mon, 14 Apr 2003 17:08:20 GMT"/> + </widget> + </child> + </widget> + </child> </widget> <packing> <property name="padding">0</property> @@ -652,7 +661,6 @@ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> <property name="has_separator">True</property> <child internal-child="vbox"> @@ -874,7 +882,6 @@ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> <property name="has_separator">False</property> <child internal-child="vbox"> @@ -936,14 +943,13 @@ <property name="spacing">6</property> <child> - <widget class="GtkImage" id="pixmap"> + <widget class="Custom" id="pixmap"> <property name="visible">True</property> - <property name="icon_size">6</property> - <property name="icon_name">stock_mail-flag-for-followup</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> + <property name="creation_function">e_create_image_widget</property> + <property name="string1">stock_mail-flag-for-followup</property> + <property name="int1">0</property> + <property name="int2">0</property> + <property name="last_modification_time">Wed, 08 Dec 2004 02:35:27 GMT</property> </widget> <packing> <property name="padding">0</property> @@ -1036,6 +1042,7 @@ Please select a follow up action from the "Flag" menu.</property> <property name="yalign">0.5</property> <property name="xpad">0</property> <property name="ypad">0</property> + <property name="mnemonic_widget">combo-entry</property> <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> <property name="width_chars">-1</property> <property name="single_line_mode">False</property> @@ -1099,6 +1106,71 @@ Please select a follow up action from the "Flag" menu.</property> </child> <child> + <widget class="GtkCombo" id="combo"> + <property name="visible">True</property> + <property name="value_in_list">False</property> + <property name="allow_empty">True</property> + <property name="case_sensitive">False</property> + <property name="enable_arrow_keys">True</property> + <property name="enable_arrows_always">False</property> + + <child internal-child="entry"> + <widget class="GtkEntry" id="combo-entry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">*</property> + <property name="activates_default">False</property> + </widget> + </child> + + <child internal-child="list"> + <widget class="GtkList" id="convertwidget3"> + <property name="visible">True</property> + <property name="selection_mode">GTK_SELECTION_BROWSE</property> + + <child> + <widget class="GtkListItem" id="convertwidget4"> + <property name="visible">True</property> + + <child> + <widget class="GtkLabel" id="convertwidget5"> + <property name="visible">True</property> + <property name="label" translatable="yes"></property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="y_options"></property> + </packing> + </child> + + <child> <widget class="Custom" id="target_date"> <property name="visible">True</property> <property name="creation_function">target_date_new</property> @@ -1136,25 +1208,6 @@ Please select a follow up action from the "Flag" menu.</property> <property name="y_options"></property> </packing> </child> - - <child> - <widget class="GtkComboBoxEntry" id="combo"> - <property name="visible">True</property> - <property name="items" translatable="yes">a -b</property> - <property name="add_tearoffs">False</property> - <property name="has_frame">True</property> - <property name="focus_on_click">True</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> </widget> <packing> <property name="padding">0</property> @@ -1188,7 +1241,6 @@ b</property> <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> <property name="has_separator">False</property> <child internal-child="vbox"> @@ -1389,6 +1441,7 @@ b</property> <property name="inconsistent">False</property> <property name="draw_indicator">True</property> <property name="group">local_rb</property> + </widget> <packing> <property name="padding">0</property> diff --git a/mail/mail-folder-cache.c b/mail/mail-folder-cache.c index 165f5941c2..46a62e4fc2 100644 --- a/mail/mail-folder-cache.c +++ b/mail/mail-folder-cache.c @@ -39,7 +39,6 @@ #include <libgnome/gnome-sound.h> #include <glib/gi18n.h> -#include <bonobo/bonobo-exception.h> #include <camel/camel-store.h> #include <camel/camel-folder.h> #include <camel/camel-vtrash-folder.h> @@ -50,13 +49,14 @@ #include <libedataserver/e-data-server-util.h> #include <libedataserver/e-msgport.h> #include "e-util/e-util.h" +#include "shell/e-shell.h" #include "mail-mt.h" #include "mail-folder-cache.h" #include "mail-ops.h" #include "mail-session.h" -#include "mail-component.h" #include "mail-tools.h" +#include "e-mail-shell-module.h" /* For notifications of changes */ #include "mail-vfolder.h" @@ -110,6 +110,8 @@ struct _folder_update { }; struct _store_info { + EShellModule *shell_module; + GHashTable *folders; /* by full_name */ GHashTable *folders_uri; /* by uri */ @@ -150,14 +152,14 @@ free_update(struct _folder_update *up) } static void -real_flush_updates(void *o, void *event_data, void *data) +real_flush_updates (EShellModule *shell_module) { - struct _MailComponent *component; + EShell *shell; struct _EMFolderTreeModel *model; struct _folder_update *up; - component = mail_component_peek (); - model = mail_component_peek_tree_model (component); + shell = e_shell_module_get_shell (shell_module); + model = e_mail_shell_module_get_folder_tree_model (shell_module); LOCK(info_lock); while ((up = (struct _folder_update *)e_dlist_remhead(&updates))) { @@ -196,7 +198,8 @@ real_flush_updates(void *o, void *event_data, void *data) t->name = em_folder_tree_model_get_folder_name (model, up->store, up->full_name); if (t->new > 0) - mail_indicate_new_mail (TRUE); + e_shell_event ( + shell, "mail-icon", "mail-unread"); /** @Event: folder.changed * @Title: Folder changed @@ -208,6 +211,19 @@ real_flush_updates(void *o, void *event_data, void *data) e_event_emit((EEvent *)e, "folder.changed", (EEventTarget *)t); } + if (CAMEL_IS_VEE_STORE (up->store) && !up->remove) { + /* Normally the vfolder store takes care of the folder_opened event itself, + but we add folder to the noting system later, thus we do not know about + search folders to update them in a tree, thus ensure their changes will + be tracked correctly. */ + CamelFolder *folder = camel_store_get_folder (up->store, up->full_name, 0, NULL); + + if (folder) { + mail_note_folder (folder); + camel_object_unref (folder); + } + } + free_update(up); LOCK(info_lock); @@ -217,10 +233,13 @@ real_flush_updates(void *o, void *event_data, void *data) } static void -flush_updates(void) +flush_updates (EShellModule *shell_module) { if (update_id == -1 && !e_dlist_empty(&updates)) - update_id = mail_async_event_emit(mail_async_event, MAIL_ASYNC_GUI, (MailAsyncFunc)real_flush_updates, NULL, NULL, NULL); + update_id = mail_async_event_emit ( + mail_async_event, MAIL_ASYNC_GUI, + (MailAsyncFunc) real_flush_updates, + shell_module, NULL, NULL); } static void @@ -233,7 +252,7 @@ unset_folder_info(struct _folder_info *mfi, int delete, int unsub) if (mfi->folder) { CamelFolder *folder = mfi->folder; - camel_object_unhook_event(folder, "folder_changed", folder_changed, NULL); + camel_object_unhook_event(folder, "folder_changed", folder_changed, mfi->store_info->shell_module); camel_object_unhook_event(folder, "renamed", folder_renamed, NULL); camel_object_unhook_event(folder, "finalize", folder_finalised, NULL); } @@ -250,7 +269,7 @@ unset_folder_info(struct _folder_info *mfi, int delete, int unsub) up->uri = g_strdup(mfi->uri); e_dlist_addtail(&updates, (EDListNode *)up); - flush_updates(); + flush_updates(mfi->store_info->shell_module); } } @@ -288,21 +307,32 @@ static void update_1folder(struct _folder_info *mfi, int new, CamelFolderInfo *info) { struct _folder_update *up; + EShellModule *shell_module; CamelFolder *folder; + CamelFolder *local_drafts; + CamelFolder *local_outbox; + CamelFolder *local_sent; int unread = -1; int deleted; + shell_module = mfi->store_info->shell_module; + local_drafts = e_mail_shell_module_get_folder ( + shell_module, E_MAIL_FOLDER_DRAFTS); + local_outbox = e_mail_shell_module_get_folder ( + shell_module, E_MAIL_FOLDER_OUTBOX); + local_sent = e_mail_shell_module_get_folder ( + shell_module, E_MAIL_FOLDER_SENT); + folder = mfi->folder; if (folder) { d(printf("update 1 folder '%s'\n", folder->full_name)); if ((count_trash && (CAMEL_IS_VTRASH_FOLDER (folder))) - || folder == mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX) - || folder == mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_DRAFTS) - || (count_sent && folder == mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_SENT))) { + || folder == local_drafts + || folder == local_outbox + || (count_sent && folder == local_sent)) { d(printf(" total count\n")); unread = camel_folder_get_message_count (folder); - if (folder == mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX) - || folder == mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_DRAFTS)) { + if (folder == local_drafts || folder == local_outbox) { guint32 junked = 0; if ((deleted = camel_folder_get_deleted_message_count (folder)) > 0) @@ -336,7 +366,7 @@ update_1folder(struct _folder_info *mfi, int new, CamelFolderInfo *info) up->uri = g_strdup(mfi->uri); camel_object_ref(up->store); e_dlist_addtail(&updates, (EDListNode *)up); - flush_updates(); + flush_updates(shell_module); } static void @@ -370,7 +400,7 @@ setup_folder(CamelFolderInfo *fi, struct _store_info *si) up->add = TRUE; e_dlist_addtail(&updates, (EDListNode *)up); - flush_updates(); + flush_updates(si->shell_module); } } @@ -393,8 +423,12 @@ static void folder_changed (CamelObject *o, gpointer event_data, gpointer user_data) { static time_t last_newmail = 0; + EShellModule *shell_module = user_data; CamelFolderChangeInfo *changes = event_data; CamelFolder *folder = (CamelFolder *)o; + CamelFolder *local_drafts; + CamelFolder *local_outbox; + CamelFolder *local_sent; CamelStore *store = folder->parent_store; CamelMessageInfo *info; struct _store_info *si; @@ -405,10 +439,17 @@ folder_changed (CamelObject *o, gpointer event_data, gpointer user_data) d(printf("folder '%s' changed\n", folder->full_name)); + local_drafts = e_mail_shell_module_get_folder ( + shell_module, E_MAIL_FOLDER_DRAFTS); + local_outbox = e_mail_shell_module_get_folder ( + shell_module, E_MAIL_FOLDER_OUTBOX); + local_sent = e_mail_shell_module_get_folder ( + shell_module, E_MAIL_FOLDER_SENT); + if (!CAMEL_IS_VEE_FOLDER(folder) - && folder != mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX) - && folder != mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_DRAFTS) - && folder != mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_SENT) + && folder != local_drafts + && folder != local_outbox + && folder != local_sent && changes && (changes->uid_added->len > 0)) { /* for each added message, check to see that it is brand new, not junk and not already deleted */ @@ -500,7 +541,7 @@ void mail_note_folder(CamelFolder *folder) UNLOCK(info_lock); - camel_object_hook_event(folder, "folder_changed", folder_changed, NULL); + camel_object_hook_event(folder, "folder_changed", folder_changed, si->shell_module); camel_object_hook_event(folder, "renamed", folder_renamed, NULL); camel_object_hook_event(folder, "finalize", folder_finalised, NULL); } @@ -596,6 +637,7 @@ rename_folders(struct _store_info *si, const char *oldbase, const char *newbase, char *old, *olduri, *oldfile, *newuri, *newfile; struct _folder_info *mfi; struct _folder_update *up; + const gchar *config_dir; up = g_malloc0(sizeof(*up)); @@ -642,7 +684,7 @@ rename_folders(struct _store_info *si, const char *oldbase, const char *newbase, up->add = TRUE; e_dlist_addtail(&updates, (EDListNode *)up); - flush_updates(); + flush_updates(si->shell_module); #if 0 if (fi->sibling) rename_folders(si, oldbase, newbase, fi->sibling, folders); @@ -651,17 +693,18 @@ rename_folders(struct _store_info *si, const char *oldbase, const char *newbase, #endif /* rename the meta-data we maintain ourselves */ + config_dir = e_shell_module_get_config_dir (si->shell_module); olduri = folder_to_url(si->store, old); e_filename_make_safe(olduri); newuri = folder_to_url(si->store, fi->full_name); e_filename_make_safe(newuri); - oldfile = g_strdup_printf("%s/config/custom_view-%s.xml", mail_component_peek_base_directory(NULL), olduri); - newfile = g_strdup_printf("%s/config/custom_view-%s.xml", mail_component_peek_base_directory(NULL), newuri); + oldfile = g_strdup_printf("%s/custom_view-%s.xml", config_dir, olduri); + newfile = g_strdup_printf("%s/custom_view-%s.xml", config_dir, newuri); g_rename(oldfile, newfile); g_free(oldfile); g_free(newfile); - oldfile = g_strdup_printf("%s/config/current_view-%s.xml", mail_component_peek_base_directory(NULL), olduri); - newfile = g_strdup_printf("%s/config/current_view-%s.xml", mail_component_peek_base_directory(NULL), newuri); + oldfile = g_strdup_printf("%s/current_view-%s.xml", config_dir, olduri); + newfile = g_strdup_printf("%s/current_view-%s.xml", config_dir, newuri); g_rename(oldfile, newfile); g_free(oldfile); g_free(newfile); @@ -765,6 +808,8 @@ mail_note_store_remove(CamelStore *store) if (si) { g_hash_table_remove(stores, store); + g_object_unref(si->shell_module); + camel_object_unhook_event(store, "folder_opened", store_folder_opened, NULL); camel_object_unhook_event(store, "folder_created", store_folder_created, NULL); camel_object_unhook_event(store, "folder_deleted", store_folder_deleted, NULL); @@ -917,7 +962,7 @@ store_online_cb (CamelStore *store, void *data) } void -mail_note_store(CamelStore *store, CamelOperation *op, +mail_note_store(EShellModule *shell_module, CamelStore *store, CamelOperation *op, gboolean (*done)(CamelStore *store, CamelFolderInfo *info, void *data), void *data) { struct _store_info *si; @@ -926,6 +971,7 @@ mail_note_store(CamelStore *store, CamelOperation *op, guint timeout; int hook = 0; + g_return_if_fail (E_IS_SHELL_MODULE (shell_module)); g_return_if_fail (CAMEL_IS_STORE(store)); g_return_if_fail (mail_in_main_thread()); @@ -945,6 +991,7 @@ mail_note_store(CamelStore *store, CamelOperation *op, d(printf("Noting a new store: %p: %s\n", store, camel_url_to_string(((CamelService *)store)->url, 0))); si = g_malloc0(sizeof(*si)); + si->shell_module = g_object_ref (shell_module); si->folders = g_hash_table_new(g_str_hash, g_str_equal); si->folders_uri = g_hash_table_new(CAMEL_STORE_CLASS(CAMEL_OBJECT_GET_CLASS(store))->hash_folder_name, CAMEL_STORE_CLASS(CAMEL_OBJECT_GET_CLASS(store))->compare_folder_name); @@ -1045,26 +1092,26 @@ int mail_note_get_folder_from_uri(const char *uri, CamelFolder **folderp) return fi.fi != NULL; } -gboolean +gboolean mail_folder_cache_get_folder_info_flags (CamelFolder *folder, int *flags) { char *uri; uri = mail_tools_folder_to_url (folder); - + struct _find_info fi = { uri, NULL, NULL }; if (stores == NULL) return FALSE; - fi.url = camel_url_new(uri, NULL); + fi.url = camel_url_new (uri, NULL); LOCK(info_lock); g_hash_table_foreach(stores, (GHFunc)storeinfo_find_folder_info, &fi); if (flags) { if (fi.fi) { *flags = fi.fi->flags; - } + } } UNLOCK(info_lock); diff --git a/mail/mail-folder-cache.h b/mail/mail-folder-cache.h index c0f7e866cf..d685e5a5ad 100644 --- a/mail/mail-folder-cache.h +++ b/mail/mail-folder-cache.h @@ -27,13 +27,14 @@ #define _MAIL_FOLDER_CACHE_H #include <camel/camel-store.h> +#include <shell/e-shell-module.h> /* Add a store whose folders should appear in the shell The folders are scanned from the store, and/or added at runtime via the folder_created event. The 'done' function returns if we can free folder info. */ void -mail_note_store (CamelStore *store, CamelOperation *op, +mail_note_store (EShellModule *shell_module, CamelStore *store, CamelOperation *op, gboolean (*done) (CamelStore *store, CamelFolderInfo *info, void *data), void *data); diff --git a/mail/mail-mt.c b/mail/mail-mt.c index 99d691b1ca..a70093e855 100644 --- a/mail/mail-mt.c +++ b/mail/mail-mt.c @@ -37,14 +37,14 @@ #include "misc/e-gui-utils.h" #include "e-util/e-error.h" #include "e-util/e-icon-factory.h" - -#include "e-activity-handler.h" +#include "widgets/misc/e-alert-activity.h" #include "mail-config.h" -#include "mail-component.h" #include "mail-session.h" #include "mail-mt.h" +#include "e-mail-shell-module.h" + /*#define MALLOC_CHECK*/ #define LOG_OPS #define LOG_LOCKS @@ -65,7 +65,7 @@ static void mail_operation_status(struct _CamelOperation *op, const char *what, struct _MailMsgPrivate { int activity_state; /* sigh sigh sigh, we need to keep track of the state external to the pointer itself for locking/race conditions */ - int activity_id; + EActivity *activity; GtkWidget *error; gboolean cancelable; }; @@ -140,19 +140,17 @@ mail_msg_new (MailMsgInfo *info) } static void -end_event_callback (CamelObject *o, void *event_data, void *error) +end_event_callback (CamelObject *o, EActivity *activity, void *error) { - MailComponent *component; - EActivityHandler *activity_handler; - guint activity_id = GPOINTER_TO_INT (event_data); - - component = mail_component_peek (); - activity_handler = mail_component_peek_activity_handler (component); - if (!error) { - e_activity_handler_operation_finished (activity_handler, activity_id); + if (error == NULL) { + e_activity_complete (activity); + g_object_unref (activity); } else { - d(printf("Yahooooo, we got it nonintrusively\n")); - e_activity_handler_operation_set_error (activity_handler, activity_id, error); + if (activity != NULL) + g_object_unref (activity); + activity = e_alert_activity_new_warning (error); + e_shell_module_add_activity (mail_shell_module, activity); + g_object_unref (activity); } } @@ -184,6 +182,9 @@ checkmem(void *p) static void mail_msg_free (MailMsg *mail_msg) { + if (mail_msg->priv->activity != NULL) + g_object_unref (mail_msg->priv->activity); + if (mail_msg->cancel != NULL) { camel_operation_mute (mail_msg->cancel); camel_operation_unref (mail_msg->cancel); @@ -210,7 +211,7 @@ void mail_msg_unref (gpointer msg) { MailMsg *mail_msg = msg; - gint activity_id; + EActivity *activity = NULL; GtkWidget *error = NULL; g_return_if_fail (mail_msg != NULL); @@ -254,24 +255,21 @@ mail_msg_unref (gpointer msg) MAIL_MT_UNLOCK(mail_msg_lock); return; } else { - activity_id = mail_msg->priv->activity_id; + activity = mail_msg->priv->activity; + if (activity != NULL) + g_object_ref (activity); error = mail_msg->priv->error; - if (error && !activity_id) { - e_activity_handler_make_error (mail_component_peek_activity_handler (mail_component_peek ()), "mail", E_LOG_ERROR, error); - printf("Making error\n"); - } - } MAIL_MT_UNLOCK(mail_msg_lock); mail_msg_free (mail_msg); - if (activity_id != 0) + if (activity != NULL) mail_async_event_emit ( mail_async_event, MAIL_ASYNC_GUI, (MailAsyncFunc) end_event_callback, - NULL, GINT_TO_POINTER (activity_id), error); + NULL, activity, error); } /* hash table of ops->dialogue of active errors */ @@ -939,7 +937,6 @@ struct _op_status_msg { static void op_status_exec (struct _op_status_msg *m) { - EActivityHandler *activity_handler = mail_component_peek_activity_handler (mail_component_peek ()); MailMsg *msg; MailMsgPrivate *data; char *out, *p, *o, c; @@ -970,7 +967,7 @@ op_status_exec (struct _op_status_msg *m) pc = m->pc; - if (data->activity_id == 0) { + if (data->activity == NULL) { char *what; /* its being created/removed? well leave it be */ @@ -990,28 +987,39 @@ op_status_exec (struct _op_status_msg *m) what = g_strdup(""); } - data->activity_id = e_activity_handler_cancelable_operation_started (activity_handler, "evolution-mail", what, TRUE, (void (*) (gpointer)) camel_operation_cancel, msg->cancel); + data->activity = e_activity_new (what); + e_activity_set_allow_cancel (data->activity, TRUE); + e_activity_set_percent (data->activity, 0.0); + e_shell_module_add_activity (mail_shell_module, data->activity); + + g_signal_connect_swapped ( + data->activity, "cancelled", + G_CALLBACK (camel_operation_cancel), + msg->cancel); g_free (what); MAIL_MT_LOCK (mail_msg_lock); if (data->activity_state == 3) { - int activity_id = data->activity_id; + EActivity *activity; + + activity = g_object_ref (data->activity); MAIL_MT_UNLOCK (mail_msg_lock); mail_msg_free (msg); - if (activity_id != 0) - mail_async_event_emit (mail_async_event, MAIL_ASYNC_GUI, (MailAsyncFunc) end_event_callback, - NULL, GINT_TO_POINTER (activity_id), NULL); + if (activity != 0) + mail_async_event_emit ( + mail_async_event, MAIL_ASYNC_GUI, (MailAsyncFunc) end_event_callback, + NULL, activity, NULL); } else { data->activity_state = 2; MAIL_MT_UNLOCK (mail_msg_lock); } return; } - } else if (data->activity_id != 0) { + } else if (data->activity != NULL) { MAIL_MT_UNLOCK (mail_msg_lock); - e_activity_handler_operation_progressing (activity_handler, data->activity_id, out, (double)(pc/100.0)); + e_activity_set_percent (data->activity, pc / 100.0); } else { MAIL_MT_UNLOCK (mail_msg_lock); } @@ -1064,6 +1072,5 @@ set_stop (int sensitive) if (last == sensitive) return; - /*bonobo_ui_component_set_prop (uic, "/commands/MailStop", "sensitive", sensitive ? "1" : "0", NULL);*/ last = sensitive; } diff --git a/mail/mail-ops.c b/mail/mail-ops.c index 5d9386b6c0..b8e442102f 100644 --- a/mail/mail-ops.c +++ b/mail/mail-ops.c @@ -58,11 +58,11 @@ #include <libedataserver/e-data-server-util.h> #include "e-util/e-util.h" +#include "e-util/e-account-utils.h" #include "e-util/e-util-private.h" #include "em-filter-rule.h" #include "em-utils.h" -#include "mail-component.h" #include "mail-config.h" #include "mail-mt.h" #include "mail-ops.h" @@ -70,6 +70,8 @@ #include "mail-tools.h" #include "mail-vfolder.h" +#include "e-mail-shell-module.h" + #define w(x) #define d(x) @@ -244,7 +246,7 @@ uid_cachename_hack (CamelStore *store) { CamelURL *url = CAMEL_SERVICE (store)->url; char *encoded_url, *filename; - const char *evolution_dir; + const gchar *data_dir; encoded_url = g_strdup_printf ("%s%s%s@%s", url->user, url->authmech ? ";auth=" : "", @@ -252,8 +254,8 @@ uid_cachename_hack (CamelStore *store) url->host); e_filename_make_safe (encoded_url); - evolution_dir = mail_component_peek_base_directory (mail_component_peek ()); - filename = g_build_filename (evolution_dir, "pop", encoded_url, "uid-cache", NULL); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + filename = g_build_filename (data_dir, "pop", encoded_url, "uid-cache", NULL); g_free (encoded_url); return filename; @@ -274,9 +276,11 @@ fetch_mail_exec (struct _fetch_mail_msg *m) if (m->cancel) camel_operation_register (m->cancel); - if ((fm->destination = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_LOCAL_INBOX)) == NULL) + fm->destination = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_LOCAL_INBOX); + if (fm->destination == NULL) goto fail; - camel_object_ref(fm->destination); + camel_object_ref (fm->destination); /* FIXME: this should support keep_on_server too, which would then perform a spool access thingy, right? problem is matching raw messages to uid's etc. */ @@ -472,9 +476,9 @@ mail_send_message(CamelFolder *queue, const char *uid, const char *destination, char *name; name = g_strstrip(g_strdup(tmp)); - if ((account = mail_config_get_account_by_uid(name)) + if ((account = e_get_account_by_uid (name)) /* 'old' x-evolution-account stored the name, how silly */ - || (account = mail_config_get_account_by_name(name))) { + || (account = e_get_account_by_name (name))) { if (account->transport && account->transport->url) transport_url = g_strdup (account->transport->url); @@ -578,7 +582,8 @@ mail_send_message(CamelFolder *queue, const char *uid, const char *destination, } if (!folder) { - folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_SENT); + folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_SENT); camel_object_ref(folder); } @@ -591,7 +596,8 @@ mail_send_message(CamelFolder *queue, const char *uid, const char *destination, if (camel_exception_get_id (ex) == CAMEL_EXCEPTION_USER_CANCEL) goto exit; - sent_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_SENT); + sent_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_SENT); if (folder != sent_folder) { const char *name; @@ -686,13 +692,16 @@ report_status (struct _send_queue_msg *m, enum camel_filter_status_t status, int static void send_queue_exec (struct _send_queue_msg *m) { - CamelFolder *sent_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_SENT); + CamelFolder *sent_folder; GPtrArray *uids, *send_uids = NULL; CamelException ex; int i, j; d(printf("sending queue\n")); + sent_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_SENT); + if (!(uids = camel_folder_get_uids (m->queue))) return; @@ -1269,7 +1278,8 @@ struct _get_quota_msg { CamelFolder *folder; CamelFolderQuotaInfo *quota; - void (*done) (CamelFolder *folder, CamelFolderQuotaInfo *quota, void *data); + void (*done) (CamelFolder *folder, const gchar *folder_uri, CamelFolderQuotaInfo *quota, void *data); + gchar *folder_uri; void *data; }; @@ -1289,7 +1299,7 @@ static void get_quota_done (struct _get_quota_msg *m) { if (m->done) - m->done (m->folder, m->quota, m->data); + m->done (m->folder, m->folder_uri, m->quota, m->data); } static void @@ -1299,6 +1309,7 @@ get_quota_free (struct _get_quota_msg *m) camel_object_unref (m->folder); if (m->quota) camel_folder_quota_info_free (m->quota); + g_free (m->folder_uri); } static MailMsgInfo get_quota_info = { @@ -1311,7 +1322,8 @@ static MailMsgInfo get_quota_info = { int mail_get_folder_quota (CamelFolder *folder, - void (*done)(CamelFolder *folder, CamelFolderQuotaInfo *quota, void *data), + const gchar *folder_uri, + void (*done)(CamelFolder *folder, const gchar *uri, CamelFolderQuotaInfo *quota, void *data), void *data, MailMsgDispatchFunc dispatch) { struct _get_quota_msg *m; @@ -1321,6 +1333,7 @@ mail_get_folder_quota (CamelFolder *folder, m = mail_msg_new (&get_quota_info); m->folder = folder; + m->folder_uri = g_strdup (folder_uri); m->data = data; m->done = done; @@ -1749,15 +1762,15 @@ empty_trash_desc (struct _empty_trash_msg *m) static void empty_trash_exec (struct _empty_trash_msg *m) { - const char *evolution_dir; + const gchar *data_dir; CamelFolder *trash; char *uri; if (m->account) { trash = mail_tool_get_trash (m->account->source->url, FALSE, &m->base.ex); } else { - evolution_dir = mail_component_peek_base_directory (mail_component_peek ()); - uri = g_strdup_printf ("mbox:%s/local", evolution_dir); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + uri = g_strdup_printf ("mbox:%s/local", data_dir); trash = mail_tool_get_trash (uri, TRUE, &m->base.ex); g_free (uri); } diff --git a/mail/mail-ops.h b/mail/mail-ops.h index e615a9121d..68ae9037df 100644 --- a/mail/mail-ops.h +++ b/mail/mail-ops.h @@ -74,7 +74,8 @@ int mail_get_folder (const char *uri, guint32 flags, /* get quota information for a folder */ int mail_get_folder_quota (CamelFolder *folder, - void (*done)(CamelFolder *folder, CamelFolderQuotaInfo *quota, void *data), + const gchar *folder_uri, + void (*done)(CamelFolder *folder, const gchar *folder_uri, CamelFolderQuotaInfo *quota, void *data), void *data, MailMsgDispatchFunc dispatch); /* and for a store */ diff --git a/mail/mail-send-recv.c b/mail/mail-send-recv.c index d957a7d216..9fe40a5fbc 100644 --- a/mail/mail-send-recv.c +++ b/mail/mail-send-recv.c @@ -38,7 +38,6 @@ #include "camel/camel-store.h" #include "mail-mt.h" -#include "mail-component.h" #include "mail-config.h" #include "mail-session.h" #include "mail-tools.h" @@ -46,7 +45,12 @@ #include "mail-send-recv.h" #include "mail-folder-cache.h" #include "em-event.h" -#include <e-util/gconf-bridge.h> + +#include "shell/e-shell.h" +#include "e-util/e-account-utils.h" +#include "e-util/gconf-bridge.h" + +#include "e-mail-shell-module.h" #define d(x) @@ -160,7 +164,8 @@ setup_send_data(void) g_str_hash, g_str_equal, (GDestroyNotify) NULL, (GDestroyNotify) free_folder_info); - data->inbox = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_LOCAL_INBOX); + data->inbox = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_LOCAL_INBOX); camel_object_ref(data->inbox); data->active = g_hash_table_new_full ( g_str_hash, g_str_equal, @@ -360,7 +365,10 @@ get_receive_type(const char *url) } static struct _send_data * -build_dialog (EAccountList *accounts, CamelFolder *outbox, const char *destination) +build_dialog (GtkWindow *parent, + EAccountList *accounts, + CamelFolder *outbox, + const gchar *destination) { GtkDialog *gd; GtkWidget *table; @@ -380,7 +388,10 @@ build_dialog (EAccountList *accounts, CamelFolder *outbox, const char *destinati EIterator *iter; EMEventTargetSendReceive *target; - gd = (GtkDialog *)(send_recv_dialog = gtk_dialog_new_with_buttons(_("Send & Receive Mail"), NULL, GTK_DIALOG_NO_SEPARATOR, NULL)); + send_recv_dialog = gtk_dialog_new_with_buttons ( + _("Send & Receive Mail"), parent, + GTK_DIALOG_NO_SEPARATOR, NULL); + gd = GTK_DIALOG (send_recv_dialog); gtk_window_set_modal ((GtkWindow *) gd, FALSE); gconf_bridge_bind_window_size ( @@ -679,8 +690,13 @@ receive_done (char *uri, void *data) /* if we've been called to run again - run again */ if (info->type == SEND_SEND && info->state == SEND_ACTIVE && info->again) { + CamelFolder *local_outbox_folder; + + local_outbox_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_OUTBOX); + info->again = 0; - mail_send_queue (mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX), + mail_send_queue (local_outbox_folder, info->uri, FILTER_SOURCE_OUTGOING, info->cancel, @@ -892,14 +908,14 @@ receive_update_got_store (char *uri, CamelStore *store, void *data) struct _send_info *info = data; if (store) { - mail_note_store(store, info->cancel, receive_update_got_folderinfo, info); + mail_note_store(mail_shell_module, store, info->cancel, receive_update_got_folderinfo, info); } else { receive_done("", info); } } GtkWidget * -mail_send_receive (void) +mail_send_receive (GtkWindow *parent) { CamelFolder *outbox_folder; struct _send_data *data; @@ -918,14 +934,16 @@ mail_send_receive (void) if (!camel_session_is_online (session)) return send_recv_dialog; - account = mail_config_get_default_account (); + account = e_get_default_account (); if (!account || !account->transport->url) return send_recv_dialog; - accounts = mail_config_get_accounts (); + accounts = e_get_account_list (); - outbox_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX); - data = build_dialog (accounts, outbox_folder, account->transport->url); + outbox_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_OUTBOX); + data = build_dialog ( + parent, accounts, outbox_folder, account->transport->url); scan = data->infos; while (scan) { struct _send_info *info = scan->data; @@ -1052,16 +1070,16 @@ auto_account_changed(EAccountList *eal, EAccount *ea, void *dummy) } static void -auto_online(CamelObject *o, void *ed, void *d) +auto_online (EShell *shell) { EIterator *iter; EAccountList *accounts; struct _auto_data *info; - if (!GPOINTER_TO_INT(ed)) + if (!e_shell_get_online (shell)) return; - accounts = mail_config_get_accounts (); + accounts = e_get_account_list (); for (iter = e_list_get_iterator((EList *)accounts);e_iterator_is_valid(iter);e_iterator_next(iter)) { info = g_object_get_data((GObject *)e_iterator_get(iter), "mail-autoreceive"); if (info && info->timeout_id) @@ -1072,15 +1090,20 @@ auto_online(CamelObject *o, void *ed, void *d) /* call to setup initial, and after changes are made to the config */ /* FIXME: Need a cleanup funciton for when object is deactivated */ void -mail_autoreceive_init (CamelSession *session) +mail_autoreceive_init (EShellModule *shell_module, + CamelSession *session) { EAccountList *accounts; EIterator *iter; + EShell *shell; + + g_return_if_fail (E_IS_SHELL_MODULE (shell_module)); + g_return_if_fail (CAMEL_IS_SESSION (session)); if (auto_active) return; - accounts = mail_config_get_accounts (); + accounts = e_get_account_list (); auto_active = g_hash_table_new(g_str_hash, g_str_equal); g_signal_connect(accounts, "account-added", G_CALLBACK(auto_account_added), NULL); @@ -1090,7 +1113,13 @@ mail_autoreceive_init (CamelSession *session) for (iter = e_list_get_iterator((EList *)accounts);e_iterator_is_valid(iter);e_iterator_next(iter)) auto_account_added(accounts, (EAccount *)e_iterator_get(iter), NULL); - camel_object_hook_event (session, "online", auto_online, NULL); + shell = e_shell_module_get_shell (shell_module); + + auto_online (shell); + + g_signal_connect ( + shell, "notify::online", + G_CALLBACK (auto_online), NULL); } /* we setup the download info's in a hashtable, if we later need to build the gui, we insert @@ -1145,7 +1174,8 @@ mail_receive_uri (const gchar *uri, gboolean keep_on_server) break; case SEND_SEND: /* todo, store the folder in info? */ - outbox_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX); + outbox_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_OUTBOX); mail_send_queue (outbox_folder, info->uri, FILTER_SOURCE_OUTGOING, info->cancel, @@ -1207,7 +1237,8 @@ mail_send (void) g_hash_table_insert (data->active, SEND_URI_KEY, info); /* todo, store the folder in info? */ - outbox_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX); + outbox_folder = e_mail_shell_module_get_folder ( + mail_shell_module, E_MAIL_FOLDER_OUTBOX); mail_send_queue (outbox_folder, info->uri, FILTER_SOURCE_OUTGOING, info->cancel, diff --git a/mail/mail-send-recv.h b/mail/mail-send-recv.h index 4fc4e991ec..d602e63bd7 100644 --- a/mail/mail-send-recv.h +++ b/mail/mail-send-recv.h @@ -25,20 +25,22 @@ #include <gtk/gtk.h> #include <camel/camel-session.h> +#include <shell/e-shell-module.h> G_BEGIN_DECLS /* send/receive all uri's */ -GtkWidget * mail_send_receive (void); +GtkWidget * mail_send_receive (GtkWindow *parent); /* receive a single uri */ -void mail_receive_uri (const gchar *uri, +void mail_receive_uri (const gchar *uri, gboolean keep_on_server); void mail_send (void); /* setup auto receive stuff */ -void mail_autoreceive_init (CamelSession *session); +void mail_autoreceive_init (EShellModule *shell_module, + CamelSession *session); G_END_DECLS diff --git a/mail/mail-session.c b/mail/mail-session.c index e02ea41b55..8e7b2177c5 100644 --- a/mail/mail-session.c +++ b/mail/mail-session.c @@ -43,15 +43,16 @@ #include <camel/camel-filter-driver.h> #include <camel/camel-i18n.h> +#include "e-util/e-util.h" #include "e-util/e-error.h" #include "e-util/e-util-private.h" #include "e-account-combo-box.h" +#include "shell/e-shell.h" #include "em-composer-utils.h" #include "em-filter-context.h" #include "em-filter-rule.h" #include "em-utils.h" -#include "mail-component.h" #include "mail-config.h" #include "mail-mt.h" #include "mail-ops.h" @@ -83,6 +84,7 @@ typedef struct _MailSessionClass { } MailSessionClass; +static EShellModule *mail_shell_module; static CamelSessionClass *ms_parent_class; static char *get_password(CamelSession *session, CamelService *service, const char *domain, const char *prompt, const char *item, guint32 flags, CamelException *ex); @@ -504,13 +506,15 @@ main_get_filter_driver (CamelSession *session, const char *type, CamelException { CamelFilterDriver *driver; FilterRule *rule = NULL; + const gchar *data_dir; char *user, *system; GConfClient *gconf; RuleContext *fc; gconf = mail_config_get_gconf_client (); - user = g_strdup_printf ("%s/filters.xml", mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "filters.xml", NULL); system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL); fc = (RuleContext *) em_filter_context_new (); rule_context_load (fc, system, user); @@ -703,12 +707,20 @@ mail_session_check_junk_notify (GConfClient *gconf, guint id, GConfEntry *entry, } void -mail_session_init (const char *base_directory) +mail_session_init (EShellModule *shell_module) { - char *camel_dir; + EShell *shell; GConfClient *gconf; + gboolean online; + const gchar *data_dir; - if (camel_init (base_directory, TRUE) != 0) + mail_shell_module = shell_module; + + shell = e_shell_module_get_shell (shell_module); + online = e_shell_get_online (shell); + + data_dir = e_get_user_data_dir (); + if (camel_init (data_dir, TRUE) != 0) exit (0); camel_provider_init(); @@ -717,8 +729,8 @@ mail_session_init (const char *base_directory) e_account_combo_box_set_session (session); /* XXX Don't ask... */ e_account_writable(NULL, E_ACCOUNT_SOURCE_SAVE_PASSWD); /* Init the EAccount Setup */ - camel_dir = g_strdup_printf ("%s/mail", base_directory); - camel_session_construct (session, camel_dir); + data_dir = e_shell_module_get_data_dir (shell_module); + camel_session_construct (session, data_dir); gconf = mail_config_get_gconf_client (); gconf_client_add_dir (gconf, "/apps/evolution/mail/junk", GCONF_CLIENT_PRELOAD_ONELEVEL, NULL); @@ -728,10 +740,8 @@ mail_session_init (const char *base_directory) session, NULL, NULL); session->junk_plugin = NULL; - /* The shell will tell us to go online. */ - camel_session_set_online ((CamelSession *) session, FALSE); + camel_session_set_online ((CamelSession *) session, online); mail_config_reload_junk_headers (); - g_free (camel_dir); } void @@ -774,13 +784,6 @@ mail_session_set_interactive (gboolean interactive) } void -mail_session_forget_passwords (BonoboUIComponent *uih, void *user_data, - const char *path) -{ - e_passwords_forget_passwords (); -} - -void mail_session_flush_filter_log (void) { MailSession *ms = (MailSession *) session; diff --git a/mail/mail-session.h b/mail/mail-session.h index a2a5e9706f..e98a4bd604 100644 --- a/mail/mail-session.h +++ b/mail/mail-session.h @@ -24,15 +24,12 @@ #define MAIL_SESSION_H #include <glib.h> -#include <bonobo/bonobo-ui-component.h> #include <camel/camel-session.h> +#include <shell/e-shell-module.h> -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ +G_BEGIN_DECLS -void mail_session_init (const char *base_directory); +void mail_session_init (EShellModule *shell_module); void mail_session_shutdown (void); gboolean mail_session_get_interactive (void); void mail_session_set_interactive (gboolean interactive); @@ -42,8 +39,6 @@ gboolean mail_session_accept_dialog (const char *prompt, const char *key, gboolean async); char *mail_session_get_password (const char *url); void mail_session_add_password (const char *url, const char *passwd); -void mail_session_forget_passwords (BonoboUIComponent *uih, void *user_data, - const char *path); void mail_session_remember_password (const char *url); void mail_session_forget_password (const char *key); @@ -57,8 +52,6 @@ void mail_session_set_junk_headers (const char **name, const char **value, int l extern CamelSession *session; -#ifdef __cplusplus -} -#endif /* __cplusplus */ +G_END_DECLS -#endif /* ! MAIL_SESSION_H */ +#endif /* MAIL_SESSION_H */ diff --git a/mail/mail-signature-editor.c b/mail/mail-signature-editor.c deleted file mode 100644 index daee1db92c..0000000000 --- a/mail/mail-signature-editor.c +++ /dev/null @@ -1,498 +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: - * Radek Doulik <rodo@ximian.com> - * Jeffrey Stedfast <fejj@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "mail-signature-editor.h" - -#include <string.h> -#include <glib/gi18n.h> - -#include <e-util/e-error.h> -#include <e-util/e-signature-list.h> -#include <composer/e-msg-composer.h> - -#include "mail-config.h" - -#define E_SIGNATURE_EDITOR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_SIGNATURE_EDITOR, ESignatureEditorPrivate)) - -enum { - PROP_0, - PROP_SIGNATURE -}; - -struct _ESignatureEditorPrivate { - GtkActionGroup *action_group; - ESignature *signature; - GtkWidget *entry; - gchar *original_name; -}; - -static const gchar *ui = -"<ui>\n" -" <menubar name='main-menu'>\n" -" <placeholder name='pre-edit-menu'>\n" -" <menu action='file-menu'>\n" -" <menuitem action='save-and-close'/>\n" -" <separator/>" -" <menuitem action='close'/>\n" -" </menu>\n" -" </placeholder>\n" -" </menubar>\n" -" <toolbar name='main-toolbar'>\n" -" <placeholder name='pre-main-toolbar'>\n" -" <toolitem action='save-and-close'/>\n" -" </placeholder>\n" -" </toolbar>\n" -"</ui>"; - -static gpointer parent_class = NULL; - -static void -handle_error (GError **error) -{ - if (*error != NULL) { - g_warning ("%s", (*error)->message); - g_clear_error (error); - } -} - -static void -action_close_cb (GtkAction *action, - ESignatureEditor *editor) -{ - gboolean something_changed = FALSE; - const gchar *original_name; - const gchar *signature_name; - - original_name = editor->priv->original_name; - signature_name = gtk_entry_get_text (GTK_ENTRY (editor->priv->entry)); - - something_changed |= gtkhtml_editor_has_undo (GTKHTML_EDITOR (editor)); - something_changed |= (strcmp (signature_name, original_name) != 0); - - if (something_changed) { - gint response; - - response = e_error_run ( - GTK_WINDOW (editor), - "mail:ask-signature-changed", NULL); - if (response == GTK_RESPONSE_YES) { - GtkActionGroup *action_group; - - action_group = editor->priv->action_group; - action = gtk_action_group_get_action ( - action_group, "save-and-close"); - gtk_action_activate (action); - return; - } else if (response == GTK_RESPONSE_CANCEL) - return; - } - - gtk_widget_destroy (GTK_WIDGET (editor)); -} - -static void -action_save_and_close_cb (GtkAction *action, - ESignatureEditor *editor) -{ - GtkWidget *entry; - ESignatureList *signature_list; - ESignature *signature; - ESignature *same_name; - const gchar *filename; - gchar *signature_name; - gboolean html; - GError *error = NULL; - - entry = editor->priv->entry; - html = gtkhtml_editor_get_html_mode (GTKHTML_EDITOR (editor)); - - if (editor->priv->signature == NULL) - signature = mail_config_signature_new (NULL, FALSE, html); - else { - signature = g_object_ref (editor->priv->signature); - signature->html = html; - } - - filename = signature->filename; - gtkhtml_editor_save (GTKHTML_EDITOR (editor), filename, html, &error); - - if (error != NULL) { - e_error_run ( - GTK_WINDOW (editor), - "mail:no-save-signature", - error->message, NULL); - g_clear_error (&error); - return; - } - - signature_list = mail_config_get_signatures (); - - signature_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry))); - g_strstrip (signature_name); - - /* Make sure the signature name is not blank. */ - if (*signature_name == '\0') { - e_error_run ( - GTK_WINDOW (editor), - "mail:blank-signature", NULL); - gtk_widget_grab_focus (entry); - g_free (signature_name); - return; - } - - /* Don't overwrite an existing signature of the same name. - * XXX ESignatureList misuses const. */ - same_name = (ESignature *) e_signature_list_find ( - signature_list, E_SIGNATURE_FIND_NAME, signature_name); - if (same_name != NULL && strcmp (signature->uid, same_name->uid) != 0) { - e_error_run ( - GTK_WINDOW (editor), - "mail:signature-already-exists", - signature_name, NULL); - gtk_widget_grab_focus (entry); - g_free (signature_name); - return; - } - - g_free (signature->name); - signature->name = signature_name; - - if (editor->priv->signature != NULL) - e_signature_list_change (signature_list, signature); - else - mail_config_add_signature (signature); - - gtk_widget_destroy (GTK_WIDGET (editor)); -} - -static GtkActionEntry entries[] = { - - { "close", - GTK_STOCK_CLOSE, - N_("_Close"), - "<Control>w", - NULL, - G_CALLBACK (action_close_cb) }, - - { "save-and-close", - GTK_STOCK_SAVE, - N_("_Save and Close"), - "<Control>Return", - NULL, - G_CALLBACK (action_save_and_close_cb) }, - - { "file-menu", - NULL, - N_("_File"), - NULL, - NULL, - NULL } -}; - -static gboolean -signature_editor_delete_event_cb (ESignatureEditor *editor, - GdkEvent *event) -{ - GtkActionGroup *action_group; - GtkAction *action; - - action_group = editor->priv->action_group; - action = gtk_action_group_get_action (action_group, "close"); - gtk_action_activate (action); - - return TRUE; -} - -static void -signature_editor_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_SIGNATURE: - e_signature_editor_set_signature ( - E_SIGNATURE_EDITOR (object), - g_value_get_object (value)); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -signature_editor_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_SIGNATURE: - g_value_set_object ( - value, e_signature_editor_get_signature ( - E_SIGNATURE_EDITOR (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -signature_editor_dispose (GObject *object) -{ - ESignatureEditorPrivate *priv; - - priv = E_SIGNATURE_EDITOR_GET_PRIVATE (object); - - if (priv->action_group != NULL) { - g_object_unref (priv->action_group); - priv->action_group = NULL; - } - - if (priv->signature != NULL) { - g_object_unref (priv->signature); - priv->signature = NULL; - } - - if (priv->entry != NULL) { - g_object_unref (priv->entry); - priv->entry = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -signature_editor_finalize (GObject *object) -{ - ESignatureEditorPrivate *priv; - - priv = E_SIGNATURE_EDITOR_GET_PRIVATE (object); - - g_free (priv->original_name); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -signature_editor_class_init (ESignatureEditorClass *class) -{ - GObjectClass *object_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (ESignatureEditorPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->set_property = signature_editor_set_property; - object_class->get_property = signature_editor_get_property; - object_class->dispose = signature_editor_dispose; - object_class->finalize = signature_editor_finalize; - - g_object_class_install_property ( - object_class, - PROP_SIGNATURE, - g_param_spec_object ( - "signature", - NULL, - NULL, - E_TYPE_SIGNATURE, - G_PARAM_READWRITE)); -} - -static void -signature_editor_init (ESignatureEditor *editor) -{ - GtkActionGroup *action_group; - GtkUIManager *ui_manager; - GtkWidget *container; - GtkWidget *widget; - GtkWidget *vbox; - GError *error = NULL; - - editor->priv = E_SIGNATURE_EDITOR_GET_PRIVATE (editor); - vbox = GTKHTML_EDITOR (editor)->vbox; - - ui_manager = gtkhtml_editor_get_ui_manager (GTKHTML_EDITOR (editor)); - - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); - handle_error (&error); - - action_group = gtk_action_group_new ("signature"); - gtk_action_group_set_translation_domain ( - action_group, GETTEXT_PACKAGE); - gtk_action_group_add_actions ( - action_group, entries, - G_N_ELEMENTS (entries), editor); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - editor->priv->action_group = g_object_ref (action_group); - - gtk_ui_manager_ensure_update (ui_manager); - - gtk_window_set_title (GTK_WINDOW (editor), _("Edit Signature")); - - widget = gtk_hbox_new (FALSE, 6); - gtk_container_set_border_width (GTK_CONTAINER (widget), 6); - gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0); - /* Position 2 should be between the main and style toolbars. */ - gtk_box_reorder_child (GTK_BOX (vbox), widget, 2); - gtk_widget_show (widget); - container = widget; - - widget = gtk_entry_new (); - gtk_box_pack_end (GTK_BOX (container), widget, TRUE, TRUE, 0); - editor->priv->entry = g_object_ref_sink (widget); - gtk_widget_show (widget); - - widget = gtk_label_new_with_mnemonic (_("_Signature Name:")); - gtk_label_set_mnemonic_widget (GTK_LABEL (widget), editor->priv->entry); - gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 0); - gtk_widget_show (widget); - - g_signal_connect ( - editor, "delete-event", - G_CALLBACK (signature_editor_delete_event_cb), NULL); - - e_signature_editor_set_signature (editor, NULL); -} - -GType -e_signature_editor_get_type (void) -{ - static GType type = 0; - - if (G_UNLIKELY (type == 0)) { - static const GTypeInfo type_info = { - sizeof (ESignatureEditorClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) signature_editor_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (ESignatureEditor), - 0, /* n_preallocs */ - (GInstanceInitFunc) signature_editor_init, - NULL /* value_table */ - }; - - type = g_type_register_static ( - GTKHTML_TYPE_EDITOR, "ESignatureEditor", - &type_info, 0); - } - - return type; -} - -GtkWidget * -e_signature_editor_new (void) -{ - return g_object_new (E_TYPE_SIGNATURE_EDITOR, NULL); -} - -ESignature * -e_signature_editor_get_signature (ESignatureEditor *editor) -{ - g_return_val_if_fail (E_IS_SIGNATURE_EDITOR (editor), NULL); - - return editor->priv->signature; -} - -void -e_signature_editor_set_signature (ESignatureEditor *editor, - ESignature *signature) -{ - const gchar *filename; - const gchar *signature_name; - gchar *contents; - gsize length; - GError *error = NULL; - - g_return_if_fail (E_IS_SIGNATURE_EDITOR (editor)); - - if (signature != NULL) - g_return_if_fail (E_SIGNATURE (signature)); - - if (editor->priv->signature != NULL) { - g_object_unref (editor->priv->signature); - editor->priv->signature = NULL; - } - - if (signature == NULL) - goto exit; - - editor->priv->signature = g_object_ref (signature); - - /* Load signature content. */ - - filename = signature->filename; - - if (signature->html) - g_file_get_contents (filename, &contents, &length, &error); - else { - gchar *data; - - data = e_msg_composer_get_sig_file_content (filename, FALSE); - contents = g_strdup_printf ("<PRE>\n%s", data); - length = -1; - g_free (data); - } - - if (error == NULL) { - gtkhtml_editor_set_html_mode ( - GTKHTML_EDITOR (editor), signature->html); - gtkhtml_editor_set_text_html ( - GTKHTML_EDITOR (editor), contents, length); - g_free (contents); - } else { - g_warning ("%s", error->message); - g_error_free (error); - } - -exit: - if (signature != NULL) - signature_name = signature->name; - else - signature_name = _("Unnamed"); - - /* Set the entry text before we grab focus. */ - g_free (editor->priv->original_name); - editor->priv->original_name = g_strdup (signature_name); - gtk_entry_set_text (GTK_ENTRY (editor->priv->entry), signature_name); - - /* Set the focus appropriately. If this is a new signature, draw - * the user's attention to the signature name entry. Otherwise go - * straight to the editing area. */ - if (signature == NULL) - gtk_widget_grab_focus (editor->priv->entry); - else { - GtkHTML *html; - - html = gtkhtml_editor_get_html (GTKHTML_EDITOR (editor)); - gtk_widget_grab_focus (GTK_WIDGET (html)); - } - - g_object_notify (G_OBJECT (editor), "signature"); -} diff --git a/mail/mail-signature-editor.h b/mail/mail-signature-editor.h deleted file mode 100644 index 649504be18..0000000000 --- a/mail/mail-signature-editor.h +++ /dev/null @@ -1,72 +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: - * Radek Doulik <rodo@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef MAIL_SIGNATURE_EDITOR_H -#define MAIL_SIGNATURE_EDITOR_H - -#include <gtkhtml-editor.h> -#include <e-util/e-signature.h> - -/* Standard GObject macros */ -#define E_TYPE_SIGNATURE_EDITOR \ - (e_signature_editor_get_type ()) -#define E_SIGNATURE_EDITOR(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_SIGNATURE_EDITOR, ESignatureEditor)) -#define E_SIGNATURE_EDITOR_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_SIGNATURE_EDITOR, ESignatureEditorClass)) -#define E_IS_SIGNATURE_EDITOR(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_SIGNATURE_EDITOR)) -#define E_IS_SIGNATURE_EDITOR_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_SIGNATURE_EDITOR)) -#define E_SIGNATURE_EDITOR_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_SIGNATURE_EDITOR, ESignatureEditorClass)) - -G_BEGIN_DECLS - -typedef struct _ESignatureEditor ESignatureEditor; -typedef struct _ESignatureEditorClass ESignatureEditorClass; -typedef struct _ESignatureEditorPrivate ESignatureEditorPrivate; - -struct _ESignatureEditor { - GtkhtmlEditor parent; - ESignatureEditorPrivate *priv; -}; - -struct _ESignatureEditorClass { - GtkhtmlEditorClass parent_class; -}; - -GType e_signature_editor_get_type (void); -GtkWidget * e_signature_editor_new (void); -ESignature * e_signature_editor_get_signature (ESignatureEditor *editor); -void e_signature_editor_set_signature (ESignatureEditor *editor, - ESignature *signature); - -G_END_DECLS - -#endif /* MAIL_SIGNATURE_EDITOR_H */ diff --git a/mail/mail-tools.c b/mail/mail-tools.c index 7278829501..4c7131dacc 100644 --- a/mail/mail-tools.c +++ b/mail/mail-tools.c @@ -51,7 +51,6 @@ #include "em-utils.h" #include "em-vfolder-context.h" #include "em-vfolder-rule.h" -#include "mail-component.h" #include "mail-config.h" #include "mail-folder-cache.h" #include "mail-mt.h" @@ -59,6 +58,8 @@ #include "mail-tools.h" #include "mail-vfolder.h" +#include "e-mail-shell-module.h" + /* **************************************** */ CamelFolder * @@ -107,6 +108,7 @@ static char * mail_tool_get_local_movemail_path (const unsigned char *uri, CamelException *ex) { unsigned char *safe_uri, *c; + const gchar *data_dir; char *path, *full; struct stat st; @@ -115,7 +117,9 @@ mail_tool_get_local_movemail_path (const unsigned char *uri, CamelException *ex) if (strchr("/:;=|%&#!*^()\\, ", *c) || !isprint((int) *c)) *c = '_'; - path = g_strdup_printf("%s/spool", mail_component_peek_base_directory(NULL)); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + path = g_build_filename (data_dir, "spool", NULL); + if (g_stat(path, &st) == -1 && g_mkdir_with_parents(path, 0777) == -1) { camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Could not create spool directory `%s': %s"), path, g_strerror(errno)); diff --git a/mail/mail-types.h b/mail/mail-types.h deleted file mode 100644 index 1873dc8d00..0000000000 --- a/mail/mail-types.h +++ /dev/null @@ -1,40 +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/> - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef MAIL_TYPES_H -#define MAIL_TYPES_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - - -typedef struct _FolderBrowser FolderBrowser; -typedef struct _MessageBrowser MessageBrowser; -typedef struct _SubscribeDialog SubscribeDialog; -typedef struct _MessageList MessageList; -typedef struct _MailDisplay MailDisplay; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* MAIL_TYPES_H */ diff --git a/mail/mail-vfolder.c b/mail/mail-vfolder.c index ee0ab21e23..817b647dd7 100644 --- a/mail/mail-vfolder.c +++ b/mail/mail-vfolder.c @@ -31,10 +31,11 @@ #include <camel/camel-vee-folder.h> #include <camel/camel-vee-store.h> #include <camel/camel-vtrash-folder.h> +#include <libedataserver/e-account-list.h> -#include "libedataserver/e-account-list.h" #include "e-util/e-error.h" #include "e-util/e-util-private.h" +#include "e-util/e-account-utils.h" #include "em-folder-tree-model.h" #include "em-utils.h" @@ -42,7 +43,6 @@ #include "em-vfolder-editor.h" #include "em-vfolder-rule.h" #include "mail-autofilter.h" -#include "mail-component.h" #include "mail-config.h" #include "mail-folder-cache.h" #include "mail-mt.h" @@ -50,6 +50,8 @@ #include "mail-tools.h" #include "mail-vfolder.h" +#include "e-mail-shell-module.h" + #define d(x) /* (printf("%s:%s: ", G_STRLOC, G_STRFUNC), (x))*/ static EMVFolderContext *context; /* context remains open all time */ @@ -230,7 +232,7 @@ vfolder_adduri_desc (struct _adduri_msg *m) else uid = g_strdup_printf("%s@%s", url->user, url->host); - account = e_account_list_find(mail_config_get_accounts(), E_ACCOUNT_FIND_UID, uid); + account = e_get_account_by_uid (uid); g_free(uid); if (account != NULL) loc = account->name; @@ -348,21 +350,31 @@ uri_is_ignore(CamelStore *store, const char *uri) EAccountList *accounts; EAccount *account; EIterator *iter; + const gchar *local_drafts_folder_uri; + const gchar *local_outbox_folder_uri; + const gchar *local_sent_folder_uri; int found = FALSE; + local_drafts_folder_uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, E_MAIL_FOLDER_DRAFTS); + local_outbox_folder_uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, E_MAIL_FOLDER_OUTBOX); + local_sent_folder_uri = e_mail_shell_module_get_folder_uri ( + mail_shell_module, E_MAIL_FOLDER_SENT); + d(printf("checking '%s' against:\n %s\n %s\n %s\n", uri, - mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_OUTBOX), - mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_SENT), - mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_DRAFTS))); + local_outbox_folder_uri, + local_sent_folder_uri, + local_drafts_folder_uri)); - found = camel_store_folder_uri_equal(store, mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_OUTBOX), uri) - || camel_store_folder_uri_equal(store, mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_SENT), uri) - || camel_store_folder_uri_equal(store, mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_DRAFTS), uri); + found = camel_store_folder_uri_equal(store, local_outbox_folder_uri, uri) + || camel_store_folder_uri_equal(store, local_sent_folder_uri, uri) + || camel_store_folder_uri_equal(store, local_drafts_folder_uri, uri); if (found) return found; - accounts = mail_config_get_accounts (); + accounts = e_get_account_list (); iter = e_list_get_iterator ((EList *) accounts); while (e_iterator_is_valid (iter)) { char *curi; @@ -603,13 +615,14 @@ done: if (changed->str[0]) { GtkWidget *dialog; + const gchar *data_dir; char *user; dialog = e_error_new(NULL, "mail:vfolder-updated", changed->str, uri, NULL); em_utils_show_info_silent (dialog); - user = g_strdup_printf ("%s/vfolders.xml", - mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "vfolders.xml", NULL); rule_context_save ((RuleContext *) context, user); g_free (user); } @@ -672,10 +685,12 @@ mail_vfolder_rename_uri(CamelStore *store, const char *cfrom, const char *cto) UNLOCK(); if (changed) { + const gchar *data_dir; char *user; d(printf("Vfolders updated from renamed folder\n")); - user = g_strdup_printf("%s/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "vfolders.xml", NULL); rule_context_save((RuleContext *)context, user); g_free(user); } @@ -804,21 +819,12 @@ static void context_rule_added(RuleContext *ctx, FilterRule *rule) static void context_rule_removed(RuleContext *ctx, FilterRule *rule) { - char *path; - gpointer key, folder = NULL; d(printf("rule removed; %s\n", rule->name)); /* TODO: remove from folder info cache? */ - /* FIXME: is this even necessary? if we remove the folder from - * the CamelStore, the tree should pick it up auto-magically - * because it listens to CamelStore events... */ - path = g_strdup_printf("/%s", rule->name); - mail_component_remove_folder (mail_component_peek (), vfolder_store, path); - g_free(path); - LOCK(); if (g_hash_table_lookup_extended (vfolder_hash, rule->name, &key, &folder)) { g_hash_table_remove (vfolder_hash, key); @@ -860,6 +866,8 @@ store_folder_deleted(CamelObject *o, void *event_data, void *data) /* delete it from our list */ rule = rule_context_find_rule((RuleContext *)context, info->full_name, NULL); if (rule) { + const gchar *data_dir; + /* We need to stop listening to removed events, otherwise we'll try and remove it again */ g_signal_handlers_disconnect_matched(context, G_SIGNAL_MATCH_FUNC|G_SIGNAL_MATCH_DATA, 0, 0, NULL, context_rule_removed, context); @@ -867,7 +875,8 @@ store_folder_deleted(CamelObject *o, void *event_data, void *data) g_object_unref(rule); g_signal_connect(context, "rule_removed", G_CALLBACK(context_rule_removed), context); - user = g_strdup_printf("%s/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "vfolders.xml", NULL); rule_context_save((RuleContext *)context, user); g_free(user); } else { @@ -894,6 +903,8 @@ store_folder_renamed(CamelObject *o, void *event_data, void *data) LOCK(); d(printf("Changing folder name in hash table to '%s'\n", info->new->full_name)); if (g_hash_table_lookup_extended (vfolder_hash, info->old_base, &key, &folder)) { + const gchar *data_dir; + g_hash_table_remove (vfolder_hash, key); g_free (key); g_hash_table_insert (vfolder_hash, g_strdup(info->new->full_name), folder); @@ -910,7 +921,8 @@ store_folder_renamed(CamelObject *o, void *event_data, void *data) filter_rule_set_name(rule, info->new->full_name); g_signal_connect(rule, "changed", G_CALLBACK(rule_changed), folder); - user = g_strdup_printf("%s/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "vfolders.xml", NULL); rule_context_save((RuleContext *)context, user); g_free(user); @@ -927,6 +939,7 @@ vfolder_load_storage(void) /* lock for loading storage, it is safe to call it more than once */ static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + const gchar *data_dir; char *user, *storeuri; FilterRule *rule; char *xmlfile; @@ -945,7 +958,8 @@ vfolder_load_storage(void) pthread_mutex_unlock (&lock); /* first, create the vfolder store, and set it up */ - storeuri = g_strdup_printf("vfolder:%s/vfolder", mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + storeuri = g_strdup_printf("vfolder:%s/vfolder", data_dir); vfolder_store = camel_session_get_store(session, storeuri, NULL); if (vfolder_store == NULL) { g_warning("Cannot open vfolder store - no vfolders available"); @@ -962,7 +976,7 @@ vfolder_load_storage(void) d(printf("got store '%s' = %p\n", storeuri, vfolder_store)); /* load our rules */ - user = g_strdup_printf ("%s/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ())); + user = g_build_filename (data_dir, "vfolders.xml", NULL); context = em_vfolder_context_new (); xmlfile = g_build_filename (EVOLUTION_PRIVDATADIR, "vfoldertypes.xml", NULL); @@ -977,7 +991,8 @@ vfolder_load_storage(void) g_signal_connect(context, "rule_removed", G_CALLBACK(context_rule_removed), context); /* load store to mail component */ - mail_component_load_store_by_uri (mail_component_peek (), storeuri, _("Search Folders")); + e_mail_shell_module_load_store_by_uri ( + mail_shell_module, storeuri, _("Search Folders")); /* and setup the rules we have */ rule = NULL; @@ -1000,66 +1015,66 @@ vfolder_load_storage(void) void vfolder_revert(void) { + const gchar *data_dir; char *user; d(printf("vfolder_revert\n")); - user = g_strdup_printf("%s/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "vfolders.xml", NULL); rule_context_revert((RuleContext *)context, user); g_free(user); } -static GtkWidget *vfolder_editor = NULL; - -static void -em_vfolder_editor_response (GtkWidget *dialog, int button, void *data) +void +vfolder_edit (EShellView *shell_view) { - char *user; + EShellModule *shell_module; + EShellWindow *shell_window; + GtkWidget *dialog; + const gchar *data_dir; + gchar *filename; - user = g_strdup_printf ("%s/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ())); - - switch(button) { - case GTK_RESPONSE_OK: - rule_context_save((RuleContext *)context, user); - break; - default: - rule_context_revert((RuleContext *)context, user); - } + g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); - vfolder_editor = NULL; + shell_module = e_shell_view_get_shell_module (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); - gtk_widget_destroy(dialog); - - g_free (user); -} - -void -vfolder_edit (void) -{ - if (vfolder_editor) { - gdk_window_raise (GTK_WIDGET (vfolder_editor)->window); - return; - } + data_dir = e_shell_module_get_data_dir (shell_module); + filename = g_build_filename (data_dir, "vfolders.xml", NULL); /* ensures vfolder is running */ vfolder_load_storage (); - vfolder_editor = GTK_WIDGET (em_vfolder_editor_new (context)); - gtk_window_set_title (GTK_WINDOW (vfolder_editor), _("Search Folders")); - g_signal_connect(vfolder_editor, "response", G_CALLBACK(em_vfolder_editor_response), NULL); + dialog = em_vfolder_editor_new (context); + gtk_window_set_title ( + GTK_WINDOW (dialog), _("Search Folders")); + gtk_window_set_transient_for ( + GTK_WINDOW (dialog), GTK_WINDOW (shell_window)); + + switch (gtk_dialog_run (GTK_DIALOG (dialog))) { + case GTK_RESPONSE_OK: + rule_context_save ((RuleContext *) context, filename); + break; + default: + rule_context_revert ((RuleContext *) context, filename); + break; + } - gtk_widget_show (vfolder_editor); + gtk_widget_destroy (dialog); } static void edit_rule_response(GtkWidget *w, int button, void *data) { if (button == GTK_RESPONSE_OK) { + const gchar *data_dir; char *user; FilterRule *rule = g_object_get_data (G_OBJECT (w), "rule"); FilterRule *orig = g_object_get_data (G_OBJECT (w), "orig"); filter_rule_copy(orig, rule); - user = g_strdup_printf("%s/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "vfolders.xml", NULL); rule_context_save((RuleContext *)context, user); g_free(user); } @@ -1116,6 +1131,7 @@ static void new_rule_clicked(GtkWidget *w, int button, void *data) { if (button == GTK_RESPONSE_OK) { + const gchar *data_dir; char *user; FilterRule *rule = g_object_get_data((GObject *)w, "rule"); @@ -1132,7 +1148,8 @@ new_rule_clicked(GtkWidget *w, int button, void *data) g_object_ref(rule); rule_context_add_rule((RuleContext *)context, rule); - user = g_strdup_printf("%s/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ())); + data_dir = e_shell_module_get_data_dir (mail_shell_module); + user = g_build_filename (data_dir, "vfolders.xml", NULL); rule_context_save((RuleContext *)context, user); g_free(user); } diff --git a/mail/mail-vfolder.h b/mail/mail-vfolder.h index b0f684e721..2db87654b1 100644 --- a/mail/mail-vfolder.h +++ b/mail/mail-vfolder.h @@ -22,6 +22,8 @@ #ifndef _MAIL_VFOLDER_H #define _MAIL_VFOLDER_H +#include <shell/e-shell-view.h> + struct _CamelStore; struct _FilterPart; struct _FilterRule; @@ -32,7 +34,7 @@ struct _CamelInternetAddress; void vfolder_load_storage(void); void vfolder_revert(void); -void vfolder_edit (void); +void vfolder_edit (EShellView *shell_view); void vfolder_edit_rule(const char *name); struct _FilterPart *vfolder_create_part (const char *name); struct _FilterRule *vfolder_clone_rule (struct _FilterRule *in); diff --git a/mail/message-list.c b/mail/message-list.c index 3027fcf3e8..11d0f19707 100644 --- a/mail/message-list.c +++ b/mail/message-list.c @@ -50,10 +50,12 @@ #include "e-util/e-profile-event.h" #include "e-util/e-util-private.h" #include "e-util/e-util.h" -#include "e-util/e-util-labels.h" #include "misc/e-gui-utils.h" +#include "shell/e-shell.h" +#include "shell/e-shell-settings.h" + #include "table/e-cell-checkbox.h" #include "table/e-cell-hbox.h" #include "table/e-cell-date.h" @@ -67,6 +69,7 @@ #include "table/e-cell-vbox.h" #include "table/e-cell-hbox.h" +#include "e-mail-label-list-store.h" #include "em-popup.h" #include "em-utils.h" #include "mail-config.h" @@ -97,6 +100,10 @@ #define d(x) #define t(x) +#define MESSAGE_LIST_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), MESSAGE_LIST_TYPE, MessageListPrivate)) + struct _MLSelection { GPtrArray *uids; CamelFolder *folder; @@ -106,6 +113,8 @@ struct _MLSelection { struct _MessageListPrivate { GtkWidget *invisible; /* 4 selection */ + EShellModule *shell_module; + struct _MLSelection clipboard; gboolean destroyed; @@ -113,6 +122,11 @@ struct _MessageListPrivate { gboolean any_row_changed; /* save state before regen list when this is set to true */ }; +enum { + PROP_0, + PROP_SHELL_MODULE +}; + static struct { char *target; GdkAtom atom; @@ -809,7 +823,7 @@ message_list_invert_selection (MessageList *message_list) void message_list_copy(MessageList *ml, gboolean cut) { - struct _MessageListPrivate *p = ml->priv; + MessageListPrivate *p = ml->priv; GPtrArray *uids; clear_selection(ml, &p->clipboard); @@ -1222,52 +1236,123 @@ sanitize_recipients (const gchar *string) } static int -get_all_labels (CamelMessageInfo *msg_info, char **label_str, gboolean get_tags) -{ +get_all_labels (MessageList *message_list, + CamelMessageInfo *msg_info, + gchar **label_str, + gboolean get_tags) +{ + EShell *shell; + EShellModule *shell_module; + EShellSettings *shell_settings; + EMailLabelListStore *store; + GtkTreeIter iter; GString *str; - const char *old_label; + const gchar *property_name; + const gchar *old_label; + gchar *new_label; int count = 0; const CamelFlag *flag; - GSList *labels; - labels = mail_config_get_labels (); + shell_module = message_list_get_shell_module (message_list); + shell = e_shell_module_get_shell (shell_module); + shell_settings = e_shell_get_shell_settings (shell); + + property_name = "mail-label-list-store"; + store = e_shell_settings_get_object (shell_settings, property_name); + str = g_string_new (""); for (flag = camel_message_info_user_flags (msg_info); flag; flag = flag->next) { - const char *name = e_util_labels_get_name (labels, flag->name); + gchar *item; - if (name) { - if (str->len) - g_string_append (str, ", "); + if (!e_mail_label_list_store_lookup (store, flag->name, &iter)) + continue; - if (get_tags) - name = flag->name; + if (get_tags) + item = e_mail_label_list_store_get_tag (store, &iter); + else + item = e_mail_label_list_store_get_name (store, &iter); - g_string_append (str, name); - count++; - } + if (str->len) + g_string_append (str, ", "); + + g_string_append (str, item); + count++; + + g_free (item); } - old_label = e_util_labels_get_new_tag (camel_message_info_user_tag (msg_info, "label")); + old_label = camel_message_info_user_tag (msg_info, "label"); + if (old_label == NULL) + goto exit; - if (old_label != NULL) { - const char *name = NULL; + /* Convert old-style labels ("<name>") to "$Label<name>". */ + new_label = g_alloca (strlen (old_label) + 10); + g_stpcpy (g_stpcpy (new_label, "$Label"), old_label); + + if (e_mail_label_list_store_lookup (store, new_label, &iter)) { + gchar *name = NULL; if (str->len) g_string_append (str, ", "); if (!get_tags) - name = e_util_labels_get_name (labels, old_label); + name = e_mail_label_list_store_get_name (store, &iter); g_string_append (str, (get_tags || !name) ? old_label : name); - ++count; + count++; + + g_free (name); } +exit: *label_str = g_string_free (str, FALSE); + g_object_unref (store); + return count; } +static const gchar * +get_label_color (MessageList *message_list, + const gchar *tag) +{ + EShell *shell; + EShellModule *shell_module; + EShellSettings *shell_settings; + EMailLabelListStore *store; + GtkTreeIter iter; + GdkColor color; + const gchar *property_name; + const gchar *interned = NULL; + gchar *color_spec; + + /* FIXME get_all_labels() should return an array of tree iterators, + * not strings. Now we just have to lookup the tag again. */ + + shell_module = message_list_get_shell_module (message_list); + shell = e_shell_module_get_shell (shell_module); + shell_settings = e_shell_get_shell_settings (shell); + + property_name = "mail-label-list-store"; + store = e_shell_settings_get_object (shell_settings, property_name); + + if (!e_mail_label_list_store_lookup (store, tag, &iter)) + goto exit; + + e_mail_label_list_store_get_color (store, &iter, &color); + + /* XXX Hack to avoid returning an allocated string. */ + color_spec = gdk_color_to_string (&color); + interned = g_intern_string (color_spec); + g_free (color_spec); + +exit: + g_object_unref (store); + + return interned; +} + static const char * get_trimmed_subject (CamelMessageInfo *info) { @@ -1469,9 +1554,8 @@ ml_tree_value_at (ETreeModel *etm, ETreePath path, int col, void *model_data) completed = camel_message_info_user_tag(msg_info, "completed-on"); followup = camel_message_info_user_tag(msg_info, "follow-up"); if (colour == NULL) { - if ((n = get_all_labels (msg_info, &labels_string, TRUE)) == 1) { - - colour = e_util_labels_get_color_str (mail_config_get_labels (), labels_string); + if ((n = get_all_labels (message_list, msg_info, &labels_string, TRUE)) == 1) { + colour = get_label_color (message_list, labels_string); } else if (camel_message_info_flags(msg_info) & CAMEL_MESSAGE_FLAGGED) { /* FIXME: extract from the important.xpm somehow. */ colour = "#A7453E"; @@ -1550,7 +1634,7 @@ ml_tree_value_at (ETreeModel *etm, ETreePath path, int col, void *model_data) cleansed_str = g_string_new (""); - if (get_all_labels (msg_info, &str, FALSE)) { + if (get_all_labels (message_list, msg_info, &str, FALSE)) { int i; for (i = 0; str[i] != '\0'; ++i) { if (str[i] != '_') { @@ -1946,7 +2030,7 @@ ml_selection_get(GtkWidget *widget, GtkSelectionData *data, guint info, guint ti static gboolean ml_selection_clear_event(GtkWidget *widget, GdkEventSelection *event, MessageList *ml) { - struct _MessageListPrivate *p = ml->priv; + MessageListPrivate *p = ml->priv; clear_selection(ml, &p->clipboard); @@ -2241,13 +2325,25 @@ on_model_row_changed (ETableModel *model, int row, MessageList *ml) /* * GObject::init */ + +static void +message_list_set_shell_module (MessageList *message_list, + EShellModule *shell_module) +{ + g_return_if_fail (message_list->priv->shell_module == NULL); + + message_list->priv->shell_module = g_object_ref (shell_module); +} + static void message_list_init (MessageList *message_list) { - struct _MessageListPrivate *p; + MessageListPrivate *p; GtkAdjustment *adjustment; GdkAtom matom; + message_list->priv = MESSAGE_LIST_GET_PRIVATE (message_list); + adjustment = (GtkAdjustment *) gtk_adjustment_new (0.0, 0.0, G_MAXDOUBLE, 0.0, 0.0, 0.0); gtk_scrolled_window_set_vadjustment ((GtkScrolledWindow *) message_list, adjustment); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (message_list), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); @@ -2276,7 +2372,7 @@ message_list_init (MessageList *message_list) message_list->regen_lock = g_mutex_new (); /* TODO: Should this only get the selection if we're realised? */ - p = message_list->priv = g_malloc0(sizeof(*message_list->priv)); + p = message_list->priv; p->invisible = gtk_invisible_new(); p->destroyed = FALSE; g_object_ref_sink(p->invisible); @@ -2297,7 +2393,7 @@ static void message_list_destroy(GtkObject *object) { MessageList *message_list = MESSAGE_LIST (object); - struct _MessageListPrivate *p = message_list->priv; + MessageListPrivate *p = message_list->priv; p->destroyed = TRUE; @@ -2349,14 +2445,65 @@ message_list_destroy(GtkObject *object) message_list->seen_id = 0; } + /* Chain up to parent's destroy() method. */ GTK_OBJECT_CLASS (message_list_parent_class)->destroy(object); } static void -message_list_finalise (GObject *object) +message_list_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SHELL_MODULE: + message_list_set_shell_module ( + MESSAGE_LIST (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +message_list_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SHELL_MODULE: + g_value_set_object ( + value, message_list_get_shell_module ( + MESSAGE_LIST (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +message_list_dispose (GObject *object) +{ + MessageListPrivate *priv; + + priv = MESSAGE_LIST_GET_PRIVATE (object); + + if (priv->shell_module != NULL) { + g_object_unref (priv->shell_module); + priv->shell_module = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (message_list_parent_class)->dispose (object); +} + +static void +message_list_finalize (GObject *object) { MessageList *message_list = MESSAGE_LIST (object); - struct _MessageListPrivate *p = message_list->priv; + MessageListPrivate *priv = message_list->priv; g_hash_table_destroy (message_list->normalised_hash); @@ -2386,10 +2533,9 @@ message_list_finalise (GObject *object) g_free(message_list->folder_uri); message_list->folder_uri = NULL; - clear_selection(message_list, &p->clipboard); - - g_free(p); + clear_selection(message_list, &priv->clipboard); + /* Chain up to parent's finalize() method. */ G_OBJECT_CLASS (message_list_parent_class)->finalize (object); } @@ -2397,17 +2543,36 @@ message_list_finalise (GObject *object) * GObjectClass::init */ static void -message_list_class_init (MessageListClass *message_list_class) +message_list_class_init (MessageListClass *class) { - GObjectClass *object_class = (GObjectClass *) message_list_class; - GtkObjectClass *gtkobject_class = (GtkObjectClass *) message_list_class; + GObjectClass *object_class; + GtkObjectClass *gtk_object_class; int i; for (i=0;i<sizeof(ml_drag_info)/sizeof(ml_drag_info[0]);i++) ml_drag_info[i].atom = gdk_atom_intern(ml_drag_info[i].target, FALSE); - object_class->finalize = message_list_finalise; - gtkobject_class->destroy = message_list_destroy; + g_type_class_add_private (class, sizeof (MessageListPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = message_list_set_property; + object_class->get_property = message_list_get_property; + object_class->dispose = message_list_dispose; + object_class->finalize = message_list_finalize; + + gtk_object_class = GTK_OBJECT_CLASS (class); + gtk_object_class->destroy = message_list_destroy; + + g_object_class_install_property ( + object_class, + PROP_SHELL_MODULE, + g_param_spec_object ( + "shell-module", + _("Shell Module"), + _("The mail shell module"), + E_TYPE_SHELL_MODULE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); message_list_signals[MESSAGE_SELECTED] = g_signal_new ("message_selected", @@ -2560,19 +2725,30 @@ message_list_construct (MessageList *message_list) * Returns a new message-list widget. **/ GtkWidget * -message_list_new (void) +message_list_new (EShellModule *shell_module) { MessageList *message_list; + g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), NULL); + message_list = MESSAGE_LIST (g_object_new(message_list_get_type (), "hadjustment", NULL, "vadjustment", NULL, + "shell-module", shell_module, NULL)); message_list_construct (message_list); return GTK_WIDGET (message_list); } +EShellModule * +message_list_get_shell_module (MessageList *message_list) +{ + g_return_val_if_fail (IS_MESSAGE_LIST (message_list), NULL); + + return message_list->priv->shell_module; +} + static void clear_info(char *key, ETreePath *node, MessageList *ml) { @@ -4067,9 +4243,8 @@ regen_list_exec (struct _regen_list_msg *m) if ((!is_deleted || (is_deleted && !m->hidedel)) && (!is_junk || (is_junk && !m->hidejunk))) g_ptr_array_add (uids, (gpointer) camel_pstring_strdup (looking_for)); - - camel_folder_free_message_info (m->folder, looking_info); } + } } } diff --git a/mail/message-list.h b/mail/message-list.h index 47be897fd2..0876d93d05 100644 --- a/mail/message-list.h +++ b/mail/message-list.h @@ -28,6 +28,9 @@ #include <table/e-table-simple.h> #include <table/e-tree-scrolled.h> +#include <camel/camel-folder.h> +#include <shell/e-shell-module.h> + #ifdef __cplusplus extern "C" { #pragma } @@ -85,11 +88,13 @@ enum { #define ML_HIDE_SAME (2147483646) typedef struct _MessageList MessageList; +typedef struct _MessageListClass MessageListClass; +typedef struct _MessageListPrivate MessageListPrivate; struct _MessageList { ETreeScrolled parent; - struct _MessageListPrivate *priv; + MessageListPrivate *priv; /* The table */ ETreeModel *model; @@ -165,14 +170,14 @@ struct _MessageList { struct _MailAsyncEvent *async_event; }; -typedef struct { +struct _MessageListClass { ETreeScrolledClass parent_class; /* signals - select a message */ void (*message_selected) (MessageList *ml, const char *uid); void (*message_list_built) (MessageList *ml); void (*message_list_scrolled) (MessageList *ml); -} MessageListClass; +}; typedef enum { MESSAGE_LIST_SELECT_NEXT = 0, @@ -182,7 +187,8 @@ typedef enum { } MessageListSelectDirection; GType message_list_get_type (void); -GtkWidget *message_list_new (void); +GtkWidget *message_list_new (EShellModule *shell_module); +EShellModule *message_list_get_shell_module (MessageList *message_list); void message_list_set_folder (MessageList *message_list, CamelFolder *camel_folder, const char *uri, gboolean outgoing); void message_list_freeze(MessageList *ml); diff --git a/mail/message-tag-followup.c b/mail/message-tag-followup.c index 2ddd372257..f2a7437a6f 100644 --- a/mail/message-tag-followup.c +++ b/mail/message-tag-followup.c @@ -293,6 +293,11 @@ construct (MessageTagEditor *editor) gtk_widget_reparent (widget, GTK_DIALOG (editor)->vbox); gtk_box_set_child_packing (GTK_BOX (GTK_DIALOG (editor)->vbox), widget, TRUE, TRUE, 6, GTK_PACK_START); + widget = glade_xml_get_widget (gui, "pixmap"); + gtk_image_set_from_icon_name ( + GTK_IMAGE (widget), "stock_mail-flag-for-followup", + GTK_ICON_SIZE_DIALOG); + followup->message_list = GTK_TREE_VIEW (glade_xml_get_widget (gui, "message_list")); model = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING); gtk_tree_view_set_model (followup->message_list, (GtkTreeModel *) model); diff --git a/mail/searchtypes.xml b/mail/searchtypes.xml index 83941d875c..ba349993f7 100644 --- a/mail/searchtypes.xml +++ b/mail/searchtypes.xml @@ -569,7 +569,7 @@ </option> </input> <input type="optionlist" name="versus"> - <dynamic func="e_util_labels_get_filter_options"/> + <dynamic func="e_mail_labels_get_filter_options"/> </input> </part> diff --git a/mail/vfoldertypes.xml b/mail/vfoldertypes.xml index 11ed7cc0af..9fd117b67d 100644 --- a/mail/vfoldertypes.xml +++ b/mail/vfoldertypes.xml @@ -569,7 +569,7 @@ </option> </input> <input type="optionlist" name="versus"> - <dynamic func="e_util_labels_get_filter_options"/> + <dynamic func="e_mail_labels_get_filter_options"/> </input> </part> |