diff options
Diffstat (limited to 'mail')
34 files changed, 5588 insertions, 3437 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog index b4c9f43a27..e02b747a6a 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,306 +1,78 @@ -2005-02-15 Radek Doulik <rodo@novell.com> +2005-02-09 Jeffrey Stedfast <fejj@novell.com> - * em-junk-filter.c: use camel_debug - -2005-02-10 Not Zed <NotZed@Ximian.com> - - ** See bug #72266 - - * em-folder-selection-button.c - (em_folder_selection_button_clicked): if the selector is already - up, just raise it. - (em_folder_selection_button_destroy): destroy the selector if it - is still up. + * message-list.c (message_list_set_folder): Reset the + normalised_hash. Fixes bug #33933. 2005-02-09 Not Zed <NotZed@Ximian.com> - ** See bug #71429 - - * em-folder-view.c (emfv_activate): setup the plugin menu's after - the main ones. - -2005-02-08 Not Zed <NotZed@Ximian.com> - - ** See bug #72228 - - * mail-ops.c (mail_send_message): fix this god-awful goto-loop - crap, and delete the message if it worked. - (mail_send_message): fix a major-leak with sent messages never - being unreffed. - (send_queue_send): don't get messages ourself. - (mail_send_message): dont lose the exception if we - can't even open the sent folder. - -2005-02-07 Not Zed <NotZed@Ximian.com> - - ** See bug #72209 - - * em-folder-tree.c (emft_popup_copy_folder_exclude): implement one - for copying/moving folders. - - * em-folder-selection.c (em_select_folder): add an excluded func - argument, fix callers. - - * em-folder-tree.c - (em_folder_tree_set_exclude_func): allow custom callback for - exclusion. - (emft_select_func): handle the custom excluded callback. + ** See bug #70795 -2005-02-07 Harry Lu <harry.lu@sun.com> + * em-folder-view.c (em_folder_view_open_selected): set the search + on the browser to match the current view. - Fix for 72275. - * em-folder-view.c: (emfv_popup_menu): try to bring up menu for - preivew html object. - (emfv_format_popup_event): handle event == NULL case. - * em-format-html-display.c: (em_format_html_display_popup_menu): - New function to popup context menu. - * em-format-html-display.h: add new function declaration. + * message-list.c (mail_regen_list): save the search if no folder + set, incase the folder gets set later on. 2005-02-04 Not Zed <NotZed@Ximian.com> - * em-subscribe-editor.c (sub_folderinfo_get): reverted jeff's - patch for the subscribed hint. - ** See bug #65329 * em-folder-properties.c (emfp_dialog_got_folder): translate local-store special folders. - * mail-session.c (alert_user, do_user_message): if we aren't - waiting for cancel, then don't worry about waiting on the reply - port, otherwise we could block when we don't need to, if there is - another window already up. - -2005-02-03 Jeffrey Stedfast <fejj@novell.com> - - * message-list.c (message_list_set_folder): Use - g_hash_table_foreach_remove() instead so the keys don't point to - free'd values. - (normalised_free): Return TRUE. - -2005-02-02 Rodney Dawes <dobey@novell.com> - - * em-subscribe-editor.c (em_subscribe_editor_new): Use the - gtk_widget_ensure_style method instead of gtk_widget_realize when - setting the border widths of the dialog containers for HIG compliance - - Fixes #68743 - -2005-02-02 Jeffrey Stedfast <fejj@novell.com> - - Fixes bug #70454 - - * em-subscribe-editor.c (sub_folderinfo_get): Request subscription - info (new flag). - (sub_fill_level): Fixed the FIXME here (imap4 now implements - CAMEL_FOLDER_SUBSCRIBED flag properly). - -2005-02-01 Rodney Dawes <dobey@novell.com> - - * em-folder-browser.c: Replace "_Virtual Folder" with "_vFolder" for - the search menu to create a vfolder from a search - - * em-folder-tree-model.c (sort_cb): s/VFolders/vFolders/ for sorting - in the folder tree - (em_folder_tree_model_load_state): s/VFolders/vFolders/ in a comment - - * em-folder-view.c: s/VFolder/vFolder/ for the popup menu - - * em-vfolder-editor.c (em_vfolder_editor_new): Replace the string - "Virtual _Folders" with "v_Folders" for the label - - * em-vfolder-rule.c (em_vfolder_editor_sourcelist_new): Repalce the - string "VFolder source" with "vFolder source" - - * mail-errors.xml: - * mail-errors.xml.h: Replace "virtual folder" with "vFolder" in an - error string - - * mail-vfolder.c (vfolder_setup_desc): s/vfolder/vFolder/ - (vfolder_setup_do): s/vfolder/vFolder/ - (vfolder_load_storage): s/VFolders/vFolders/ - (vfolder_edit_rule): s/VFolder/vFolder/ - (vfolder_gui_add_rule): s/VFolder/vFolder/ - - Fixes #68137 - 2005-02-01 Not Zed <NotZed@Ximian.com> - ** See bug #65329. - - * mail-component.c (view_changed_cb): translate special names on - the local store. - - * em-folder-tree-model.c (sort_cb): use the type hint to sort for - inbox, not the name. - (emft_is_special_local_folder): removed. - (em_folder_tree_model_set_folder_info): special-case the - local-store case, handle translated names and the name hints. - - * em-folder-tree.c (render_pixbuf): use the camel folderinfo - folder type to determine the icon, don't hardcode based on name. - - ** See bug #71310 - - * em-composer-prefs.c (sig_add_script_response): force a save of - the signatures as soon as they change. Also save the script name - if we were just editing it, not just the signature name. - ** See bug #71312. * em-folder-view.c (em_folder_view_open_selected): if we're looking at a vfolder, then look open the original folder if we need to perform any edits. -2005-01-31 Hans Petter Jansson <hpj@novell.com> - - * importers/mail-importer.h (mc): Remove unused global symbol. - -2005-01-28 Jeffrey Stedfast <fejj@novell.com> +2005-02-01 Not Zed <NotZed@Ximian.com> - * message-list.c (message_list_set_folder): Reset the normalised - string sort table. + ** See bug #71310 -2005-01-31 JP Rosevear <jpr@novell.com> + * em-composer-prefs.c (sig_add_script_response): force a save of + the signatures as soon as they change. Also save the script name + if we were just editing it, not just the signature name. - Fixes #71937 +2005-02-01 Not Zed <NotZed@Ximian.com> - * evolution-mail.schemas.in.in: fix spelling error + ** See bug #65329. - * mail-errors.xml: fix two spelling errors + * mail-component.c (view_changed_cb): translate special names on + the local store. 2005-01-31 Not Zed <NotZed@Ximian.com> - - ** See bug #67083 - - * em-format-html.c (efh_format_text_header): no-wrap the header line. - + ** See bug #69850 * mail-autofilter.c (rule_from_message): dont crash if we're missing the requested headers. - ** See bug #71521. - - * em-account-editor.c (emae_url_set_hostport): dont ever set a - NULL host. - -2005-01-28 Not Zed <NotZed@Ximian.com> - - * em-account-editor.c (emae_service_provider_changed): handle - 'hide' bits, don't get/set values from the widgets at all. - - * em-account-editor.c: put some tables back into the - druid and editor, since econfig supports tables now. - - * em-account-editor.c (emae_service_provider_changed): handle - 'hide' bits, don't get/set values from the widgets at all. - - * em-account-editor.c: put some tables back into the - druid and editor, since econfig supports tables now. - - * em-account-editor.c (emae_service_provider_changed): handle - 'hide' bits, don't get/set values from the widgets at all. - - * em-account-editor.c: put some tables back into the - druid and editor, since econfig supports tables now. - - ** See bug #71520. - - * em-account-prefs.c (account_edit_clicked): repeat the nasty hack - from account_edit, to refresh the list after edit. - -2005-01-27 Not Zed <NotZed@Ximian.com> - - * See bug #69815. - - * mail-component.c (impl_quit): shutdown vfolders as first step. - - * mail-vfolder.c (vfolder_setup_do): if we're shutdown during - processing, just noop. - (vfolder_adduri_do): same. - (mail_vfolder_shutdown): set the shutdown flag. - -2005-01-27 Rodney Dawes <dobey@novell.com> - - * mail-config.glade: Fix the labels in the account druid to be - left aligned, and justified left - Fix the border and spacing for all the vboxes in the account druid - pages to be HIG compliant - Fix the account naming info label to be more concise - - Fixes #68696 - -2005-01-27 Rodney Dawes <dobey@novell.com> - - * mail-send-recv.c (build_dialog): Fix the dialog to have borders - that are HIG-compliant and fix up the spacing and padding of the - internal widgets to do the right thing to be HIG compliant - -2005-01-27 JP Rosevear <jpr@novell.com> - - * em-format-hook.c: add a d(x) debugging define and default to off - -2005-01-26 Mengjie Yu <meng-jie.yu@sun.com> - - Fixes #71774 - - * em-folder-tree.c (emft_popup_rename_folder): we should check - whether the 'new_name' is a NULL pointer to avoid Evolution - crashes. - -2005-01-25 Mengjie Yu <meng-jie.yu@sun.com> - - * em-mailer-prefs.c: (restore_labels_clicked), - (em_mailer_prefs_construct): - add a11y names for color pickers. - -2005-01-24 Hans Petter Jansson <hpj@novell.com> - - * Makefile.am (libevolution_mail_la_LIBADD): Pull in the contact - editors, so we can pass pointers to their creation functions to - ENameSelectorEntry. - -2005-01-24 JP Rosevear <jpr@novell.com> - - * searchtypes.xml: add back body contains - -2005-01-21 JP Rosevear <jpr@novell.com> - - Fixes #46287 - - * mail-config.glade: remove enable/disable button - - * em-composer-prefs.h: remove unused button - - * em-composer-prefs.c (spell_language_toggled): handle the cell - being toggled - (spell_setup): enable/disable button is gone - (em_composer_prefs_construct): setup a listener for the toggle - cell - -2005-01-24 Radek Doulik <rodo@ximian.com> +2005-01-14 Not Zed <NotZed@Ximian.com> - * em-popup.[ch]: removed EM_POPUP_SELECT_MARK_[NO]JUNK masks + ** Related to changes for #65178. -2005-01-20 Radek Doulik <rodo@ximian.com> + * mail-vfolder.c (mv_find_folder): changed from my_list_find, take + store arg and use camel_Store_Folder_uri_equal() instead of wrong + uri_cmp function. + (mail_vfolder_delete_uri): same. + (mail_vfolder_rename_uri): same. + (uri_is_ignore): take store arg, and same as above. use the right + uri for checking sent folder. + (mail_vfolder_*): convert to storing uri's in camel form. - * em-folder-view.c: patch from Chris Lahey, makes Mark as Junk/not - Junk items active on all messages, removes calls to - message_list_get_selected where not needed +2005-01-19 Not Zed <NotZed@Ximian.com> -2005-01-24 Not Zed <NotZed@Ximian.com> + ** See bug #70858. - * searchtypes.xml: changed for 69122. + * em-folder-selector.c (folder_created_cb): removed. + (emfs_response): set the selected uri directly after creating it, + rather than doing it asynchronously. -2005-01-21 JP Rosevear <jpr@novell.com> - - Fixes #46404 - - * em-folder-view.c (emfv_print_response): use the config in the - print data and free it - (em_folder_view_print): load the config from e_print and use the - dialog from e_print + * mail-account-gui.c (mail_account_gui_save): dont dereference + default folder pointers if they're NULL. 2005-01-21 Not Zed <NotZed@Ximian.com> @@ -309,30 +81,34 @@ * em-format-html-display.c (efhd_init, efhd_gtkhtml_style_set): if the style changes, re-calculate the page colours, and redraw. -2005-01-20 Jeffrey Stedfast <fejj@novell.com> +2005-01-18 Not Zed <NotZed@Ximian.com> - * em-folder-tree.c (emft_copy_folders__desc): Added a description - function for copying folders (so we don't get a "Working 0x..." - status message). + ** See bug #70768. - * mail-mt.c (do_op_status): Always g_free(what) since we always - strdup it. + * em-folder-browser.c (emfb_mark_all_read): get the uid list from + the message-list (view) rather than folder (model). -2005-01-20 Not Zed <NotZed@Ximian.com> + * message-list.c (message_list_foreach): removed, no longer used. + (message_list_get_uids): new function replacing ml_foreach, get + visible uids's of messages. - ** See bug #55831. +2005-01-18 Not Zed <NotZed@Ximian.com> + + * em-format-html.c (emfh_gethttp): kill old 'load http 0 now=0' debug. - * evolution-mail.schemas.in.in: added open_many prompt key. + ** See bug #70563. - * mail-errors.xml: added ask-open-many + * em-utils.c (emu_set_proxy, emu_proxy_setup) + (em_utils_get_proxy_uri): make sure the init code is called from + main thread (gconf usage), and add locking for data consistency. - * em-folder-view.c (em_folder_view_open_selected): put back the - 'you're opening too many are you sure' thing. +2005-01-08 Not Zed <NotZed@Ximian.com> -2005-01-19 Jeffrey Stedfast <fejj@novell.com> + * mail-account-gui.c (save_service): dont skip the authtype + setting if we don't have a needsauth widget at all (i.e. the store + page). - * em-folder-properties.c (emfp_get_folder_item): Increment i each - time thru the loop or we lose widgets. + * em-folder-tree.c (emft_get_folder_info__desc): fix broken cast. 2005-01-19 Not Zed <NotZed@Ximian.com> @@ -344,11 +120,6 @@ (em_utils_composer_save_draft_cb): grab resources before getting the folder, so the composer doesn't go away. -2005-01-18 Rodrigo Moya <rodrigo@novell.com> - - * em-filter-source-element.c: - * mail-config.c: removed e-url.h include. - 2005-01-18 Not Zed <NotZed@Ximian.com> ** See bug #70768. @@ -361,174 +132,20 @@ visible uids's of messages. 2005-01-18 Not Zed <NotZed@Ximian.com> - + ** See bug #71105. * em-folder-tree.c (emft_popup_rename_folder): dont let a user rename a folder to one including '/'. - * em-format-html.c (emfh_gethttp): kill old 'load http 0 now=0' debug. - - ** See bug #70563. - - * em-utils.c (emu_set_proxy, emu_proxy_setup) - (em_utils_get_proxy_uri): make sure the init code is called from - main thread (gconf usage), and add locking for data consistency. - -2005-01-14 Not Zed <NotZed@Ximian.com> - - ** Related to changes for #65178. - - * mail-vfolder.c (mv_find_folder): changed from my_list_find, take - store arg and use camel_Store_Folder_uri_equal() instead of wrong - uri_cmp function. - (mail_vfolder_delete_uri): same. - (mail_vfolder_rename_uri): same. - (uri_is_ignore): take store arg, and same as above. use the right - uri for checking sent folder. - (mail_vfolder_*): convert to storing uri's in camel form. - -2005-01-13 Not Zed <NotZed@Ximian.com> - - ** See bug #71029. - - * em-account-editor.c (emae_option_toggle): revert menjie's patch - and do it using object args. - -2005-01-12 Not Zed <NotZed@Ximian.com> - - ** See bug #70990. - - * em-account-editor.c (emae_service_url_changed): if the value is - "" then don't set it - - ** See bug #70018. - - * mail-signature-editor.c (mail_signature_editor): use the right - version for the gtkhtml editor control. - -2005-01-11 Vivek Jain <jvivek@novell.com> - - * em-folder-tree.c (render_pixbuf): Added conditions to check for - shared folders to display different icon if it is a shard folder. - -2005-01-07 Not Zed <NotZed@Ximian.com> - - * em-account-prefs.c (account_add_clicked): remove old code, setup - transient parent and weak ref for refresh. + * em-format-html.c (emfh_gethttp): kill old 'load http 0 now=0' debug. + +2004-12-01 Not Zed <NotZed@Ximian.com> -2005-01-06 JP Rosevear <jpr@novell.com> + ** See bug #69851. - * Makefile.am: install schemas properly - -2005-01-06 Jeffrey Stedfast <fejj@novell.com> - - * mail-folder-cache.c (mail_note_store): Handle the - CamelOfflineStore case just like the CamelDiscoStore case. - - * mail-ops.c (prep_offline_do): Since we can't kill off - CamelDisco* (groupwise is using it), we have to handle both - CamelOfflineFolder and CamelDiscoFolder for now. - (set_offline_do): Same. - -2005-01-05 Not Zed <NotZed@Ximian.com> - - * em-menu.c: (emph_targets[]): Add the widget target, missed this. - -2005-01-05 Not Zed <NotZed@Ximian.com> - - * em-menu.c (em_menu_target_new_widget): add a semi-dummy target - for widget target. - - * mail-component.c (handleuri_got_folder): handle the "reply" - parameter, if set. - - * em-composer-utils.c (em_utils_reply_to_message): only ref the - source if supplied. - (reply_to_message): only unref the source if supplied. - -2004-12-28 Mengjie Yu <meng-jie.yu@sun.com> - - * em-folder-tree.c: (em_folder_tree_new_with_model): - add atk name for the treeview. - -2004-12-22 Not Zed <NotZed@Ximian.com> - - * em-account-editor.c (emae_needs_auth): moved to after - emae_authtype_changed to fix warning. - -2004-12-17 Not Zed <NotZed@Ximian.com> - - * em-format-html-display.c (efhd_attachment_popup): - - * message-list.c (ml_tree_drag_data_received): - - * em-folder-view.c (emfv_popup, emfv_format_popup_event): - - * em-folder-tree.c (tree_drag_data_received): api changes. - (emft_popup): - - * em-popup.c (emp_standard_menu_factory) - (emp_standard_menu_factory): api changes. - -2004-12-21 Not Zed <NotZed@Ximian.com> - - * em-account-editor.c (emae_needs_auth): if we're turned on, then - record the current authtype setting on the widgets, if we're - turned off, clear the authmech setting. - (emae_setup_service): setup the needs auth after the authtype, and - get setting from url->authmech. - (emae_service_provider_changed): only clear the url->authmech if - we don't have the current one in our list. - -2004-12-20 Takeshi AIHANA <aihana@gnome.gr.jp> - - * default/Makefile.am: Added 'ja' and 'nl' to install. - -2004-12-14 Rodney Dawes <dobey@novell.com> - - * mail-account-gui.c: Remove this from CVS - - * mail-config.glade: Use em_account_editor_folder_selector_button_new - instead of mail_account_gui_folder_selector_button_new - -2004-12-14 JP Rosevear <jpr@novell.com> - - Fixes #68759 - - * mail-account-gui.c (service_check_supported): fix typo in - routine name - -2004-12-08 Hans Petter Jansson <hpj@novell.com> - - * importers/pine-importer.c: Include <libebook/e-destination.h> from - evolution-data-server. - -2004-12-08 Rodney Dawes <dobey@novell.com> - - * em-folder-tree.c: - * mail-component.c (impl__get_userCreatableItems): - Use stock_new-dir instead of stock_folder for "New Folder" creation - -2004-12-07 Mengjie Yu <meng-jie.yu@sun.com> - - * mail-config.glade: add mnemonic for buttons, labels, etc. - * mail-dialogs.glade:add mnemonic for buttons, labels, etc. - * message-tags.glade:add mnemonic for buttons, labels, etc. - -2004-12-08 Not Zed <NotZed@Ximian.com> - - * mail-component-factory.c (make_factory): and put them here - instead so they're available even when the mailer isn't activated - yet. - - * mail-component.c (mc_startup): remove plugin hook registrations. - -2004-11-22 Not Zed <NotZed@Ximian.com> - - * em-account-editor.c (emae_receive_options_extra_item): dont - track containee widgets anymore, they are automagically destroyed - by the container if required. + * mail-account-gui.c (save_service): dont skip the save_password + setting if we don't have a needs_auth widget. 2004-11-25 Radek Doulik <rodo@ximian.com> @@ -540,22 +157,6 @@ Fixes #69623 -2004-12-01 Mengjie Yu <meng-jie.yu@sun.com> - - * em-account-editor.c:according to the HIG, remove accelerators in - the notebook tab labels - -2004-12-01 Mengjie Yu <meng-jie.yu@sun.com> - - * em-account-editor.c: (emae_option_toggle), - (emae_receive_options_item):add mnemonic for buttons. - * em-format-html-display.c: (efhd_attachment_button):add atk name - for the popup button. - * mail-account-gui.c: (mail_account_gui_build_extra_conf):add - access key for checkbox. - * message-list.c: (message_list_construct):add a atk name for the - message list. - 2004-11-22 Not Zed <NotZed@Ximian.com> ** See bug #69339. @@ -597,87 +198,20 @@ some strcasecmp() calls changed with g_ascii_strcasecmp() for Turkish character conversiton problems [ http://www.i18nguy.com/unicode/turkish-i18n.html ] -2004-11-26 JP Rosevear <jpr@novell.com> - - * em-format.c: wrap printf's in debug defines - -2004-11-26 JP Rosevear <jpr@novell.com> - - * em-format-html-display.c (efhd_xpkcs7mime_button): get image - widget directly from icon factory - - * mail-send-recv.c (build_dialog): ditto - -2004-10-12 Radek Doulik <rodo@ximian.com> - - * em-junk-filter.c: when starting new spamd, call it with - --socketpath parameter to use unix sockets instead of opening TCP - port. kill such started daemon in finalize callback which is - installed by atexit. also try to respawn spamd in case spamc - returns error, if respawning is too fast (8 restarts in last 5 - minutes) fallback to spamassassin - - * mail-component.c (impl_quit): call mail_session_quit - - * mail-session.c (mail_session_init): call junk plugin init - (mail_session_quit): new method, called on evo exit - -2004-11-22 Joan Sanfeliu <joan@fibranet.com> - - * mail-config.glade : Evolution word spelled with an uppercase E - - Fixes #61065 - -2004-11-16 Not Zed <NotZed@Ximian.com> - - * Makefile.am: - * importers/Makefile.am: Removed camel linking. - -2004-11-15 Not Zed <NotZed@Ximian.com> - - * *.c: Moved various things from e-util to libedataserver. - - * GNOME_Evolution_Mail.server.in.in: remove the startup wizard stuff. +2004-11-10 Not Zed <NotZed@Ximian.com> - * mail-config-druid.[ch]: - * mail-account-editor.[ch]: - * mail-account-gui.[ch]: removed & deleted. + ** See bug #68794. - * mail-session.c (mail_session_init): and here too. - * em-migrate.c (em_migrate_1_4): init camel-provider library too. - (e_path_to_physical): copy from e-util/e-path.c. + * mail-account-gui.h: moved the needs_auth checkbox to the service + structure so it can be checked in save_service. removed the + transport_needs_auth field. the 'source' one is always NULL. - * Makefile.am (libevolution_mail_la_LIBADD): link to new libcamel - provider too. - -2004-11-12 Not Zed <NotZed@Ximian.com> - - * filtertypes.xml: - * vfoldertypes.xml: - * searchtypes.xml: Added 'match all' rules. - - ** Merge in notzed-messageinfo-branch. - -2004-11-11 Radek Doulik <rodo@ximian.com> - - * em-format-hook.c (emfh_enable): l = g_list_next (l); in inner - loop instead of g = g_list_next (l).. probably typo after c'n'p - - * em-format.c (em_format_class_remove_handler): in case the old - handler doesn't exist, remove 'info' handler from type_handler - table + * mail-account-gui.c (save_service): check the needs-auth checkbox + rather than the round-a-bout and functionless sensitivity check on + the widget. 2004-11-03 Not Zed <NotZed@Ximian.com> - * em-folder-view.c (emfv_popup): Fix the popup id. - -2004-11-03 Not Zed <NotZed@Ximian.com> - - * em-folder-view.c (emfv_list_done_message_selected): revert - jeff's last change - we do actually want to know when we couldn't - load a message. the crash he was fixing was fixed elsewhere. - also fix the unref ordering stuff. - * em-format-html.c (efh_format_timeout): removed the fixme i added. @@ -694,131 +228,17 @@ (em_format_part_as): track content-base (& absolute content-location) of all parts here. -2004-11-02 Not Zed <NotZed@Ximian.com> - - * em-event.c (eme_target_free, em_event_target_new_message): - handle NULL folder or message. - -2004-11-02 Jeffrey Stedfast <fejj@novell.com> - - * em-folder-view.c (emfv_list_done_message_selected): Check for - NULL messages (happens if the message isn't available). - -2004-11-02 Radek Doulik <rodo@ximian.com> - - * em-format-html.c: replace 3 nested html tables used to create - this gray border around parts content with div block with border - style - use shorthand border: property - -2004-11-01 Jeffrey Stedfast <fejj@novell.com> - - * em-account-editor.c: Change the labels back to the same as they - were in 2.0 - -2004-11-12 Not Zed <NotZed@Ximian.com> - - * mail-send-recv.c (auto_account_finalised): fix the callback - signature. - -2004-11-11 Not Zed <NotZed@Ximian.com> - - * mail-component.c (mc_add_store): - (mc_add_store_done): Let the counters know about the junk/trash - folders that have already been opened. - - * em-vfs-stream.[ch]: Added stream class to read/write gnome-vfs - data from camel. NFI if this will work, depends on how - thread-safe gnome-vfs is. - -2004-11-08 Not Zed <NotZed@Ximian.com> - - * mail-vfolder.c (uri_is_spethal): fix the special check for local - folders. - -2004-10-30 Not Zed <NotZed@Ximian.com> - - * */*.c, *.c: camel api changes. - -2004-10-28 Not Zed <NotZed@Ximian.com> - - * mail-folder-cache.c (real_flush_updates): - * em-message-browser.c (em_message_browser_new): - * em-mailer-prefs.c (em_mailer_prefs_construct): - * em-format-html-display.c (efhd_attachment_popup): - * em-folder-view.c (emfv_popup, emfv_list_done_message_selected) - (emfv_format_popup_event): - * em-folder-tree.c (emft_popup): - * em-folder-properties.c (emfp_dialog_got_folder): - * em-folder-browser.c (em_folder_browser_new): - * em-composer-utils.c (em_utils_reply_to_message): - * em-composer-prefs.c (em_composer_prefs_construct): - * em-account-editor.c (em_account_editor_construct): added hook - docs, and cleaned up some of the hook point names. - -2004-10-22 Jeffrey Stedfast <fejj@novell.com> - - * em-folder-tree.c: Give the Rename item a different path than the - Delete item. - -2004-10-22 Not Zed <NotZed@Ximian.com> - - * em-event.c (eme_target_free): duh, they're camel not gobjects. - - * em-folder-view.c (emfv_list_done_message_selected): added a - message.reading event. - -2004-10-22 Nat Friedman <nat@novell.com> - - * em-event.c: Add a REPLY_ALL flag to the Message target. - * em-composer-utils.c (em_utils_reply_to_message): Set the - REPLY_ALL flag when appropriate. - -2004-10-21 Not Zed <NotZed@Ximian.com> - - * em-composer-utils.c (em_utils_reply_to_message): emit a - 'message.replying' event with a message target. - -2004-10-21 Nat Friedman <nat@novell.com> - - * em-event.c (em_event_target_new_message): new target type for - message-related events. - -2004-10-21 Not Zed <NotZed@Ximian.com> - - * em-folder-view.c (emfv_format_popup_event): put 'evolution' back - in the popup hook names. - -2004-10-19 JP Rosevear <jpr@novell.com> - - * em-account-editor.c, em-composer-prefs.c, em-config.c, - em-event.c, em-folder-browser.c, em-folder-properties.c, - em-folder-tree.c, em-folder-view.c, em-format-hook.c, - em-format-html-display.c, em-mailer-prefs.c, em-menu.c, - em-message-browser.c, em-popup.c, message-list.c: convert to - org.gnome hook names - -2004-10-19 JP Rosevear <jpr@novell.com> - - * message-list.c: convert to G_DEFINE_TYPE - 2004-10-11 Not Zed <NotZed@Ximian.com> ** See bug #67014. - * mail-errors.xml: added "checking-service" error. - - * em-account-editor.c (em_account_editor_construct): keep track of - the dialogue - (emae_editor_destroyed): , and clean up when destroyed. - - * em-account-editor.c (emae_check_authtype) - (emae_check_authtype_response, emae_check_authtype_done): handle - checking authtype gui here. - * mail-config.c (check_service_describe, check_service_check) (check_response, mail_config_check_service): removed. + * mail-account-gui.c (service_check_supported): call + mail_check_service to do the checking async. Make the popopup + window non-modal, but de-sensitize the dialog instead. + * mail-ops.c (mail_check_service): moved here from mail-config, and modified to be a re-usable threaded function. @@ -829,23 +249,6 @@ * em-folder-view.c (emfv_init): dont ref/sink the invisible. (emfv_destroy): just destroy it here. -2004-10-15 Not Zed <NotZed@Ximian.com> - - * em-composer-utils.c (create_new_composer): - (em_utils_compose_new_message, forward_non_attached): do noting if - the composer couldn't be created. We get a popup from elsewhere - to let the user know. - -2004-10-14 Sivaiah Nallagatla <snallagatla@novell.com> - - * mail-errors.xml : Remove Pango markup from groupwise - account setup error message - -2004-10-12 Not Zed <NotZed@Ximian.com> - - * em-format-html-display.c (efhd_find_handler): use builtin - handlers (and plugins) always overriding bonobo ones. - 2004-10-11 Not Zed <NotZed@Ximian.com> ** See bug #67408. @@ -854,27 +257,10 @@ destroyed. (emfv_destroy): set destroyed bit. -2004-10-11 Not Zed <NotZed@Ximian.com> +2004-10-07 JP Rosevear <jpr@novell.com> - * mail-component.c (mc_startup): register the formatter types - before registering the formatter hook. - -2004-10-08 JP Rosevear <jpr@novell.com> - - * mail-account-gui.c (browse_clicked): use "Select a file" - -2004-10-08 Harry Lu <harry.lu@sun.com> - - * em-folder-tree.c: (em_folder_tree_class_init), (real_popup_menu), - (emft_popup_menu), (emft_tree_button_press): implement popup_menu - so that popup menu can be shown with Shift+F10 on folder tree. - * em-folder-view.c: (emfv_popup), (emfv_list_key_press): - same as above. - -2004-10-07 Not Zed <NotZed@Ximian.com> - - * mail-component.c (mc_startup): dont init the base plugin system - here anymore, only register the hook types for mail hooks. + * mail-account-gui.c (browse_clicked): use "Select a file" so as + not to break string freeze 2004-09-28 Not Zed <NotZed@Ximian.com> @@ -884,12 +270,6 @@ 2004-10-06 Not Zed <NotZed@Ximian.com> - * em-folder-tree.c (emft_get_folder_info__desc): fix busted cast. - - * *.c: e-popup api changes. - -2004-10-06 Not Zed <NotZed@Ximian.com> - * em-folder-tree.c (emft_tree_button_press): remove some debug that made it in accidentally. @@ -909,10 +289,6 @@ * em-migrate.c (upgrade_passwords_1_2): fix uninitialised pointer. -2004-09-27 Jeffrey Stedfast <fejj@novell.com> - - * em-account-editor.c: Changed the SSL option menu labels. - 2004-09-21 Not Zed <NotZed@Ximian.com> ** See bug #63521. @@ -980,6 +356,65 @@ emfv->mark_seen for deciding whether or not to mark the message as seen. Fixes bug #65448. +2004-09-08 Not Zed <NotZed@Ximian.com> + + ** See bug #60515. + + * mail-account-gui.c (sig_fill_menu): connect to the activate + signal for the none item. + +2004-09-01 Jeffrey Stedfast <fejj@novell.com> + + Fix for bug #63377 and prevention of similar cases. + + * em-format.c (emf_finalise): Free the default_charset. + (emf_format_clone): Clone the default_charset - this prevents the + particular crash described in bug #63377. + + * em-utils.c (em_utils_message_to_html): If source is NULL, set + our own default charset (from the user's gconf key) on the + formatter to make sure there's always a source charset for + conversion to UTF-8. + +2004-08-30 Jeffrey Stedfast <fejj@novell.com> + + * em-folder-tree.c (emft_popup_delete_folder): Set the store and + full_name info on the dialog. + (emft_popup_delete_response): Use the requisite data stored on the + dialog object rather than examining the selection again. Fixes bug + #62665. + +2004-08-30 Not Zed <NotZed@Ximian.com> + + ** See bug #64377. + + * em-folder-selector.c (emfs_response): only set the uri if we + have one to set. + + * em-folder-tree.c (em_folder_tree_finalize): Removed + cose using selected_path and selected_uri strings. + (emft_popup_new_folder): " + (emft_popup_copy_folder_selected): " + (emft_tree_selection_changed): + (emft_tree_row_activated): ", free paths after use. + + * em-folder-selector.c (emfs_create_name_changed): free + get_selected_uri return. + (emfs_create_name_activate): " + (em_folder_selector_get_selected_path): handle api change, store + the selected_path too. + + * em-folder-tree.c (em_folder_tree_get_selected_uri): + de-constify,and get the selection directly from the tree. + (em_folder_tree_get_selected_path): same. + +2004-08-27 Not Zed <NotZed@Ximian.com> + + ** See bug #63456. + + * message-list.c (main_folder_changed): noop if the async_event + pointer is NULL which can happen during destroy. + 2004-09-09 Jeffrey Stedfast <fejj@novell.com> * mail-account-gui.c (mail_account_gui_new): If built with @@ -1387,216 +822,6 @@ * Makefile.am (SUBDIRS): Revert previous error change -2004-09-10 Not Zed <NotZed@Ximian.com> - - * em-*: various doco updates. - - * em-format-quote.c (emfq_builtin_init): instead of removing the - type, just add an override noop. Changed api's. - -2004-09-09 Not Zed <NotZed@Ximian.com> - - * em-format.c (em_format_class_remove_handler): Change this to use - the original structure only, not by type. - - * em-format-hook.c (emfh_enable): implement hook enablation. - -2004-09-07 Not Zed <NotZed@Ximian.com> - - * em-account-editor.c (emae_setup_providers): set the provider - shown selected on the store as well. - - * mail-config.glade: moved the druid 'help text' directly into the - glade file. - - * em-account-editor.c (emae_check_complete): add pre-load for - management page options. - - * em-utils.c (em_utils_configure_account): remove use of - mail-config-druid. - - * em-account-editor.c (emae_remove_childen): removed. - (*): removed service->url, always get it from/set it to the - e-account so it doesn't have side-effects with plugins. - - * mail-dialogs.glade: fix up the names of the various license - dialog fields. - -2004-09-06 Not Zed <NotZed@Ximian.com> - - * em-account-editor.c (emae_receive_options_extra_item): store the - config widgets in the item entry itself. - (emae_auto_detect): wasted a whole lot of time on this crap. - - * em-account-prefs.c (account_able_clicked): removed some redundant logic. - - * mail-send-recv.c (mail_autoreceive_setup): renamed to - mail_autoreceive_init and rewrote all the callbacks. now it - listens to events on the accountlist directly and doesn't need - invoking manually. It also runs relative to the account always, - rather than copying the uri. Removed all callers except the mail - component one. - - * em-account-editor.c (em_account_editor_provider_selector_new): - removed becaus eof below. - (em_account_editor_construct): copy the account to a working - object if supplied, else create a new one. - - * mail-config.glade: make the provider selectors just use - em_account_editor_dropdown new for the dropdown menu. - - * em-account-editor.c (prepare_signatures): removed, merged into - the identity page code. - (sig_fill_menu): removed. - (emae_setup_signatures): new function to setup signatures on a - gtkcombobox. - (clear_menu): removed. - (signature_changed): removed. - (emae_signature_changed): new function for changed. - (signature_removed): removed. - (emae_signature_removed): new function for removed. - (emae_signature_get_iter): helper for finding the right row for - this signature. - (signature_added): removed. - (emae_signature_added): new function for added. - (sig_activate): removed. - (emae_signaturetype_changed): new function to update the account - info immediately. - (sig_add_new_signature): renamed to emae_signature_new. - (select_account_signature): no longer needed, this happens in the - setup. - - * mail-config.glade: changed the signature thing to a custom - widget (gtkcombobox). - - * em-account-editor.c (em_account_editor_construct): updates for - api change, table sections require table items. - (emae_setup_service): handle host:port hostname syntax. - (emae_hostname_changed): and here too. - (emae_commit): fill this out, and implement it. - -2004-09-04 Not Zed <NotZed@Ximian.com> - - * *.c: include gnome i18.h if needed since camel-object.h was - fixed. - - * em-format.c (em_format_class_add_handler): if a handler is - already set for type, link it in. - - * em-format.h: added a link pointer to EMFormatHanlder, so that - overrides can also fallback. remove applications member - not - used anymore. - -2004-09-01 Not Zed <NotZed@Ximian.com> - - * em-popup.h: added some docs. - - * em-popup.c (emp_standard_menu_factory): - * em-folder-tree.c (tree_drag_data_received): popup api changes. - -2004-08-31 Not Zed <NotZed@Ximian.com> - - * em-format-html-display.c (efhd_attachment_button_show): use a - wrapper for the button event since the popup event has changed - signature. - -2004-08-30 Not Zed <NotZed@Ximian.com> - - * em-popup.c (emp_standard_menu_factory): changed args. - (struct _open_in_item): removed, use user data instead. - (*): fix callbacks for new apis. - (emp_popup_open): Removed some dead popup callbacks never invoked. - (em_popup_target_new_attachments): new target type for attachment - bar in composer. - - * em-folder-tree.c (emft_popup*): convert to new e-popup apis. - - * em-folder-view.c: emfv_popup_*: convert to new e-poup callback - signatures. - (EMFV_MAP_CALLBACK): fix for e-popup callback change. - (EMFV_POPUP_AUTO_TYPE): same. - (emfv_popup): dont bother setting item callback data. - (emfv_popup_labels_free): api changes. - (emfv_popup_items_free): new free method. - (EMFVPopupItem): No longer needed. - (emfv_uri_popup_free): api changes. - (emfv_format_popup_event): new api's == simpler code. - - * em-account-editor.c (emae_receive_options_extra_item): add a - hack for the label item, which is only used by connector to - override the hostname and username labels. - -2004-08-24 Not Zed <NotZed@Ximian.com> - - * em-account-editor.c (em_account_editor_construct): create the - window rather than the widget here. - - * mail-config.glade: remove the extra_page from the druid, it is - autogenerated now. renamed the "Receiving options" notebook page - to "Receiving Email" since it isn't hte options page. - - * em-account-editor.c (emae_receive_options_page): no longer - needed, autogenerated. - (emae_receive_options_item): setup the auto-receive time values. - (emae_receive_page): don't setup the auto check time values here. - - * mail-config.glade: Remove the Receiving Mail tab, it is now - completely auto-generated. - -2004-08-17 Not Zed <NotZed@Ximian.com> - - * em-event.[ch]: mail event dispatcher. - - * mail-component.c (mc_startup): hook into events. - - * mail-folder-cache.c (update_1folder): always set the uri field. - (real_flush_updates): emit a folder.changed:new event if we have new - mail. - -2004-08-13 Not Zed <NotZed@Ximian.com> - - * mail-config.glade: replaced ssl selector with custom widget - (gtkcombobox). Giv the preferences, composer toplevel unique - names. - -2004-07-29 Not Zed <NotZed@Ximian.com> - - * mail-config.glade: replaced source and transport selector with - custom widget (gtkcombobox). - - * em-account-editor.[ch]: copy over mail-account-gui.[ch] and - rename stuff. Make a gobject. Move most internals, internal. - -2004-07-28 Not Zed <NotZed@Ximian.com> - - * em-composer-prefs.c (em_composer_prefs_construct): get the - toplevel tab as the root. - (em_composer_prefs_construct): setup plugin metadata for composer - prefs. - - * em-mailer-prefs.c (em_mailer_prefs_construct): setup plugin - metadata for mail preferences. - - * em-config.c (em_config_target_new_prefs): new target for 'prefs' - mode, everything global via gconf. - - * em-mailer-prefs.c (em_mailer_prefs_construct): get the gui from - the preferences_toplevel not the preferences_tab window which we - don't need. - - * mail-config.glade: rename the preferences 'toplevel' to - preferences_toplevel so we can get it unparented. And the - composer toplevel to composer_toplevel. - - * em-folder-properties.c (em_folder_properties_show): remove test - code. - - * em-format.h (struct _EMFormatPURI): add a free function - callback. - - * em-format.c (emf_clear_puri_node): if the free function is set, - call it. - 2004-07-01 Rodney Dawes <dobey@novell.com> * Makefile.am (BUILT_SOURCES): Remove $(error_i18n) diff --git a/mail/em-composer-prefs.c b/mail/em-composer-prefs.c index 7a3cd88beb..2867fa50e5 100644 --- a/mail/em-composer-prefs.c +++ b/mail/em-composer-prefs.c @@ -38,7 +38,7 @@ #include <bonobo/bonobo-generic-factory.h> -#include <libedataserver/e-iconv.h> +#include <gal/util/e-iconv.h> #include <gal/widgets/e-gui-utils.h> #include <gtk/gtktreemodel.h> @@ -66,7 +66,6 @@ #include "mail-config.h" #include "mail-signature-editor.h" -#include "em-config.h" #define d(x) @@ -583,6 +582,28 @@ spell_color_set (GtkWidget *widget, guint r, guint g, guint b, guint a, EMCompos gconf_client_set_int (prefs->gconf, GNOME_SPELL_GCONF_DIR "/spell_error_color_blue", b, NULL); } +static void +spell_live_toggled (GtkWidget *widget, gpointer user_data) +{ + /* FIXME: what gconf key is this? */ +} + +static void +spell_language_selection_changed (GtkTreeSelection *selection, EMComposerPrefs *prefs) +{ + GtkTreeIter iter; + GtkTreeModel *model; + gboolean state = FALSE; + + if (gtk_tree_selection_get_selected (selection, &model, &iter)) { + gtk_tree_model_get ((GtkTreeModel *) model, &iter, 0, &state, -1); + gtk_button_set_label ((GtkButton *) prefs->spell_able_button, state ? _("Disable") : _("Enable")); + state = TRUE; + } + + gtk_widget_set_sensitive (prefs->spell_able_button, state); +} + static char * spell_get_language_str (EMComposerPrefs *prefs) { @@ -619,25 +640,58 @@ spell_get_language_str (EMComposerPrefs *prefs) return rv; } -static void -spell_language_toggled (GtkCellRendererToggle *renderer, const char *path_string, EMComposerPrefs *prefs) +static void +spell_language_enable (GtkWidget *widget, EMComposerPrefs *prefs) { - GtkTreePath *path = gtk_tree_path_new_from_string (path_string); + GtkTreeIter iter; + GtkTreeModel *model; + GtkTreeSelection *selection; + gboolean state; + char *str; + + selection = gtk_tree_view_get_selection (prefs->language); + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + return; + + gtk_tree_model_get (model, &iter, 0, &state, -1); + gtk_list_store_set ((GtkListStore *) model, &iter, 0, !state, -1); + gtk_button_set_label ((GtkButton *) prefs->spell_able_button, state ? _("Enable") : _("Disable")); + + str = spell_get_language_str (prefs); + gconf_client_set_string (prefs->gconf, GNOME_SPELL_GCONF_DIR "/language", str ? str : "", NULL); + g_free (str); +} + +static gboolean +spell_language_button_press (GtkTreeView *treeview, GdkEventButton *event, EMComposerPrefs *prefs) +{ + GtkTreeViewColumn *column = NULL; + GtkTreePath *path = NULL; GtkTreeModel *model; GtkTreeIter iter; gboolean enabled; char *str; - model = gtk_tree_view_get_model (prefs->language); + if (!(gtk_tree_view_get_path_at_pos (treeview, event->x, event->y, &path, &column, NULL, NULL))) + return FALSE; + + /* FIXME: This routine should just be a "toggled" event handler on the checkbox cell renderer which + has "activatable" set. */ + + if (strcmp (gtk_tree_view_column_get_title (column), _("Enabled")) != 0) + return FALSE; + + model = gtk_tree_view_get_model (treeview); gtk_tree_model_get_iter (model, &iter, path); gtk_tree_model_get (model, &iter, 0, &enabled, -1); gtk_list_store_set ((GtkListStore *) model, &iter, 0, !enabled, -1); + gtk_button_set_label ((GtkButton *) prefs->spell_able_button, enabled ? _("Enable") : _("Disable")); str = spell_get_language_str (prefs); gconf_client_set_string (prefs->gconf, GNOME_SPELL_GCONF_DIR "/language", str ? str : "", NULL); g_free (str); - - gtk_tree_path_free (path); + + return FALSE; } static void @@ -664,6 +718,14 @@ spell_setup (EMComposerPrefs *prefs) widget = glade_xml_get_widget (prefs->gui, "colorpickerSpellCheckColor"); g_signal_connect (widget, "color_set", G_CALLBACK (spell_color_set), prefs); + + widget = glade_xml_get_widget (prefs->gui, "buttonSpellCheckEnable"); + g_signal_connect (widget, "clicked", G_CALLBACK (spell_language_enable), prefs); + + widget = glade_xml_get_widget (prefs->gui, "chkEnableSpellChecking"); + g_signal_connect (widget, "toggled", G_CALLBACK (spell_live_toggled), prefs); + + g_signal_connect (prefs->language, "button_press_event", G_CALLBACK (spell_language_button_press), prefs); } static gboolean @@ -782,36 +844,6 @@ toggle_button_init (EMComposerPrefs *prefs, GtkToggleButton *toggle, int not, co gtk_widget_set_sensitive ((GtkWidget *) toggle, FALSE); } -static GtkWidget * -emcp_widget_glade(EConfig *ec, EConfigItem *item, struct _GtkWidget *parent, struct _GtkWidget *old, void *data) -{ - EMComposerPrefs *prefs = data; - - return glade_xml_get_widget(prefs->gui, item->label); -} - -/* plugin meta-data */ -static EMConfigItem emcp_items[] = { - { E_CONFIG_BOOK, "", "composer_toplevel", emcp_widget_glade }, - { E_CONFIG_PAGE, "00.general", "vboxGeneral", emcp_widget_glade }, - { E_CONFIG_SECTION, "00.general/00.behavior", "vboxBehavior", emcp_widget_glade }, - { E_CONFIG_SECTION, "00.general/10.alerts", "vboxAlerts", emcp_widget_glade }, - { E_CONFIG_PAGE, "10.signatures", "vboxSignatures", emcp_widget_glade }, - /* signature/signatures and signature/preview parts not usable */ - - { E_CONFIG_PAGE, "20.spellcheck", "vboxSpellChecking", emcp_widget_glade }, - { E_CONFIG_SECTION, "20.spellcheck/00.languages", "vbox178", emcp_widget_glade }, - { E_CONFIG_SECTION, "20.spellcheck/00.options", "vboxOptions", emcp_widget_glade }, -}; - -static void -emcp_free(EConfig *ec, GSList *items, void *data) -{ - /* the prefs data is freed automagically */ - - g_slist_free(items); -} - static void em_composer_prefs_construct (EMComposerPrefs *prefs) { @@ -820,34 +852,24 @@ em_composer_prefs_construct (EMComposerPrefs *prefs) GladeXML *gui; GtkListStore *model; GtkTreeSelection *selection; - GtkCellRenderer *cell_renderer; int style; char *buf; - EMConfig *ec; - EMConfigTargetPrefs *target; - GSList *l; - int i; prefs->gconf = mail_config_get_gconf_client (); - gui = glade_xml_new (EVOLUTION_GLADEDIR "/mail-config.glade", "composer_toplevel", NULL); + gui = glade_xml_new (EVOLUTION_GLADEDIR "/mail-config.glade", "composer_tab", NULL); prefs->gui = gui; prefs->sig_script_gui = glade_xml_new (EVOLUTION_GLADEDIR "/mail-config.glade", "vbox_add_script_signature", NULL); - - /** @HookPoint-EMConfig: Mail Composer Preferences - * @Id: org.gnome.evolution.mail.composerPrefs - * @Type: E_CONFIG_BOOK - * @Class: org.gnome.evolution.mail.config:1.0 - * @Target: EMConfigTargetPrefs - * - * The mail composer preferences settings page. - */ - ec = em_config_new(E_CONFIG_BOOK, "org.gnome.evolution.mail.composerPrefs"); - l = NULL; - for (i=0;i<sizeof(emcp_items)/sizeof(emcp_items[0]);i++) - l = g_slist_prepend(l, &emcp_items[i]); - e_config_add_items((EConfig *)ec, l, NULL, NULL, emcp_free, prefs); - + + /* get our toplevel widget */ + toplevel = glade_xml_get_widget (gui, "toplevel"); + + /* reparent */ + gtk_widget_ref (toplevel); + gtk_container_remove (GTK_CONTAINER (toplevel->parent), toplevel); + gtk_container_add (GTK_CONTAINER (prefs), toplevel); + gtk_widget_unref (toplevel); + /* General tab */ /* Default Behavior */ @@ -884,19 +906,19 @@ em_composer_prefs_construct (EMComposerPrefs *prefs) prefs->language = GTK_TREE_VIEW (glade_xml_get_widget (gui, "listSpellCheckLanguage")); model = gtk_list_store_new (3, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_POINTER); gtk_tree_view_set_model (prefs->language, (GtkTreeModel *) model); - cell_renderer = gtk_cell_renderer_toggle_new (); gtk_tree_view_insert_column_with_attributes (prefs->language, -1, _("Enabled"), - cell_renderer, + gtk_cell_renderer_toggle_new (), "active", 0, NULL); - g_signal_connect (cell_renderer, "toggled", G_CALLBACK (spell_language_toggled), prefs); - gtk_tree_view_insert_column_with_attributes (prefs->language, -1, _("Language(s)"), gtk_cell_renderer_text_new (), "text", 1, NULL); selection = gtk_tree_view_get_selection (prefs->language); - gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); + g_signal_connect (selection, "changed", G_CALLBACK (spell_language_selection_changed), prefs); + + prefs->spell_able_button = glade_xml_get_widget (gui, "buttonSpellCheckEnable"); info_pixmap = glade_xml_get_widget (gui, "pixmapSpellInfo"); gtk_image_set_from_stock (GTK_IMAGE (info_pixmap), GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_BUTTON); if (!spell_setup_check_options (prefs)) { @@ -970,14 +992,9 @@ em_composer_prefs_construct (EMComposerPrefs *prefs) 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)); - - /* get our toplevel widget */ - target = em_config_target_new_prefs(ec, prefs->gconf); - e_config_set_target((EConfig *)ec, (EConfigTarget *)target); - toplevel = e_config_create_widget((EConfig *)ec); - gtk_container_add (GTK_CONTAINER (prefs), toplevel); } + GtkWidget * em_composer_prefs_new (void) { diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c index e7b0a7aa35..602f58b708 100644 --- a/mail/em-composer-utils.c +++ b/mail/em-composer-utils.c @@ -28,7 +28,6 @@ #include <gtk/gtkdialog.h> #include <gal/util/e-util.h> -#include <libgnome/gnome-i18n.h> #include "mail-mt.h" #include "mail-ops.h" @@ -45,7 +44,6 @@ #include "composer/e-msg-composer.h" #include "em-format-html.h" #include "em-format-quote.h" -#include "em-event.h" #include "e-util/e-account-list.h" @@ -415,8 +413,8 @@ em_utils_composer_send_cb (EMsgComposer *composer, gpointer user_data) if (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 (); + info->flags = CAMEL_MESSAGE_SEEN; send = g_malloc (sizeof (*send)); send->emcs = user_data; @@ -439,8 +437,8 @@ em_utils_composer_send_cb (EMsgComposer *composer, gpointer user_data) mail_tool_destroy_xevolution (xev); /* mail the message */ - info = camel_message_info_new(NULL); - camel_message_info_set_flags(info, CAMEL_MESSAGE_SEEN, ~0); + info = camel_message_info_new (); + info->flags = CAMEL_MESSAGE_SEEN; post_ptr = post_folders; while (post_ptr) { @@ -533,7 +531,7 @@ save_draft_done (CamelFolder *folder, CamelMimeMessage *msg, CamelMessageInfo *i g_object_unref (sdi->composer); if (sdi->emcs) emcs_unref (sdi->emcs); - camel_message_info_free(info); + g_free (info); g_free (sdi); } @@ -599,8 +597,8 @@ em_utils_composer_save_draft_cb (EMsgComposer *composer, int quit, gpointer user camel_object_ref (folder); } - info = camel_message_info_new(NULL); - camel_message_info_set_flags(info, CAMEL_MESSAGE_DRAFT | CAMEL_MESSAGE_SEEN, ~0); + info = g_malloc0(sizeof(*info)); + info->flags = CAMEL_MESSAGE_DRAFT | CAMEL_MESSAGE_SEEN; mail_append_mail (folder, msg, info, save_draft_done, sdi); camel_object_unref (folder); @@ -644,9 +642,7 @@ create_new_composer (const char *subject, const char *fromuri) EAccount *account = NULL; composer = e_msg_composer_new (); - if (composer == NULL) - return NULL; - + if (fromuri) account = mail_config_get_account_by_source_url(fromuri); @@ -669,8 +665,6 @@ em_utils_compose_new_message (const char *fromuri) GtkWidget *composer; composer = (GtkWidget *) create_new_composer ("", fromuri); - if (composer == NULL) - return; e_msg_composer_unset_changed ((EMsgComposer *)composer); e_msg_composer_drop_editor_undo ((EMsgComposer *)composer); @@ -846,10 +840,8 @@ forward_attached (CamelFolder *folder, GPtrArray *messages, CamelMimePart *part, EMsgComposer *composer; composer = create_new_composer (subject, fromuri); - if (composer == NULL) - return; - e_msg_composer_attach (composer, part); + e_msg_composer_unset_changed (composer); e_msg_composer_drop_editor_undo (composer); @@ -912,16 +904,16 @@ forward_non_attached (GPtrArray *messages, int style, const char *fromuri) if (text) { composer = create_new_composer (subject, fromuri); - if (composer) { - if (CAMEL_IS_MULTIPART(camel_medium_get_content_object((CamelMedium *)message))) - e_msg_composer_add_message_attachments(composer, message, FALSE); + if (CAMEL_IS_MULTIPART(camel_medium_get_content_object((CamelMedium *)message))) + e_msg_composer_add_message_attachments(composer, message, FALSE); - e_msg_composer_set_body_text (composer, text, len); - e_msg_composer_unset_changed (composer); - e_msg_composer_drop_editor_undo (composer); + e_msg_composer_set_body_text (composer, text, len); + + e_msg_composer_unset_changed (composer); + e_msg_composer_drop_editor_undo (composer); + + gtk_widget_show (GTK_WIDGET (composer)); - gtk_widget_show (GTK_WIDGET (composer)); - } g_free (text); } @@ -1730,8 +1722,7 @@ reply_to_message(CamelFolder *folder, const char *uid, CamelMimeMessage *message if (message != NULL) em_utils_reply_to_message(folder, uid, message, rd->mode, rd->source); - if (rd->source) - g_object_unref(rd->source); + g_object_unref(rd->source); g_free(rd); } @@ -1760,34 +1751,19 @@ em_utils_reply_to_message(CamelFolder *folder, const char *uid, CamelMimeMessage EAccount *account; const char *postto = NULL; guint32 flags; - EMEvent *eme; - EMEventTargetMessage *target; if (folder && uid && message == NULL) { struct _reply_data *rd = g_malloc0(sizeof(*rd)); rd->mode = mode; rd->source = source; - if (rd->source) - g_object_ref(rd->source); + g_object_ref(rd->source); mail_get_message(folder, uid, reply_to_message, rd, mail_thread_new); return; } g_return_if_fail(message != NULL); - - /** @Event: message.replying - * @Title: Message being replied to - * @Target: EMEventTargetMessage - * - * message.replying is emitted when a user starts replying to a message. - */ - - eme = em_event_peek(); - target = em_event_target_new_message(eme, folder, message, uid, - mode == REPLY_MODE_ALL ? EM_EVENT_MESSAGE_REPLY_ALL : 0); - e_event_emit((EEvent *)eme, "message.replying", (EEventTarget *)target); account = guess_account (message, folder); flags = CAMEL_MESSAGE_ANSWERED | CAMEL_MESSAGE_SEEN; diff --git a/mail/em-folder-browser.c b/mail/em-folder-browser.c index c0b9d92529..ded2ace97f 100644 --- a/mail/em-folder-browser.c +++ b/mail/em-folder-browser.c @@ -60,7 +60,7 @@ #include <bonobo/bonobo-ui-util.h> /* for efilterbar stuff */ -#include <libedataserver/e-sexp.h> +#include <e-util/e-sexp.h> #include "mail-vfolder.h" #include "em-vfolder-rule.h" #include <widgets/misc/e-filter-bar.h> @@ -74,7 +74,6 @@ #include "em-folder-browser.h" #include "em-folder-properties.h" #include "em-subscribe-editor.h" -#include "em-menu.h" #include "message-list.h" #include "mail-component.h" @@ -102,8 +101,6 @@ struct _EMFolderBrowserPrivate { char *select_uid; guint folder_changed_id; - - EMMenu *menu; /* toplevel menu manager */ }; static void emfb_activate(EMFolderView *emfv, BonoboUIComponent *uic, int state); @@ -130,7 +127,7 @@ static ESearchBarItem emfb_search_items[] = { E_FILTERBAR_SAVE, E_FILTERBAR_EDIT, { NULL, 0, NULL }, - { N_("Create _vFolder From Search..."), ESB_SAVE, NULL }, + { N_("Create _Virtual Folder From Search..."), ESB_SAVE, NULL }, { NULL, -1, NULL } }; @@ -291,15 +288,6 @@ 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. - */ - ((EMFolderView *)emfb)->menu = em_menu_new("org.gnome.evolution.mail.browser"); - return (GtkWidget *)emfb; } diff --git a/mail/em-folder-properties.c b/mail/em-folder-properties.c index e4e50b8aeb..c4baa983b8 100644 --- a/mail/em-folder-properties.c +++ b/mail/em-folder-properties.c @@ -40,10 +40,8 @@ #include <camel/camel-folder.h> #include <camel/camel-vee-folder.h> -#include <libgnome/gnome-i18n.h> #include "em-folder-properties.h" -#include "em-config.h" #include "mail-component.h" #include "mail-ops.h" @@ -54,32 +52,19 @@ struct _prop_data { void *object; CamelArgV *argv; GtkWidget **widgets; - - GSList *properties; - char *name; - int total; - int unread; - EMConfig *config; }; static void emfp_dialog_response (GtkWidget *dialog, int response, struct _prop_data *prop_data) { - if (response == GTK_RESPONSE_OK) - e_config_commit((EConfig *)prop_data->config); - else - e_config_abort((EConfig *)prop_data->config); - - gtk_widget_destroy (dialog); -} - -static void -emfp_commit(EConfig *ec, GSList *items, void *data) -{ - struct _prop_data *prop_data = data; CamelArgV *argv = prop_data->argv; int i; + if (response != GTK_RESPONSE_OK) { + gtk_widget_destroy (dialog); + return; + } + for (i = 0; i < argv->argc; i++) { CamelArg *arg = &argv->argv[i]; @@ -98,75 +83,144 @@ emfp_commit(EConfig *ec, GSList *items, void *data) } camel_object_setv (prop_data->object, NULL, argv); + gtk_widget_destroy (dialog); } static void -emfp_free(EConfig *ec, GSList *items, void *data) +emfp_dialog_free (void *data) { struct _prop_data *prop_data = data; int i; - g_slist_free(items); - for (i = 0; i < prop_data->argv->argc; i++) { if ((prop_data->argv->argv[i].tag & CAMEL_ARG_TYPE) == CAMEL_ARG_STR) g_free (prop_data->argv->argv[i].ca_str); } - - camel_object_free (prop_data->object, CAMEL_FOLDER_PROPERTIES, prop_data->properties); - camel_object_free (prop_data->object, CAMEL_FOLDER_NAME, prop_data->name); camel_object_unref (prop_data->object); g_free (prop_data->argv); - g_free (prop_data); } -static GtkWidget * -emfp_get_folder_item(EConfig *ec, EConfigItem *item, struct _GtkWidget *parent, struct _GtkWidget *old, void *data) +static void +emfp_dialog_got_folder (char *uri, CamelFolder *folder, void *data) { + GtkWidget *dialog, *w, *table, *label, *vbox, *hbox; + struct _prop_data *prop_data; + CamelArgGetV *arggetv; + CamelArgV *argv; + GSList *list, *l; + gint32 count, i; + char *name, *title; char countstr[16]; - GtkWidget *w, *table, *label; - struct _prop_data *prop_data = data; - int row = 0, i; - GSList *l; + int row = 0, total=0, unread=0; + + if (folder == NULL) + return; + + camel_object_get (folder, NULL, CAMEL_FOLDER_PROPERTIES, &list, CAMEL_FOLDER_NAME, &name, + CAMEL_FOLDER_TOTAL, &total, CAMEL_FOLDER_UNREAD, &unread, NULL); + + 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); + gtk_window_set_default_size ((GtkWindow *) dialog, 192, 160); + gtk_widget_ensure_style (dialog); + gtk_container_set_border_width ((GtkContainer *) ((GtkDialog *) dialog)->vbox, 0); + gtk_container_set_border_width ((GtkContainer *) ((GtkDialog *) dialog)->vbox, 12); + + vbox = gtk_vbox_new (FALSE, 12); + gtk_container_set_border_width ((GtkContainer *) vbox, 12); + gtk_box_pack_start ((GtkBox *) ((GtkDialog *) dialog)->vbox, vbox, TRUE, TRUE, 0); + gtk_widget_show (vbox); + + if (folder->parent_store == mail_component_peek_local_store(NULL) + && (!strcmp(name, "Drafts") + || !strcmp(name, "Inbox") + || !strcmp(name, "Outbox") + || !strcmp(name, "Sent"))) + title = g_strdup_printf("<b>%s</b>", _(name)); + else + title = g_strdup_printf ("<b>%s</b>", name); - if (old) - return old; + label = gtk_label_new (title); + gtk_label_set_use_markup ((GtkLabel *) label, TRUE); + gtk_misc_set_alignment ((GtkMisc *) label, 0.0, 0.5); + gtk_box_pack_start ((GtkBox *) vbox, label, FALSE, FALSE, 0); + gtk_widget_show (label); + g_free (title); + + hbox = gtk_hbox_new (FALSE, 12); + gtk_box_pack_start ((GtkBox *) vbox, hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + label = gtk_label_new (""); + gtk_box_pack_start ((GtkBox *) hbox, label, FALSE, FALSE, 0); + gtk_widget_show (label); - table = gtk_table_new (g_slist_length (prop_data->properties) + 2, 2, FALSE); + /* TODO: maybe we want some basic properties here, like message counts/approximate size/etc */ + table = gtk_table_new (g_slist_length (list) + 2, 2, FALSE); gtk_table_set_row_spacings ((GtkTable *) table, 6); gtk_table_set_col_spacings ((GtkTable *) table, 12); gtk_widget_show (table); - gtk_box_pack_start ((GtkBox *) parent, table, TRUE, TRUE, 0); + gtk_box_pack_start ((GtkBox *) hbox, table, TRUE, TRUE, 0); /* TODO: can this be done in a loop? */ - label = gtk_label_new (ngettext ("Total message:", "Total messages:", prop_data->total)); + label = gtk_label_new (ngettext ("Total message:", "Total messages:", total)); gtk_widget_show (label); gtk_misc_set_alignment ((GtkMisc *) label, 0.0, 0.5); gtk_table_attach ((GtkTable *) table, label, 0, 1, row, row+1, GTK_FILL, 0, 0, 0); - sprintf(countstr, "%d", prop_data->total); + sprintf(countstr, "%d", total); label = gtk_label_new (countstr); gtk_widget_show (label); gtk_misc_set_alignment ((GtkMisc *) label, 1.0, 0.5); gtk_table_attach ((GtkTable *) table, label, 1, 2, row, row+1, GTK_FILL | GTK_EXPAND, 0, 0, 0); row++; - label = gtk_label_new (ngettext ("Unread message:", "Unread messages:", prop_data->unread)); + label = gtk_label_new (ngettext ("Unread message:", "Unread messages:", unread)); gtk_widget_show (label); gtk_misc_set_alignment ((GtkMisc *) label, 0.0, 0.5); gtk_table_attach ((GtkTable *) table, label, 0, 1, row, row+1, GTK_FILL, 0, 0, 0); - sprintf(countstr, "%d", prop_data->unread); + sprintf(countstr, "%d", unread); label = gtk_label_new (countstr); gtk_widget_show (label); gtk_misc_set_alignment ((GtkMisc *) label, 1.0, 0.5); gtk_table_attach ((GtkTable *) table, label, 1, 2, row, row+1, GTK_FILL | GTK_EXPAND, 0, 0, 0); row++; + /* build an arggetv/argv to retrieve/store the results */ + count = g_slist_length (list); + arggetv = g_malloc0 (sizeof (*arggetv) + (count - CAMEL_ARGV_MAX) * sizeof (arggetv->argv[0])); + arggetv->argc = count; + argv = g_malloc0 (sizeof (*argv) + (count - CAMEL_ARGV_MAX) * sizeof (argv->argv[0])); + argv->argc = count; + + i = 0; + l = list; + while (l) { + CamelProperty *prop = l->data; + + argv->argv[i].tag = prop->tag; + arggetv->argv[i].tag = prop->tag; + arggetv->argv[i].ca_ptr = &argv->argv[i].ca_ptr; + + l = l->next; + i++; + } + + camel_object_getv (folder, NULL, arggetv); + g_free (arggetv); + + prop_data = g_malloc0 (sizeof (*prop_data)); + prop_data->widgets = g_malloc0 (sizeof (prop_data->widgets[0]) * count); + prop_data->argv = argv; + /* setup the ui with the values retrieved */ - l = prop_data->properties; + l = list; i = 0; while (l) { CamelProperty *prop = l->data; @@ -174,7 +228,7 @@ emfp_get_folder_item(EConfig *ec, EConfigItem *item, struct _GtkWidget *parent, switch (prop->tag & CAMEL_ARG_TYPE) { case CAMEL_ARG_BOO: w = gtk_check_button_new_with_label (prop->description); - gtk_toggle_button_set_active ((GtkToggleButton *) w, prop_data->argv->argv[i].ca_int != 0); + gtk_toggle_button_set_active ((GtkToggleButton *) w, argv->argv[i].ca_int != 0); gtk_widget_show (w); gtk_table_attach ((GtkTable *) table, w, 0, 2, row, row + 1, GTK_FILL | GTK_EXPAND, 0, 0, 0); prop_data->widgets[i] = w; @@ -187,10 +241,10 @@ emfp_get_folder_item(EConfig *ec, EConfigItem *item, struct _GtkWidget *parent, w = gtk_entry_new (); gtk_widget_show (w); - if (prop_data->argv->argv[i].ca_str) { - gtk_entry_set_text ((GtkEntry *) w, prop_data->argv->argv[i].ca_str); - camel_object_free (prop_data->object, prop_data->argv->argv[i].tag, prop_data->argv->argv[i].ca_str); - prop_data->argv->argv[i].ca_str = NULL; + if (argv->argv[i].ca_str) { + gtk_entry_set_text ((GtkEntry *) w, argv->argv[i].ca_str); + camel_object_free (folder, argv->argv[i].tag, argv->argv[i].ca_str); + argv->argv[i].ca_str = NULL; } gtk_table_attach ((GtkTable *) table, w, 1, 2, row, row + 1, GTK_FILL | GTK_EXPAND, 0, 0, 0); prop_data->widgets[i] = w; @@ -202,112 +256,18 @@ emfp_get_folder_item(EConfig *ec, EConfigItem *item, struct _GtkWidget *parent, row++; l = l->next; - i++; } - - return table; -} - -#define EMFP_FOLDER_SECTION (2) - -static EMConfigItem emfp_items[] = { - { E_CONFIG_BOOK, "", NULL }, - { E_CONFIG_PAGE, "00.general", N_("General") }, - { E_CONFIG_SECTION, "00.general/00.folder", NULL /* set by code */ }, - { E_CONFIG_ITEM, "00.general/00.folder/00.info", NULL, emfp_get_folder_item }, -}; - -static void -emfp_dialog_got_folder (char *uri, CamelFolder *folder, void *data) -{ - GtkWidget *dialog, *w; - struct _prop_data *prop_data; - GSList *l; - gint32 count, i; - EMConfig *ec; - EMConfigTargetFolder *target; - CamelArgGetV *arggetv; - CamelArgV *argv; - - if (folder == NULL) - return; - - prop_data = g_malloc0 (sizeof (*prop_data)); + prop_data->object = folder; camel_object_ref (folder); - - camel_object_get (folder, NULL, CAMEL_FOLDER_PROPERTIES, &prop_data->properties, CAMEL_FOLDER_NAME, &prop_data->name, - CAMEL_FOLDER_TOTAL, &prop_data->total, CAMEL_FOLDER_UNREAD, &prop_data->unread, NULL); - - if (folder->parent_store == mail_component_peek_local_store(NULL) - && (!strcmp(prop_data->name, "Drafts") - || !strcmp(prop_data->name, "Inbox") - || !strcmp(prop_data->name, "Outbox") - || !strcmp(prop_data->name, "Sent"))) - emfp_items[EMFP_FOLDER_SECTION].label = _(prop_data->name); - else - emfp_items[EMFP_FOLDER_SECTION].label = prop_data->name; - - count = g_slist_length (prop_data->properties); - - prop_data->widgets = g_malloc0 (sizeof (prop_data->widgets[0]) * count); - - /* build an arggetv/argv to retrieve/store the results */ - argv = g_malloc0 (sizeof (*argv) + (count - CAMEL_ARGV_MAX) * sizeof (argv->argv[0])); - argv->argc = count; - arggetv = g_malloc0 (sizeof (*arggetv) + (count - CAMEL_ARGV_MAX) * sizeof (arggetv->argv[0])); - arggetv->argc = count; - i = 0; - l = prop_data->properties; - while (l) { - CamelProperty *prop = l->data; - - argv->argv[i].tag = prop->tag; - arggetv->argv[i].tag = prop->tag; - arggetv->argv[i].ca_ptr = &argv->argv[i].ca_ptr; - - l = l->next; - i++; - } + camel_object_free (folder, CAMEL_FOLDER_PROPERTIES, list); + camel_object_free (folder, CAMEL_FOLDER_NAME, name); - camel_object_getv (prop_data->object, NULL, arggetv); - 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); - gtk_window_set_default_size ((GtkWindow *) dialog, 192, 160); - gtk_widget_ensure_style (dialog); - gtk_container_set_border_width ((GtkContainer *) ((GtkDialog *) dialog)->vbox, 12); - - /** @HookPoint-EMConfig: Folder Properties Window - * @Id: org.gnome.evolution.mail.folderConfig - * @Type: E_CONFIG_BOOK - * @Class: org.gnome.evolution.mail.config:1.0 - * @Target: EMConfigTargetFolder - * - * The folder properties window. - */ - ec = em_config_new(E_CONFIG_BOOK, "org.gnome.evolution.mail.folderConfig"); - prop_data->config = ec; - l = NULL; - for (i=0;i<sizeof(emfp_items)/sizeof(emfp_items[0]);i++) - 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); - e_config_set_target((EConfig *)ec, (EConfigTarget *)target); - w = e_config_create_widget((EConfig *)ec); - - gtk_box_pack_start ((GtkBox *) ((GtkDialog *) dialog)->vbox, w, TRUE, TRUE, 0); - /* we do 'apply on ok' ... since instant apply may apply some very long running tasks */ g_signal_connect (dialog, "response", G_CALLBACK (emfp_dialog_response), prop_data); + g_object_set_data_full ((GObject *) dialog, "e-prop-data", prop_data, emfp_dialog_free); gtk_widget_show (dialog); } diff --git a/mail/em-folder-selector.c b/mail/em-folder-selector.c index 69f4662d79..1b3af98192 100644 --- a/mail/em-folder-selector.c +++ b/mail/em-folder-selector.c @@ -108,15 +108,7 @@ em_folder_selector_init (EMFolderSelector *emfs) static void em_folder_selector_destroy (GtkObject *obj) { - 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; - } - + /*EMFolderSelector *emfs = (EMFolderSelector *) obj;*/ GTK_OBJECT_CLASS (parent_class)->destroy (obj); } @@ -127,31 +119,11 @@ em_folder_selector_finalize (GObject *obj) g_free (emfs->selected_path); g_free (emfs->selected_uri); - g_free (emfs->created_uri); G_OBJECT_CLASS (parent_class)->finalize (obj); } static void -folder_created_cb (EMFolderTreeModel *model, const char *path, const char *uri, EMFolderSelector *emfs) -{ - CamelException ex; - CamelStore *store; - - camel_exception_init (&ex); - if (!(store = (CamelStore *) camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, &ex))) - return; - - if (camel_store_folder_uri_equal (store, emfs->created_uri, uri)) { - em_folder_tree_set_selected (emfs->emft, uri); - g_signal_handler_disconnect (model, emfs->created_id); - emfs->created_id = 0; - } - - camel_object_unref (store); -} - -static void emfs_response (GtkWidget *dialog, int response, EMFolderSelector *emfs) { EMFolderTreeModel *model; @@ -172,14 +144,8 @@ emfs_response (GtkWidget *dialog, int response, EMFolderSelector *emfs) if (gtk_dialog_run ((GtkDialog *) dialog) == GTK_RESPONSE_OK) { uri = em_folder_selector_get_selected_uri ((EMFolderSelector *) dialog); path = em_folder_selector_get_selected_path ((EMFolderSelector *) dialog); - - g_free (emfs->created_uri); - emfs->created_uri = g_strdup (uri); - - if (emfs->created_id == 0) - emfs->created_id = g_signal_connect (model, "folder-added", G_CALLBACK (folder_created_cb), emfs); - em_folder_tree_create_folder (emfs->emft, path, uri); + em_folder_tree_set_selected(emfs->emft, uri); } gtk_widget_destroy (dialog); diff --git a/mail/em-folder-selector.h b/mail/em-folder-selector.h index 9d282dd77b..c33017ed20 100644 --- a/mail/em-folder-selector.h +++ b/mail/em-folder-selector.h @@ -49,9 +49,6 @@ struct _EMFolderSelector { struct _GtkEntry *name_entry; char *selected_path; char *selected_uri; - - char *created_uri; - guint created_id; }; struct _EMFolderSelectorClass { diff --git a/mail/em-folder-tree-model.c b/mail/em-folder-tree-model.c index 40cf8de1e9..33c3c97843 100644 --- a/mail/em-folder-tree-model.c +++ b/mail/em-folder-tree-model.c @@ -20,6 +20,7 @@ * */ + #ifdef HAVE_CONFIG_H #include <config.h> #endif @@ -37,7 +38,6 @@ #include <e-util/e-mktemp.h> #include <gal/util/e-xml-utils.h> -#include <libgnome/gnome-i18n.h> #include <camel/camel-file-utils.h> @@ -184,23 +184,22 @@ sort_cb (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data char *aname, *bname; CamelStore *store; gboolean is_store; - 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); + COL_STRING_DISPLAY_NAME, &aname, -1); + gtk_tree_model_get (model, b, COL_STRING_DISPLAY_NAME, &bname, -1); if (is_store) { - /* On This Computer is always first and vFolders is always last */ + /* On This Computer is always first and VFolders is always last */ if (!strcmp (aname, _("On This Computer"))) rv = -1; else if (!strcmp (bname, _("On This Computer"))) rv = 1; - else if (!strcmp (aname, _("vFolders"))) + else if (!strcmp (aname, _("VFolders"))) rv = 1; - else if (!strcmp (bname, _("vFolders"))) + else if (!strcmp (bname, _("VFolders"))) rv = -1; } else if (store == vfolder_store) { /* UNMATCHED is always last */ @@ -210,9 +209,9 @@ sort_cb (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data rv = -1; } else { /* Inbox is always first */ - if ((aflags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_INBOX) + if (aname && (!strcmp (aname, "INBOX") || !strcmp (aname, _("Inbox")))) rv = -1; - else if ((bflags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_INBOX) + else if (bname && (!strcmp (bname, "INBOX") || !strcmp (bname, _("Inbox")))) rv = 1; } @@ -331,7 +330,7 @@ em_folder_tree_model_load_state (EMFolderTreeModel *model, const char *filename) if (stat (filename, &st) == 0 && (model->state = xmlParseFile (filename))) return; - /* setup some defaults - expand "Local Folders" and "vFolders" */ + /* setup some defaults - expand "Local Folders" and "VFolders" */ model->state = xmlNewDoc ("1.0"); root = xmlNewDocNode (model->state, NULL, "tree-state", NULL); xmlDocSetRootElement (model->state, root); @@ -415,6 +414,16 @@ account_removed (EAccountList *accounts, EAccount *account, gpointer user_data) em_folder_tree_model_remove_store (model, si->store); } +/* NB: more-or-less copied from em-folder-tree.c */ +static gboolean +emft_is_special_local_folder(CamelStore *store, const char *name) +{ + /* Bit of a hack to translate local mailbox names */ + return store == mail_component_peek_local_store(NULL) + && (!strcmp (name, "Drafts") || !strcmp (name, "Inbox") + || !strcmp (name, "Outbox") || !strcmp (name, "Sent")); +} + void em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *iter, struct _EMFolderTreeModelStoreInfo *si, @@ -428,7 +437,6 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *ite struct _CamelFolder *folder; gboolean emitted = FALSE; const char *name; - guint32 flags; if (!fully_loaded) load = fi->child == NULL && !(fi->flags & (CAMEL_FOLDER_NOCHILDREN | CAMEL_FOLDER_NOINFERIORS)); @@ -460,22 +468,10 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *ite camel_object_unref(folder); } - /* 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 (!strcmp(fi->full_name, "Drafts")) { - name = _("Drafts"); - } else if (!strcmp(fi->full_name, "Inbox")) { - flags = (flags & ~CAMEL_FOLDER_TYPE_MASK) | CAMEL_FOLDER_TYPE_INBOX; - name = _("Inbox"); - } else if (!strcmp(fi->full_name, "Outbox")) { - flags = (flags & ~CAMEL_FOLDER_TYPE_MASK) | CAMEL_FOLDER_TYPE_OUTBOX; - name = _("Outbox"); - } else if (!strcmp(fi->full_name, "Sent")) { - name = _("Sent"); - } - } + if (emft_is_special_local_folder(si->store, fi->full_name)) + name = _(fi->name); + else + name = fi->name; gtk_tree_store_set ((GtkTreeStore *) model, iter, COL_STRING_DISPLAY_NAME, name, @@ -483,7 +479,7 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *ite COL_STRING_FULL_NAME, fi->full_name, COL_STRING_URI, fi->uri, COL_UINT_UNREAD, unread, - COL_UINT_FLAGS, flags, + COL_UINT_FLAGS, fi->flags, COL_BOOL_IS_STORE, FALSE, COL_BOOL_LOAD_SUBDIRS, load, -1); diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c index 7bc32e5568..1c6d71d854 100644 --- a/mail/em-folder-tree.c +++ b/mail/em-folder-tree.c @@ -37,7 +37,6 @@ #include <gtk/gtk.h> #include <gdk-pixbuf/gdk-pixbuf.h> -#include <libgnome/gnome-i18n.h> #include <camel/camel-session.h> #include <camel/camel-store.h> @@ -88,8 +87,6 @@ struct _EMFolderTreePrivate { GHashTable *select_uris_table; /*Removed as they're encountered, so use this to find uri's not presnet but selected */ guint32 excluded; - gboolean (*excluded_func)(EMFolderTree *emft, GtkTreeModel *model, GtkTreeIter *iter, void *data); - void *excluded_data; int do_multiselect:1; /* multiple select mode */ int cursor_set:1; /* set to TRUE means we or something @@ -165,7 +162,6 @@ static void emft_tree_row_expanded (GtkTreeView *treeview, GtkTreeIter *root, Gt static gboolean emft_tree_button_press (GtkTreeView *treeview, GdkEventButton *event, EMFolderTree *emft); static void emft_tree_selection_changed (GtkTreeSelection *selection, EMFolderTree *emft); static gboolean emft_tree_user_event (GtkTreeView *treeview, GdkEvent *e, EMFolderTree *emft); -static gboolean emft_popup_menu (GtkWidget *widget); struct _emft_selection_data { GtkTreeModel *model; @@ -204,14 +200,11 @@ em_folder_tree_class_init (EMFolderTreeClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); parent_class = g_type_class_ref (GTK_TYPE_VBOX); object_class->finalize = em_folder_tree_finalize; gtk_object_class->destroy = em_folder_tree_destroy; - - widget_class->popup_menu = emft_popup_menu; signals[FOLDER_SELECTED] = g_signal_new ("folder-selected", @@ -266,8 +259,6 @@ enum { FOLDER_ICON_OUTBOX, FOLDER_ICON_TRASH, FOLDER_ICON_JUNK, - FOLDER_ICON_SHARED_TO_ME, - FOLDER_ICON_SHARED_BY_ME, FOLDER_ICON_LAST }; @@ -280,7 +271,7 @@ render_pixbuf (GtkTreeViewColumn *column, GtkCellRenderer *renderer, static gboolean initialised = FALSE; GdkPixbuf *pixbuf = NULL; gboolean is_store; - guint32 flags; + char *full_name; if (!initialised) { folder_icons[FOLDER_ICON_NORMAL] = e_icon_factory_get_icon ("stock_folder", E_ICON_SIZE_MENU); @@ -288,38 +279,27 @@ render_pixbuf (GtkTreeViewColumn *column, GtkCellRenderer *renderer, folder_icons[FOLDER_ICON_OUTBOX] = e_icon_factory_get_icon ("stock_outbox", E_ICON_SIZE_MENU); folder_icons[FOLDER_ICON_TRASH] = e_icon_factory_get_icon ("stock_delete", E_ICON_SIZE_MENU); folder_icons[FOLDER_ICON_JUNK] = e_icon_factory_get_icon ("stock_spam", 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); 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: + gtk_tree_model_get (model, iter, COL_STRING_FULL_NAME, &full_name, + COL_BOOL_IS_STORE, &is_store, -1); + + if (!is_store && full_name != NULL) { + if (!g_ascii_strcasecmp (full_name, "Inbox")) pixbuf = folder_icons[FOLDER_ICON_INBOX]; - break; - case CAMEL_FOLDER_TYPE_OUTBOX: + else if (!g_ascii_strcasecmp (full_name, "Outbox")) pixbuf = folder_icons[FOLDER_ICON_OUTBOX]; - break; - case CAMEL_FOLDER_TYPE_TRASH: + else if (!strcmp (full_name, CAMEL_VTRASH_NAME)) pixbuf = folder_icons[FOLDER_ICON_TRASH]; - break; - case CAMEL_FOLDER_TYPE_JUNK: + else if (!strcmp (full_name, CAMEL_VJUNK_NAME)) pixbuf = folder_icons[FOLDER_ICON_JUNK]; - 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 - pixbuf = folder_icons[FOLDER_ICON_NORMAL]; - } + else + pixbuf = folder_icons[FOLDER_ICON_NORMAL]; } - + g_object_set (renderer, "pixbuf", pixbuf, "visible", !is_store, NULL); + g_free (full_name); } static void @@ -362,15 +342,12 @@ emft_select_func(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath * GtkTreeIter iter; /* NB: This will be called with selection==NULL from tree_row_activated */ - if (emft->priv->excluded == 0 && emft->priv->excluded_func == NULL) + if (emft->priv->excluded == 0) return TRUE; if (!gtk_tree_model_get_iter(model, &iter, path)) return TRUE; - if (emft->priv->excluded_func != NULL) - return emft->priv->excluded_func(emft, model, &iter, emft->priv->excluded_data); - gtk_tree_model_get(model, &iter, COL_UINT_FLAGS, &flags, COL_BOOL_IS_STORE, &is_store, -1); if (is_store) flags |= CAMEL_FOLDER_NOSELECT; @@ -673,7 +650,6 @@ GtkWidget * em_folder_tree_new_with_model (EMFolderTreeModel *model) { EMFolderTree *emft; - AtkObject *a11y; emft = g_object_new (EM_TYPE_FOLDER_TREE, NULL); em_folder_tree_construct (emft, model); @@ -683,9 +659,6 @@ 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)); - atk_object_set_name (a11y, _("Mail Folder Tree")); return (GtkWidget *) emft; } @@ -1014,48 +987,36 @@ tree_drag_data_action(struct _DragDataReceivedAsync *m) } static void -emft_drop_popup_copy(EPopup *ep, EPopupItem *item, void *data) +emft_drop_popup_copy(GtkWidget *item, struct _DragDataReceivedAsync *m) { - struct _DragDataReceivedAsync *m = data; - m->action = GDK_ACTION_COPY; tree_drag_data_action(m); } static void -emft_drop_popup_move(EPopup *ep, EPopupItem *item, void *data) +emft_drop_popup_move(GtkWidget *item, struct _DragDataReceivedAsync *m) { - struct _DragDataReceivedAsync *m = data; - m->action = GDK_ACTION_MOVE; tree_drag_data_action(m); } static void -emft_drop_popup_cancel(EPopup *ep, EPopupItem *item, void *data) +emft_drop_popup_cancel(GtkWidget *item, struct _DragDataReceivedAsync *m) { - struct _DragDataReceivedAsync *m = data; - m->aborted = TRUE; mail_msg_free(&m->msg); } -static EPopupItem emft_drop_popup_menu[] = { - { E_POPUP_ITEM, "00.emc.00", N_("_Copy to Folder"), emft_drop_popup_copy, NULL, NULL, 1 }, - { E_POPUP_ITEM, "00.emc.01", N_("_Move to Folder"), emft_drop_popup_move, NULL, NULL, 1 }, - { E_POPUP_ITEM, "00.emc.02", N_("_Copy"), emft_drop_popup_copy, NULL, "stock_folder-copy", 2 }, - { E_POPUP_ITEM, "00.emc.03", N_("_Move"), emft_drop_popup_move, NULL, "stock_folder-move", 2 }, - { E_POPUP_BAR, "10.emc" }, - { E_POPUP_ITEM, "99.emc.00", N_("Cancel _Drag"), emft_drop_popup_cancel, NULL, "stock_cancel", 0 }, +static EMPopupItem emft_drop_popup_menu[] = { + { EM_POPUP_ITEM, "00.emc.00", N_("_Copy to Folder"), G_CALLBACK (emft_drop_popup_copy), NULL, NULL, 1 }, + { EM_POPUP_ITEM, "00.emc.01", N_("_Move to Folder"), G_CALLBACK (emft_drop_popup_move), NULL, NULL, 1 }, + { EM_POPUP_ITEM, "00.emc.02", N_("_Copy"), G_CALLBACK (emft_drop_popup_copy), NULL, "stock_folder-copy", 2 }, + { EM_POPUP_ITEM, "00.emc.03", N_("_Move"), G_CALLBACK (emft_drop_popup_move), NULL, "stock_folder-move", 2 }, + { EM_POPUP_BAR, "10.emc" }, + { EM_POPUP_ITEM, "99.emc.00", N_("Cancel _Drag"), G_CALLBACK (emft_drop_popup_cancel), NULL, "stock_cancel", 0 }, }; static void -emft_drop_popup_free(EPopup *ep, GSList *items, void *data) -{ - g_slist_free(items); -} - -static void tree_drag_data_received(GtkWidget *widget, GdkDragContext *context, int x, int y, GtkSelectionData *selection, guint info, guint time, EMFolderTree *emft) { struct _EMFolderTreePrivate *priv = emft->priv; @@ -1114,20 +1075,22 @@ tree_drag_data_received(GtkWidget *widget, GdkDragContext *context, int x, int y GSList *menus = NULL; GtkMenu *menu; - emp = em_popup_new("org.gnome.mail.storageset.popup.drop"); + emp = em_popup_new("com.ximian.mail.storageset.popup.drop"); if (info != DND_DROP_TYPE_FOLDER) mask = ~1; else mask = ~2; for (i=0;i<sizeof(emft_drop_popup_menu)/sizeof(emft_drop_popup_menu[0]);i++) { - EPopupItem *item = &emft_drop_popup_menu[i]; + EMPopupItem *item = &emft_drop_popup_menu[i]; - if ((item->visible & mask) == 0) + if ((item->mask & mask) == 0) { + item->activate_data = m; menus = g_slist_append(menus, item); + } } - e_popup_add_items((EPopup *)emp, menus, NULL, emft_drop_popup_free, m); - menu = e_popup_create_menu_once((EPopup *)emp, NULL, mask); + em_popup_add_items(emp, menus, (GDestroyNotify)g_slist_free); + menu = em_popup_create_menu_once(emp, NULL, mask, mask); gtk_menu_popup(menu, NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time()); } else { tree_drag_data_action(m); @@ -1571,12 +1534,6 @@ void em_folder_tree_set_excluded(EMFolderTree *emft, guint32 flags) emft->priv->excluded = flags; } -void em_folder_tree_set_excluded_func(EMFolderTree *emft, EMFTExcludeFunc exclude, void *data) -{ - emft->priv->excluded_func = exclude; - emft->priv->excluded_data = data; -} - GList * em_folder_tree_get_selected_uris (EMFolderTree *emft) { @@ -2015,14 +1972,6 @@ struct _EMCopyFolders { int delete; }; -static char * -emft_copy_folders__desc (struct _mail_msg *mm, int complete) -{ - struct _EMCopyFolders *m = (struct _EMCopyFolders *) mm; - - return g_strdup_printf (_("Copying `%s' to `%s'"), m->frombase, m->tobase); -} - static void emft_copy_folders__copy (struct _mail_msg *mm) { @@ -2160,7 +2109,7 @@ emft_copy_folders__free (struct _mail_msg *mm) } static struct _mail_msg_op copy_folders_op = { - emft_copy_folders__desc, + NULL, emft_copy_folders__copy, NULL, emft_copy_folders__free, @@ -2226,10 +2175,10 @@ emft_popup_copy_folder_selected (const char *uri, void *data) if (!(tostore = camel_session_get_store (session, uri, &ex))) { e_error_run((GtkWindow *)gtk_widget_get_toplevel((GtkWidget *) cfd->emft), - cfd->delete?"mail:no-move-folder-to-notexist":"mail:no-copy-folder-to-notexist", frombase, uri, ex.desc, NULL); + cfd->delete?"mail:no-move-folder-to-notexist":"mail:no-move-folder-to-notexist", frombase, uri, ex.desc, NULL); goto fail; } - + url = camel_url_new (uri, NULL); if (((CamelService *)tostore)->provider->url_flags & CAMEL_URL_FRAGMENT_IS_PATH) tobase = url->fragment; @@ -2252,42 +2201,9 @@ fail: g_free (cfd); } -/* tree here is the 'destination' selector, not 'self' */ -static gboolean -emft_popup_copy_folder_exclude(EMFolderTree *tree, GtkTreeModel *model, GtkTreeIter *iter, void *data) -{ - struct _copy_folder_data *cfd = data; - int fromvfolder, tovfolder; - char *fromuri, *touri; - guint flags; - gboolean is_store; - - /* handles moving to/from vfolders */ - - fromuri = em_folder_tree_get_selected_uri(cfd->emft); - fromvfolder = strncmp(fromuri, "vfolder:", 8) == 0; - gtk_tree_model_get(model, iter, COL_STRING_URI, &touri, COL_UINT_FLAGS, &flags, COL_BOOL_IS_STORE, &is_store, -1); - tovfolder = strncmp(touri, "vfolder:", 8) == 0; - g_free(fromuri); - g_free(touri); - - /* moving from vfolder to normal- not allowed */ - if (fromvfolder && !tovfolder && cfd->delete) - return FALSE; - /* copy/move from normal folder to vfolder - not allowed */ - if (!fromvfolder && tovfolder) - return FALSE; - /* copying to vfolder - not allowed */ - if (tovfolder && !cfd->delete) - return FALSE; - - return (flags & EMFT_EXCLUDE_NOINFERIORS) == 0; -} - static void -emft_popup_copy(EPopup *ep, EPopupItem *item, void *data) +emft_popup_copy (GtkWidget *item, EMFolderTree *emft) { - EMFolderTree *emft = data; struct _copy_folder_data *cfd; cfd = g_malloc (sizeof (*cfd)); @@ -2295,13 +2211,12 @@ emft_popup_copy(EPopup *ep, EPopupItem *item, void *data) cfd->delete = FALSE; em_select_folder (NULL, _("Select folder"), _("C_opy"), - NULL, emft_popup_copy_folder_exclude, emft_popup_copy_folder_selected, cfd); + NULL, emft_popup_copy_folder_selected, cfd); } static void -emft_popup_move(EPopup *ep, EPopupItem *item, void *data) +emft_popup_move (GtkWidget *item, EMFolderTree *emft) { - EMFolderTree *emft = data; struct _copy_folder_data *cfd; cfd = g_malloc (sizeof (*cfd)); @@ -2309,7 +2224,7 @@ emft_popup_move(EPopup *ep, EPopupItem *item, void *data) cfd->delete = TRUE; em_select_folder (NULL, _("Select folder"), _("_Move"), - NULL, emft_popup_copy_folder_exclude, emft_popup_copy_folder_selected, cfd); + NULL, emft_popup_copy_folder_selected, cfd); } @@ -2514,10 +2429,8 @@ emft_popup_new_folder_response (EMFolderSelector *emfs, int response, EMFolderTr } static void -emft_popup_new_folder (EPopup *ep, EPopupItem *pitem, void *data) +emft_popup_new_folder (GtkWidget *item, EMFolderTree *emft) { - EMFolderTree *emft = data; - EMFolderTree *folder_tree; GtkWidget *dialog; char *uri; @@ -2642,9 +2555,8 @@ emft_popup_delete_response (GtkWidget *dialog, int response, EMFolderTree *emft) } static void -emft_popup_delete_folder (EPopup *ep, EPopupItem *pitem, void *data) +emft_popup_delete_folder (GtkWidget *item, EMFolderTree *emft) { - EMFolderTree *emft = data; struct _EMFolderTreePrivate *priv = emft->priv; GtkTreeSelection *selection; CamelStore *local, *store; @@ -2678,9 +2590,8 @@ emft_popup_delete_folder (EPopup *ep, EPopupItem *pitem, void *data) } static void -emft_popup_rename_folder (EPopup *ep, EPopupItem *pitem, void *data) +emft_popup_rename_folder (GtkWidget *item, EMFolderTree *emft) { - EMFolderTree *emft = data; struct _EMFolderTreePrivate *priv = emft->priv; char *prompt, *full_name, *name, *new_name, *uri; GtkTreeSelection *selection; @@ -2720,12 +2631,16 @@ emft_popup_rename_folder (EPopup *ep, EPopupItem *pitem, void *data) prompt = g_strdup_printf (_("Rename the \"%s\" folder to:"), name); while (!done) { new_name = e_request_string (NULL, _("Rename Folder"), prompt, name); - if (new_name == NULL || !strcmp (name, new_name)) { - /* old name == new name */ - done = TRUE; - } else if (strchr(new_name, '/') != NULL) { + if (strchr(new_name, '/') != NULL) { + char *tmp; + + tmp = g_strdup_printf(_("The folder name \"%s\" is invalid because it contains the character \"%c\""), new_name, '/'); e_error_run((GtkWindow *)gtk_widget_get_toplevel((GtkWidget *)emft), - "mail:no-rename-folder", name, new_name, _("Folder names cannot contain '/'"), NULL); + "mail:no-rename-folder", name, new_name, tmp, NULL); + g_free(tmp); + done = TRUE; + } else if (new_name == NULL || !strcmp (name, new_name)) { + /* old name == new name */ done = TRUE; } else { CamelFolderInfo *fi; @@ -2779,9 +2694,8 @@ emft_popup_rename_folder (EPopup *ep, EPopupItem *pitem, void *data) static void -emft_popup_properties (EPopup *ep, EPopupItem *pitem, void *data) +emft_popup_properties (GtkWidget *item, EMFolderTree *emft) { - EMFolderTree *emft = data; struct _EMFolderTreePrivate *priv = emft->priv; GtkTreeSelection *selection; GtkTreeModel *model; @@ -2797,40 +2711,34 @@ emft_popup_properties (EPopup *ep, EPopupItem *pitem, void *data) g_free (uri); } -static EPopupItem emft_popup_items[] = { +static EMPopupItem emft_popup_menu[] = { #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 }, + { EM_POPUP_ITEM, "00.emc.00", N_("_View"), G_CALLBACK (emft_popup_view), NULL, NULL, EM_POPUP_FOLDER_SELECT }, + { EM_POPUP_ITEM, "00.emc.01", N_("Open in _New Window"), G_CALLBACK (emft_popup_open_new), NULL, NULL, EM_POPUP_FOLDER_SELECT }, - { E_POPUP_BAR, "10.emc" }, + { EM_POPUP_BAR, "10.emc" }, #endif - { E_POPUP_ITEM, "10.emc.00", N_("_Copy..."), emft_popup_copy, NULL, "stock_folder-copy", 0, EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_SELECT }, - { E_POPUP_ITEM, "10.emc.01", N_("_Move..."), emft_popup_move, NULL, "stock_folder-move", 0, EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_DELETE }, + { EM_POPUP_ITEM, "10.emc.00", N_("_Copy..."), G_CALLBACK (emft_popup_copy), NULL, "stock_folder-copy", EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_SELECT }, + { EM_POPUP_ITEM, "10.emc.01", N_("_Move..."), G_CALLBACK (emft_popup_move), NULL, "stock_folder-move", EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_DELETE }, - { E_POPUP_BAR, "20.emc" }, + { EM_POPUP_BAR, "20.emc" }, /* FIXME: need to disable for nochildren folders */ - { E_POPUP_ITEM, "20.emc.00", N_("_New Folder..."), emft_popup_new_folder, NULL, "stock_new-dir", 0, EM_POPUP_FOLDER_INFERIORS }, + { EM_POPUP_ITEM, "20.emc.00", N_("_New Folder..."), G_CALLBACK (emft_popup_new_folder), NULL, "stock_folder", EM_POPUP_FOLDER_INFERIORS }, /* FIXME: need to disable for undeletable folders */ - { E_POPUP_ITEM, "20.emc.01", N_("_Delete"), emft_popup_delete_folder, NULL, "stock_delete", 0, EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_DELETE }, - { E_POPUP_ITEM, "20.emc.02", N_("_Rename..."), emft_popup_rename_folder, NULL, NULL, 0, EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_DELETE }, + { EM_POPUP_ITEM, "20.emc.01", N_("_Delete"), G_CALLBACK (emft_popup_delete_folder), NULL, "stock_delete", EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_DELETE }, + { EM_POPUP_ITEM, "20.emc.01", N_("_Rename..."), G_CALLBACK (emft_popup_rename_folder), NULL, NULL, EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_DELETE }, - { E_POPUP_BAR, "80.emc" }, - { E_POPUP_ITEM, "80.emc.00", N_("_Properties"), emft_popup_properties, NULL, "stock_folder-properties", 0, EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_SELECT } + { EM_POPUP_BAR, "80.emc" }, + { EM_POPUP_ITEM, "80.emc.00", N_("_Properties"), G_CALLBACK (emft_popup_properties), NULL, "stock_folder-properties", 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_tree_button_press (GtkTreeView *treeview, GdkEventButton *event, EMFolderTree *emft) { - GtkTreeView *treeview; GtkTreeSelection *selection; CamelStore *local, *store; - EMPopupTargetFolder *target; + EMPopupTarget *target; + GtkTreePath *tree_path; GtkTreeModel *model; GtkTreeIter iter; GSList *menus = NULL; @@ -2842,13 +2750,29 @@ emft_popup (EMFolderTree *emft, GdkEvent *event) EMPopup *emp; 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 */ + + if (event->button != 3 && !(event->button == 1 && event->type == GDK_2BUTTON_PRESS)) + return FALSE; + + if (!gtk_tree_view_get_path_at_pos (treeview, (int) event->x, (int) event->y, &tree_path, NULL, NULL, NULL)) + return FALSE; + + /* select/focus the row that was right-clicked or double-clicked */ selection = gtk_tree_view_get_selection (treeview); + gtk_tree_selection_select_path(selection, tree_path); + gtk_tree_view_set_cursor (treeview, tree_path, NULL, FALSE); + + if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) { + emft_tree_row_activated (treeview, tree_path, NULL, emft); + gtk_tree_path_free (tree_path); + return TRUE; + } + + gtk_tree_path_free (tree_path); + + /* FIXME: we really need the folderinfo to build a proper menu */ if (!emft_selection_get_selected (selection, &model, &iter)) return FALSE; @@ -2880,73 +2804,34 @@ emft_popup (EMFolderTree *emft, GdkEvent *event) info_flags |= CAMEL_FOLDER_VIRTUAL | CAMEL_FOLDER_NOINFERIORS; } - /** @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"); + /* handle right-click by opening a context menu */ + emp = em_popup_new ("com.ximian.mail.storageset.popup.select"); /* FIXME: pass valid fi->flags here */ - target = em_popup_target_new_folder (emp, uri, info_flags, flags); + target = em_popup_target_new_folder (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]); + for (i = 0; i < sizeof (emft_popup_menu) / sizeof (emft_popup_menu[0]); i++) { + EMPopupItem *item = &emft_popup_menu[i]; + + item->activate_data = emft; + menus = g_slist_prepend (menus, item); + } - e_popup_add_items ((EPopup *)emp, menus, NULL, emft_popup_free, emft); + em_popup_add_items (emp, menus, (GDestroyNotify) g_slist_free); - menu = e_popup_create_menu_once ((EPopup *)emp, (EPopupTarget *)target, 0); + menu = em_popup_create_menu_once (emp, target, 0, target->mask); 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()); + gtk_menu_popup (menu, NULL, NULL, NULL, NULL, 0, event->time); } else { - gtk_menu_popup (menu, NULL, NULL, NULL, NULL, event->button.button, event->button.time); + gtk_menu_popup (menu, NULL, NULL, NULL, NULL, event->button, event->time); } g_free (full_name); g_free (uri); - - 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; - GtkTreePath *tree_path; - - /* this centralises working out when the user's done something */ - emft_tree_user_event(treeview, (GdkEvent *)event, emft); - if (event->button != 3 && !(event->button == 1 && event->type == GDK_2BUTTON_PRESS)) - return FALSE; - - if (!gtk_tree_view_get_path_at_pos (treeview, (int) event->x, (int) event->y, &tree_path, NULL, NULL, NULL)) - return FALSE; - - /* select/focus the row that was right-clicked or double-clicked */ - selection = gtk_tree_view_get_selection (treeview); - gtk_tree_selection_select_path(selection, tree_path); - gtk_tree_view_set_cursor (treeview, tree_path, NULL, FALSE); - - if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) { - emft_tree_row_activated (treeview, tree_path, NULL, emft); - gtk_tree_path_free (tree_path); - return TRUE; - } - - gtk_tree_path_free (tree_path); - - return emft_popup (emft, (GdkEvent *)event); + return TRUE; } /* This is called for keyboard and mouse events, it seems the only way diff --git a/mail/em-folder-tree.h b/mail/em-folder-tree.h index e7c465998b..8ce1ad5873 100644 --- a/mail/em-folder-tree.h +++ b/mail/em-folder-tree.h @@ -51,8 +51,6 @@ typedef struct _EMFolderTreeClass EMFolderTreeClass; #define EMFT_EXCLUDE_SYSTEM CAMEL_FOLDER_SYSTEM #define EMFT_EXCLUDE_VTRASH CAMEL_FOLDER_VTRASH -typedef gboolean (*EMFTExcludeFunc)(EMFolderTree *emft, GtkTreeModel *model, GtkTreeIter *iter, void *data); - struct _EMFolderTree { GtkVBox parent_object; @@ -76,7 +74,6 @@ void em_folder_tree_enable_drag_and_drop (EMFolderTree *emft); void em_folder_tree_set_multiselect (EMFolderTree *emft, gboolean mode); void em_folder_tree_set_excluded(EMFolderTree *emft, guint32 flags); -void em_folder_tree_set_excluded_func(EMFolderTree *emft, EMFTExcludeFunc exclude, void *data); void em_folder_tree_set_selected_list (EMFolderTree *emft, GList *list); GList *em_folder_tree_get_selected_uris (EMFolderTree *emft); diff --git a/mail/em-folder-view.c b/mail/em-folder-view.c index 8793aba3ea..0699849d04 100644 --- a/mail/em-folder-view.c +++ b/mail/em-folder-view.c @@ -67,7 +67,6 @@ #include <e-util/e-dialog-utils.h> #include <e-util/e-icon-factory.h> -#include <e-util/e-print.h> #include "em-format-html-display.h" #include "em-format-html-print.h" @@ -79,8 +78,6 @@ #include "em-utils.h" #include "em-composer-utils.h" #include "em-marshal.h" -#include "em-menu.h" -#include "em-event.h" #include <gtkhtml/gtkhtml.h> #include <gtkhtml/htmlobject.h> @@ -125,8 +122,6 @@ 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 gboolean emfv_popup_menu (GtkWidget *widget); - static const EMFolderViewEnable emfv_enable_map[]; struct _EMFolderViewPrivate { @@ -254,7 +249,7 @@ emfv_destroy (GtkObject *o) } if (p->invisible) { - gtk_object_destroy((GtkObject *)p->invisible); + gtk_object_destroy(p->invisible); p->invisible = NULL; } @@ -273,8 +268,6 @@ emfv_class_init(GObjectClass *klass) ((GtkObjectClass *) klass)->destroy = emfv_destroy; - ((GtkWidgetClass *) klass)->popup_menu = emfv_popup_menu; - ((EMFolderViewClass *) klass)->update_message_style = TRUE; ((EMFolderViewClass *)klass)->set_folder = emfv_set_folder; @@ -371,25 +364,12 @@ em_folder_view_open_selected(EMFolderView *emfv) 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) + + if (em_utils_folder_is_drafts(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; + i = uids->len; + em_utils_edit_messages (emfv->folder, uids, TRUE); + return i; } /* for vfolders we need to edit the *original*, not the vfolder copy */ @@ -417,7 +397,7 @@ em_folder_view_open_selected(EMFolderView *emfv) } } else { g_ptr_array_add(views, g_strdup(uids->pdata[i])); - } + } } /* TODO: have an em_utils_open_messages call? */ @@ -426,6 +406,7 @@ em_folder_view_open_selected(EMFolderView *emfv) emmb = (EMMessageBrowser *)em_message_browser_window_new(); message_list_set_threaded(((EMFolderView *)emmb)->list, emfv->list->threaded); + 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); @@ -435,7 +416,6 @@ em_folder_view_open_selected(EMFolderView *emfv) g_free(views->pdata[i]); } g_ptr_array_free(views, TRUE); - message_list_free_uids(emfv->list, uids); return i; @@ -642,17 +622,22 @@ emfv_selection_clear_event(GtkWidget *widget, GdkEventSelection *event, EMFolder /* Popup menu In many cases these are the functions called by the bonobo callbacks too */ +struct _emfv_label_item { + EMPopupItem item; + + EMFolderView *emfv; + const char *label; +}; + static void -emfv_popup_open(EPopup *ep, EPopupItem *pitem, void *data) +emfv_popup_open(GtkWidget *w, EMFolderView *emfv) { - EMFolderView *emfv = data; em_folder_view_open_selected(emfv); } static void -emfv_popup_edit (EPopup *ep, EPopupItem *pitem, void *data) +emfv_popup_edit (GtkWidget *w, EMFolderView *emfv) { - EMFolderView *emfv = data; GPtrArray *uids; if (!em_utils_check_user_can_send_mail((GtkWidget *)emfv)) @@ -663,9 +648,8 @@ emfv_popup_edit (EPopup *ep, EPopupItem *pitem, void *data) } static void -emfv_popup_saveas(EPopup *ep, EPopupItem *pitem, void *data) +emfv_popup_saveas(GtkWidget *w, EMFolderView *emfv) { - EMFolderView *emfv = data; GPtrArray *uids; uids = message_list_get_selected(emfv->list); @@ -673,37 +657,32 @@ emfv_popup_saveas(EPopup *ep, EPopupItem *pitem, void *data) } static void -emfv_popup_print(EPopup *ep, EPopupItem *pitem, void *data) +emfv_popup_print(GtkWidget *w, EMFolderView *emfv) { - EMFolderView *emfv = data; em_folder_view_print(emfv, FALSE); } static void -emfv_popup_reply_sender(EPopup *ep, EPopupItem *pitem, void *data) +emfv_popup_reply_sender(GtkWidget *w, EMFolderView *emfv) { - EMFolderView *emfv = data; emfv_message_reply(emfv, REPLY_MODE_SENDER); } static void -emfv_popup_reply_list(EPopup *ep, EPopupItem *pitem, void *data) +emfv_popup_reply_list(GtkWidget *w, EMFolderView *emfv) { - EMFolderView *emfv = data; emfv_message_reply(emfv, REPLY_MODE_LIST); } static void -emfv_popup_reply_all(EPopup *ep, EPopupItem *pitem, void *data) +emfv_popup_reply_all(GtkWidget *w, EMFolderView *emfv) { - EMFolderView *emfv = data; emfv_message_reply(emfv, REPLY_MODE_ALL); } static void -emfv_popup_forward(EPopup *ep, EPopupItem *pitem, void *data) +emfv_popup_forward(GtkWidget *w, EMFolderView *emfv) { - EMFolderView *emfv = data; GPtrArray *uids; if (!em_utils_check_user_can_send_mail((GtkWidget *)emfv)) @@ -714,18 +693,16 @@ emfv_popup_forward(EPopup *ep, EPopupItem *pitem, void *data) } static void -emfv_popup_flag_followup(EPopup *ep, EPopupItem *pitem, void *data) +emfv_popup_flag_followup(GtkWidget *w, EMFolderView *emfv) { - 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) +emfv_popup_flag_completed(GtkWidget *w, EMFolderView *emfv) { - EMFolderView *emfv = data; GPtrArray *uids; uids = message_list_get_selected(emfv->list); @@ -733,25 +710,22 @@ emfv_popup_flag_completed(EPopup *ep, EPopupItem *pitem, void *data) } static void -emfv_popup_flag_clear(EPopup *ep, EPopupItem *pitem, void *data) +emfv_popup_flag_clear(GtkWidget *w, EMFolderView *emfv) { - EMFolderView *emfv = data; GPtrArray *uids = message_list_get_selected(emfv->list); em_utils_flag_for_followup_clear((GtkWidget *)emfv, emfv->folder, uids); } static void -emfv_popup_mark_read(EPopup *ep, EPopupItem *pitem, void *data) +emfv_popup_mark_read(GtkWidget *w, EMFolderView *emfv) { - 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) +emfv_popup_mark_unread(GtkWidget *w, EMFolderView *emfv) { - EMFolderView *emfv = data; em_folder_view_mark_selected(emfv, CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_DELETED, 0); if (emfv->priv->seen_id) { @@ -761,63 +735,65 @@ emfv_popup_mark_unread(EPopup *ep, EPopupItem *pitem, void *data) } static void -emfv_popup_mark_important(EPopup *ep, EPopupItem *pitem, void *data) +emfv_popup_mark_important(GtkWidget *w, EMFolderView *emfv) { - 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) +emfv_popup_mark_unimportant(GtkWidget *w, EMFolderView *emfv) { - EMFolderView *emfv = data; em_folder_view_mark_selected(emfv, CAMEL_MESSAGE_FLAGGED, 0); } static void -emfv_popup_mark_junk (EPopup *ep, EPopupItem *pitem, void *data) +emfv_popup_mark_junk (GtkWidget *w, EMFolderView *emfv) { - EMFolderView *emfv = data; - int count; + GPtrArray *uids; - count = em_folder_view_mark_selected(emfv, - CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_JUNK|CAMEL_MESSAGE_JUNK_LEARN, - CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_JUNK|CAMEL_MESSAGE_JUNK_LEARN); - if (count == 1) + uids = message_list_get_selected(emfv->list); + em_folder_view_mark_selected(emfv, + CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_JUNK|CAMEL_MESSAGE_JUNK_LEARN, + CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_JUNK|CAMEL_MESSAGE_JUNK_LEARN); + if (uids->len == 1) message_list_select(emfv->list, MESSAGE_LIST_SELECT_NEXT, 0, 0); + + message_list_free_uids(emfv->list, uids); } static void -emfv_popup_mark_nojunk (EPopup *ep, EPopupItem *pitem, void *data) +emfv_popup_mark_nojunk (GtkWidget *w, EMFolderView *emfv) { - EMFolderView *emfv = data; - int count; + GPtrArray *uids; - count = em_folder_view_mark_selected(emfv, - CAMEL_MESSAGE_JUNK|CAMEL_MESSAGE_JUNK_LEARN, - CAMEL_MESSAGE_JUNK_LEARN); - if (count == 1) + uids = message_list_get_selected(emfv->list); + em_folder_view_mark_selected(emfv, + CAMEL_MESSAGE_JUNK|CAMEL_MESSAGE_JUNK_LEARN, + CAMEL_MESSAGE_JUNK_LEARN); + if (uids->len == 1) message_list_select(emfv->list, MESSAGE_LIST_SELECT_NEXT, 0, 0); + + message_list_free_uids(emfv->list, uids); } static void -emfv_popup_delete(EPopup *ep, EPopupItem *pitem, void *data) +emfv_popup_delete(GtkWidget *w, EMFolderView *emfv) { - EMFolderView *emfv = data; - int count; + GPtrArray *uids; - count = em_folder_view_mark_selected(emfv, CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_DELETED, CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_DELETED); + uids = message_list_get_selected(emfv->list); + em_folder_view_mark_selected(emfv, CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_DELETED, CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_DELETED); - if (count == 1) { + if (uids->len == 1) { if (!message_list_select (emfv->list, MESSAGE_LIST_SELECT_NEXT, 0, 0) && emfv->hide_deleted) message_list_select (emfv->list, MESSAGE_LIST_SELECT_PREVIOUS, 0, 0); } + em_utils_uids_free(uids); } static void -emfv_popup_undelete(EPopup *ep, EPopupItem *pitem, void *data) +emfv_popup_undelete(GtkWidget *w, EMFolderView *emfv) { - EMFolderView *emfv = data; em_folder_view_mark_selected(emfv, CAMEL_MESSAGE_DELETED, 0); } @@ -846,9 +822,8 @@ emfv_popup_move_cb(const char *uri, void *data) } static void -emfv_popup_move(EPopup *ep, EPopupItem *pitem, void *data) +emfv_popup_move(GtkWidget *w, EMFolderView *emfv) { - EMFolderView *emfv = data; struct _move_data *d; d = g_malloc(sizeof(*d)); @@ -857,13 +832,12 @@ emfv_popup_move(EPopup *ep, EPopupItem *pitem, void *data) 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); + em_select_folder ((GtkWindow *) emfv, _("Select folder"), _("_Move"), default_xfer_messages_uri, emfv_popup_move_cb, d); } static void -emfv_popup_copy(EPopup *ep, EPopupItem *pitem, void *data) +emfv_popup_copy(GtkWidget *w, EMFolderView *emfv) { - EMFolderView *emfv = data; struct _move_data *d; d = g_malloc(sizeof(*d)); @@ -872,7 +846,7 @@ emfv_popup_copy(EPopup *ep, EPopupItem *pitem, void *data) 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); + em_select_folder ((GtkWindow *) emfv, _("Select folder"), _("C_opy"), default_xfer_messages_uri, emfv_popup_move_cb, d); } static void @@ -888,24 +862,20 @@ emfv_set_label(EMFolderView *emfv, const char *label) } static void -emfv_popup_label_clear(EPopup *ep, EPopupItem *pitem, void *data) +emfv_popup_label_clear(GtkWidget *w, EMFolderView *emfv) { - EMFolderView *emfv = data; emfv_set_label(emfv, NULL); } static void -emfv_popup_label_set(EPopup *ep, EPopupItem *pitem, void *data) +emfv_popup_label_set(GtkWidget *w, struct _emfv_label_item *item) { - EMFolderView *emfv = data; - - emfv_set_label(emfv, pitem->user_data); + emfv_set_label(item->emfv, item->label); } static void -emfv_popup_add_sender(EPopup *ep, EPopupItem *pitem, void *data) +emfv_popup_add_sender(GtkWidget *w, EMFolderView *emfv) { - EMFolderView *emfv = data; GPtrArray *uids = message_list_get_selected(emfv->list); CamelMessageInfo *info; const char *addr; @@ -920,18 +890,16 @@ emfv_popup_add_sender(EPopup *ep, EPopupItem *pitem, void *data) } static void -emfv_popup_apply_filters(EPopup *ep, EPopupItem *pitem, void *data) +emfv_popup_apply_filters(GtkWidget *w, EMFolderView *emfv) { - 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) +emfv_popup_filter_junk(GtkWidget *w, EMFolderView *emfv) { - EMFolderView *emfv = data; GPtrArray *uids = message_list_get_selected(emfv->list); mail_filter_junk(emfv->folder, uids); @@ -942,9 +910,8 @@ emfv_popup_filter_junk(EPopup *ep, EPopupItem *pitem, void *data) #define EMFV_POPUP_AUTO_TYPE(autotype, name, type) \ static void \ -name(EPopup *ep, EPopupItem *item, void *data) \ +name(GtkWidget *w, EMFolderView *emfv) \ { \ - EMFolderView *emfv = data; \ autotype(emfv, type); \ } @@ -960,87 +927,83 @@ 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_("_Open"), emfv_popup_open, NULL, NULL, 0 }, - { E_POPUP_ITEM, "00.emfv.01", N_("_Edit as New Message..."), emfv_popup_edit, NULL, NULL, EM_POPUP_SELECT_EDIT }, - { E_POPUP_ITEM, "00.emfv.02", N_("_Save As..."), emfv_popup_saveas, NULL, "stock_save-as", 0 }, - { E_POPUP_ITEM, "00.emfv.03", N_("_Print"), emfv_popup_print, NULL, "stock_print", 0 }, - - { E_POPUP_BAR, "10.emfv" }, - { E_POPUP_ITEM, "10.emfv.00", N_("_Reply to Sender"), emfv_popup_reply_sender, NULL, "stock_mail-reply", EM_POPUP_SELECT_ONE }, - { E_POPUP_ITEM, "10.emfv.01", N_("Reply to _List"), emfv_popup_reply_list, NULL, NULL, EM_POPUP_SELECT_ONE|EM_POPUP_SELECT_MAILING_LIST }, - { E_POPUP_ITEM, "10.emfv.02", N_("Reply to _All"), emfv_popup_reply_all, NULL, "stock_mail-reply-to-all", EM_POPUP_SELECT_ONE }, - { E_POPUP_ITEM, "10.emfv.03", N_("_Forward"), emfv_popup_forward, NULL, "stock_mail-forward", EM_POPUP_SELECT_MANY }, - - { E_POPUP_BAR, "20.emfv", NULL, NULL, NULL, NULL, EM_POPUP_SELECT_FLAG_FOLLOWUP|EM_POPUP_SELECT_FLAG_COMPLETED|EM_POPUP_SELECT_FLAG_CLEAR }, - { E_POPUP_ITEM, "20.emfv.00", N_("Follo_w Up..."), emfv_popup_flag_followup, NULL, "stock_mail-flag-for-followup", EM_POPUP_SELECT_FLAG_FOLLOWUP }, - { E_POPUP_ITEM, "20.emfv.01", N_("Fla_g Completed"), emfv_popup_flag_completed, NULL, NULL, EM_POPUP_SELECT_FLAG_COMPLETED }, - { E_POPUP_ITEM, "20.emfv.02", N_("Cl_ear Flag"), emfv_popup_flag_clear, NULL, NULL, EM_POPUP_SELECT_FLAG_CLEAR }, - - { E_POPUP_BAR, "30.emfv" }, - { E_POPUP_ITEM, "30.emfv.00", N_("Mar_k as Read"), emfv_popup_mark_read, NULL, "stock_mail-open", EM_POPUP_SELECT_MARK_READ }, - { E_POPUP_ITEM, "30.emfv.01", N_("Mark as _Unread"), emfv_popup_mark_unread, NULL, "stock_mail-unread", EM_POPUP_SELECT_MARK_UNREAD }, - { E_POPUP_ITEM, "30.emfv.02", N_("Mark as _Important"), emfv_popup_mark_important, NULL, "stock_mail-priority-high", EM_POPUP_SELECT_MARK_IMPORTANT }, - { E_POPUP_ITEM, "30.emfv.03", N_("_Mark as Unimportant"), emfv_popup_mark_unimportant, NULL, NULL, EM_POPUP_SELECT_MARK_UNIMPORTANT }, - { E_POPUP_ITEM, "30.emfv.04", N_("Mark as _Junk"), emfv_popup_mark_junk, NULL, "stock_spam", EM_POPUP_SELECT_MANY }, - { E_POPUP_ITEM, "30.emfv.05", N_("Mark as _Not Junk"), emfv_popup_mark_nojunk, NULL, "stock_not-spam", EM_POPUP_SELECT_MANY }, - - { E_POPUP_BAR, "40.emfv" }, - { E_POPUP_ITEM, "40.emfv.00", N_("_Delete"), emfv_popup_delete, NULL, "stock_delete", EM_POPUP_SELECT_DELETE }, - { E_POPUP_ITEM, "40.emfv.01", N_("U_ndelete"), emfv_popup_undelete, NULL, "stock_undelete", EM_POPUP_SELECT_UNDELETE }, - - { E_POPUP_BAR, "50.emfv" }, - { E_POPUP_ITEM, "50.emfv.00", N_("Mo_ve to Folder..."), emfv_popup_move }, - { E_POPUP_ITEM, "50.emfv.01", N_("_Copy to Folder..."), emfv_popup_copy }, - - { E_POPUP_BAR, "60.label" }, - { E_POPUP_SUBMENU, "60.label.00", N_("Label") }, - { E_POPUP_IMAGE, "60.label.00/00.label", N_("None"), emfv_popup_label_clear }, - { E_POPUP_BAR, "60.label.00/00.label.00" }, - - { E_POPUP_BAR, "70.emfv", NULL, NULL, NULL, NULL, EM_POPUP_SELECT_ADD_SENDER }, - { E_POPUP_ITEM, "70.emfv.00", N_("Add Sender to Address_book"), emfv_popup_add_sender, NULL, NULL, EM_POPUP_SELECT_ADD_SENDER }, - - { E_POPUP_BAR, "80.emfv" }, - { E_POPUP_ITEM, "80.emfv.00", N_("Appl_y Filters"), emfv_popup_apply_filters, NULL, "stock_mail-filters-apply" }, - { E_POPUP_ITEM, "80.emfv.01", N_("F_ilter Junk"), emfv_popup_filter_junk, NULL, "stock_spam" }, - - { E_POPUP_BAR, "90.filter", NULL, NULL, NULL, NULL, EM_POPUP_SELECT_ONE }, - { E_POPUP_SUBMENU, "90.filter.00", N_("Crea_te Rule From Message"), NULL, NULL, NULL, EM_POPUP_SELECT_ONE }, - { E_POPUP_ITEM, "90.filter.00/00.00", N_("vFolder on _Subject"), emfv_popup_vfolder_subject, NULL, NULL, EM_POPUP_SELECT_ONE }, - { E_POPUP_ITEM, "90.filter.00/00.01", N_("vFolder on Se_nder"), emfv_popup_vfolder_sender, NULL, NULL, EM_POPUP_SELECT_ONE }, - { E_POPUP_ITEM, "90.filter.00/00.02", N_("vFolder on _Recipients"), emfv_popup_vfolder_recipients, NULL, NULL, EM_POPUP_SELECT_ONE }, - { E_POPUP_ITEM, "90.filter.00/00.03", N_("vFolder on Mailing _List"), - emfv_popup_vfolder_mlist, NULL, NULL, EM_POPUP_SELECT_ONE|EM_POPUP_SELECT_MAILING_LIST }, - - { E_POPUP_BAR, "90.filter.00/10", NULL, NULL, NULL, NULL, EM_POPUP_SELECT_ONE }, - { E_POPUP_ITEM, "90.filter.00/10.00", N_("Filter on Sub_ject"), emfv_popup_filter_subject, NULL, NULL, EM_POPUP_SELECT_ONE }, - { E_POPUP_ITEM, "90.filter.00/10.01", N_("Filter on Sen_der"), emfv_popup_filter_sender, NULL, NULL, EM_POPUP_SELECT_ONE }, - { E_POPUP_ITEM, "90.filter.00/10.02", N_("Filter on Re_cipients"), emfv_popup_filter_recipients, NULL, NULL, EM_POPUP_SELECT_ONE }, - { E_POPUP_ITEM, "90.filter.00/10.03", N_("Filter on _Mailing List"), - emfv_popup_filter_mlist, NULL, NULL, EM_POPUP_SELECT_ONE|EM_POPUP_SELECT_MAILING_LIST }, +static EMPopupItem emfv_popup_menu[] = { + { EM_POPUP_ITEM, "00.emfv.00", N_("_Open"), G_CALLBACK(emfv_popup_open), NULL, NULL, 0 }, + { EM_POPUP_ITEM, "00.emfv.01", N_("_Edit as New Message..."), G_CALLBACK(emfv_popup_edit), NULL, NULL, EM_POPUP_SELECT_EDIT }, + { EM_POPUP_ITEM, "00.emfv.02", N_("_Save As..."), G_CALLBACK(emfv_popup_saveas), NULL, "stock_save-as", 0 }, + { EM_POPUP_ITEM, "00.emfv.03", N_("_Print"), G_CALLBACK(emfv_popup_print), NULL, "stock_print", 0 }, + + { EM_POPUP_BAR, "10.emfv" }, + { EM_POPUP_ITEM, "10.emfv.00", N_("_Reply to Sender"), G_CALLBACK(emfv_popup_reply_sender), NULL, "stock_mail-reply", EM_POPUP_SELECT_ONE }, + { EM_POPUP_ITEM, "10.emfv.01", N_("Reply to _List"), G_CALLBACK(emfv_popup_reply_list), NULL, NULL, EM_POPUP_SELECT_ONE|EM_POPUP_SELECT_MAILING_LIST }, + { EM_POPUP_ITEM, "10.emfv.02", N_("Reply to _All"), G_CALLBACK(emfv_popup_reply_all), NULL, "stock_mail-reply-to-all", EM_POPUP_SELECT_ONE }, + { EM_POPUP_ITEM, "10.emfv.03", N_("_Forward"), G_CALLBACK(emfv_popup_forward), NULL, "stock_mail-forward", EM_POPUP_SELECT_MANY }, + + { EM_POPUP_BAR, "20.emfv", NULL, NULL, NULL, NULL, EM_POPUP_SELECT_FLAG_FOLLOWUP|EM_POPUP_SELECT_FLAG_COMPLETED|EM_POPUP_SELECT_FLAG_CLEAR }, + { EM_POPUP_ITEM, "20.emfv.00", N_("Follo_w Up..."), G_CALLBACK(emfv_popup_flag_followup), NULL, "stock_mail-flag-for-followup", EM_POPUP_SELECT_FLAG_FOLLOWUP }, + { EM_POPUP_ITEM, "20.emfv.01", N_("Fla_g Completed"), G_CALLBACK(emfv_popup_flag_completed), NULL, NULL, EM_POPUP_SELECT_FLAG_COMPLETED }, + { EM_POPUP_ITEM, "20.emfv.02", N_("Cl_ear Flag"), G_CALLBACK(emfv_popup_flag_clear), NULL, NULL, EM_POPUP_SELECT_FLAG_CLEAR }, + + { EM_POPUP_BAR, "30.emfv" }, + { EM_POPUP_ITEM, "30.emfv.00", N_("Mar_k as Read"), G_CALLBACK(emfv_popup_mark_read), NULL, "stock_mail-open", EM_POPUP_SELECT_MARK_READ }, + { EM_POPUP_ITEM, "30.emfv.01", N_("Mark as _Unread"), G_CALLBACK(emfv_popup_mark_unread), NULL, "stock_mail-unread", EM_POPUP_SELECT_MARK_UNREAD }, + { EM_POPUP_ITEM, "30.emfv.02", N_("Mark as _Important"), G_CALLBACK(emfv_popup_mark_important), NULL, "stock_mail-priority-high", EM_POPUP_SELECT_MARK_IMPORTANT }, + { EM_POPUP_ITEM, "30.emfv.03", N_("_Mark as Unimportant"), G_CALLBACK(emfv_popup_mark_unimportant), NULL, NULL, EM_POPUP_SELECT_MARK_UNIMPORTANT }, + { EM_POPUP_ITEM, "30.emfv.04", N_("Mark as _Junk"), G_CALLBACK(emfv_popup_mark_junk), NULL, "stock_spam", EM_POPUP_SELECT_MARK_JUNK }, + { EM_POPUP_ITEM, "30.emfv.05", N_("Mark as _Not Junk"), G_CALLBACK(emfv_popup_mark_nojunk), NULL, "stock_not-spam", EM_POPUP_SELECT_MARK_NOJUNK }, + + { EM_POPUP_BAR, "40.emfv" }, + { EM_POPUP_ITEM, "40.emfv.00", N_("_Delete"), G_CALLBACK(emfv_popup_delete), NULL, "stock_delete", EM_POPUP_SELECT_DELETE }, + { EM_POPUP_ITEM, "40.emfv.01", N_("U_ndelete"), G_CALLBACK(emfv_popup_undelete), NULL, "stock_undelete", EM_POPUP_SELECT_UNDELETE }, + + { EM_POPUP_BAR, "50.emfv" }, + { EM_POPUP_ITEM, "50.emfv.00", N_("Mo_ve to Folder..."), G_CALLBACK(emfv_popup_move) }, + { EM_POPUP_ITEM, "50.emfv.01", N_("_Copy to Folder..."), G_CALLBACK(emfv_popup_copy) }, + + { EM_POPUP_BAR, "60.label" }, + { EM_POPUP_SUBMENU, "60.label.00", N_("Label") }, + { EM_POPUP_IMAGE, "60.label.00/00.label", N_("None"), G_CALLBACK(emfv_popup_label_clear) }, + { EM_POPUP_BAR, "60.label.00/00.label.00" }, + + { EM_POPUP_BAR, "70.emfv", NULL, NULL, NULL, NULL, EM_POPUP_SELECT_ADD_SENDER }, + { EM_POPUP_ITEM, "70.emfv.00", N_("Add Sender to Address_book"), G_CALLBACK(emfv_popup_add_sender), NULL, NULL, EM_POPUP_SELECT_ADD_SENDER }, + + { EM_POPUP_BAR, "80.emfv" }, + { EM_POPUP_ITEM, "80.emfv.00", N_("Appl_y Filters"), G_CALLBACK(emfv_popup_apply_filters), NULL, "stock_mail-filters-apply" }, + { EM_POPUP_ITEM, "80.emfv.01", N_("F_ilter Junk"), G_CALLBACK(emfv_popup_filter_junk), NULL, "stock_spam" }, + + { EM_POPUP_BAR, "90.filter", NULL, NULL, NULL, NULL, EM_POPUP_SELECT_ONE }, + { EM_POPUP_SUBMENU, "90.filter.00", N_("Crea_te Rule From Message"), NULL, NULL, NULL, EM_POPUP_SELECT_ONE }, + { EM_POPUP_ITEM, "90.filter.00/00.00", N_("VFolder on _Subject"), G_CALLBACK(emfv_popup_vfolder_subject), NULL, NULL, EM_POPUP_SELECT_ONE }, + { EM_POPUP_ITEM, "90.filter.00/00.01", N_("VFolder on Se_nder"), G_CALLBACK(emfv_popup_vfolder_sender), NULL, NULL, EM_POPUP_SELECT_ONE }, + { EM_POPUP_ITEM, "90.filter.00/00.02", N_("VFolder on _Recipients"), G_CALLBACK(emfv_popup_vfolder_recipients), NULL, NULL, EM_POPUP_SELECT_ONE }, + { EM_POPUP_ITEM, "90.filter.00/00.03", N_("VFolder on Mailing _List"), + G_CALLBACK(emfv_popup_vfolder_mlist), NULL, NULL, EM_POPUP_SELECT_ONE|EM_POPUP_SELECT_MAILING_LIST }, + + { EM_POPUP_BAR, "90.filter.00/10", NULL, NULL, NULL, NULL, EM_POPUP_SELECT_ONE }, + { EM_POPUP_ITEM, "90.filter.00/10.00", N_("Filter on Sub_ject"), G_CALLBACK(emfv_popup_filter_subject), NULL, NULL, EM_POPUP_SELECT_ONE }, + { EM_POPUP_ITEM, "90.filter.00/10.01", N_("Filter on Sen_der"), G_CALLBACK(emfv_popup_filter_sender), NULL, NULL, EM_POPUP_SELECT_ONE }, + { EM_POPUP_ITEM, "90.filter.00/10.02", N_("Filter on Re_cipients"), G_CALLBACK(emfv_popup_filter_recipients), NULL, NULL, EM_POPUP_SELECT_ONE }, + { EM_POPUP_ITEM, "90.filter.00/10.03", N_("Filter on _Mailing List"), + G_CALLBACK(emfv_popup_filter_mlist), NULL, NULL, EM_POPUP_SELECT_ONE|EM_POPUP_SELECT_MAILING_LIST }, }; static void -emfv_popup_labels_free(EPopup *ep, GSList *l, void *data) +emfv_popup_labels_free(void *data) { + GSList *l = data; + while (l) { GSList *n = l->next; - EPopupItem *item = l->data; + struct _emfv_label_item *item = l->data; - g_free(item->path); + g_free(item->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) @@ -1048,38 +1011,37 @@ emfv_popup(EMFolderView *emfv, GdkEvent *event) GSList *menus = NULL, *l, *label_list = NULL; GtkMenu *menu; EMPopup *emp; - EMPopupTargetSelect *target; + EMPopupTarget *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); + emp = em_popup_new("com.ximian.mail.folderview.popup.select"); + target = em_folder_view_get_popup_target(emfv); + + for (i=0;i<sizeof(emfv_popup_menu)/sizeof(emfv_popup_menu[0]);i++) { + EMPopupItem *item = &emfv_popup_menu[i]; - for (i=0;i<sizeof(emfv_popup_items)/sizeof(emfv_popup_items[0]);i++) - menus = g_slist_prepend(menus, &emfv_popup_items[i]); + item->activate_data = emfv; + menus = g_slist_prepend(menus, item); + } - e_popup_add_items((EPopup *)emp, menus, NULL, emfv_popup_items_free, emfv); + em_popup_add_items(emp, menus, (GDestroyNotify)g_slist_free); i = 1; for (l = mail_config_get_labels(); l; l = l->next) { - EPopupItem *item; + struct _emfv_label_item *item; MailConfigLabel *label = l->data; GdkPixmap *pixmap; GdkColor colour; GdkGC *gc; item = g_malloc0(sizeof(*item)); - item->type = E_POPUP_IMAGE; - 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->item.type = EM_POPUP_IMAGE; + item->item.path = g_strdup_printf("60.label.00/00.label.%02d", i++); + item->item.label = label->name; + item->item.activate = G_CALLBACK(emfv_popup_label_set); + item->item.activate_data = item; + item->emfv = emfv; + item->label = label->tag; gdk_color_parse(label->colour, &colour); gdk_color_alloc(gdk_colormap_get_system(), &colour); @@ -1090,19 +1052,19 @@ emfv_popup(EMFolderView *emfv, GdkEvent *event) gdk_draw_rectangle(pixmap, gc, TRUE, 0, 0, 16, 16); gdk_gc_unref(gc); - item->image = gtk_image_new_from_pixmap(pixmap, NULL); - gtk_widget_show(item->image); + item->item.image = gtk_image_new_from_pixmap(pixmap, NULL); + gtk_widget_show(item->item.image); label_list = g_slist_prepend(label_list, item); } - e_popup_add_items((EPopup *)emp, label_list, NULL, emfv_popup_labels_free, emfv); + em_popup_add_items(emp, label_list, emfv_popup_labels_free); - menu = e_popup_create_menu_once((EPopup *)emp, (EPopupTarget *)target, 0); + menu = em_popup_create_menu_once(emp, target, target->mask, target->mask); 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()); + gtk_menu_popup(menu, NULL, NULL, NULL, NULL, 0, event ? event->key.time : time (NULL)); } else { gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event->button.button, event->button.time); } @@ -1117,7 +1079,7 @@ emfv_popup(EMFolderView *emfv, GdkEvent *event) static void \ from(BonoboUIComponent *uid, void *data, const char *path) \ { \ - to(NULL, NULL, data); \ + to(NULL, (EMFolderView *)data); \ } EMFV_MAP_CALLBACK(emfv_add_sender_addressbook, emfv_popup_add_sender) @@ -1642,8 +1604,8 @@ static const EMFolderViewEnable emfv_enable_map[] = { { "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 }, - { "MessageMarkAsNotJunk", EM_POPUP_SELECT_MANY }, + { "MessageMarkAsJunk", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_JUNK }, + { "MessageMarkAsNotJunk", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_NOJUNK }, { "MessageFollowUpFlag", EM_POPUP_SELECT_MANY }, { "MessageMove", EM_POPUP_SELECT_MANY }, { "MessageOpen", EM_POPUP_SELECT_MANY }, @@ -1689,31 +1651,15 @@ emfv_enable_menus(EMFolderView *emfv) guint32 disable_mask; GString *name; GSList *l; + EMPopupTarget *t; if (emfv->uic == NULL) return; - { - if (emfv->menu) { - if (emfv->folder) { - EMMenuTargetSelect *t; - - t = em_menu_target_new_select(emfv->menu, emfv->folder, emfv->folder_uri, message_list_get_selected(emfv->list)); - e_menu_update_target((EMenu *)emfv->menu, t); - } else { - e_menu_update_target((EMenu *)emfv->menu, NULL); - } - } - } - if (emfv->folder) { - EMPopup *emp = em_popup_new("dummy"); - EMPopupTargetSelect *t; - - t = em_folder_view_get_popup_target(emfv, emp); - disable_mask = t->target.mask; - e_popup_target_free((EPopup *)emp, t); - g_object_unref(emp); + t = em_folder_view_get_popup_target(emfv); + disable_mask = t->mask; + em_popup_target_free(t); } else { disable_mask = ~0; } @@ -1819,10 +1765,6 @@ emfv_activate(EMFolderView *emfv, BonoboUIComponent *uic, int act) 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); @@ -1850,9 +1792,6 @@ emfv_activate(EMFolderView *emfv, BonoboUIComponent *uic, int act) } else { const BonoboUIVerb *v; - if (emfv->menu) - e_menu_activate((EMenu *)emfv->menu, uic, act); - /* TODO: Should this just rm /? */ for (v = &emfv_message_verbs[0]; v->cname; v++) bonobo_ui_component_remove_verb(uic, v->cname); @@ -1877,7 +1816,6 @@ emfv_activate(EMFolderView *emfv, BonoboUIComponent *uic, int act) struct _print_data { EMFolderView *emfv; - GnomePrintConfig *config; int preview; CamelFolder *folder; char *uid; @@ -1887,15 +1825,20 @@ static void emfv_print_response(GtkWidget *w, int resp, struct _print_data *data) { EMFormatHTMLPrint *print; + GnomePrintConfig *config = NULL; switch (resp) { case GNOME_PRINT_DIALOG_RESPONSE_PREVIEW: data->preview = TRUE; case GNOME_PRINT_DIALOG_RESPONSE_PRINT: + if (w) + config = gnome_print_dialog_get_config((GnomePrintDialog *)w); print = em_format_html_print_new(); em_format_set_session((EMFormat *)print, ((EMFormat *)data->emfv->preview)->session); - em_format_html_print_message(print, (EMFormatHTML *)data->emfv->preview, data->config, data->folder, data->uid, data->preview); + em_format_html_print_message(print, (EMFormatHTML *)data->emfv->preview, config, data->folder, data->uid, data->preview); g_object_unref(print); + if (config) + g_object_unref(config); break; } @@ -1903,8 +1846,6 @@ emfv_print_response(GtkWidget *w, int resp, struct _print_data *data) gtk_widget_destroy(w); g_object_unref(data->emfv); - e_print_save_config (data->config); - g_object_unref(data->config); camel_object_unref(data->folder); g_free(data->uid); g_free(data); @@ -1927,7 +1868,6 @@ int em_folder_view_print(EMFolderView *emfv, int preview) data = g_malloc0(sizeof(*data)); data->emfv = emfv; g_object_ref(emfv); - data->config = e_print_load_config (); data->preview = preview; data->folder = emfv->folder; camel_object_ref(data->folder); @@ -1937,8 +1877,8 @@ int em_folder_view_print(EMFolderView *emfv, int preview) if (preview) { emfv_print_response(NULL, GNOME_PRINT_DIALOG_RESPONSE_PREVIEW, data); } else { - GtkDialog *dialog = (GtkDialog *)e_print_get_dialog_with_config (_("Print Message"), GNOME_PRINT_DIALOG_COPIES, data->config); - + GtkDialog *dialog = (GtkDialog *)gnome_print_dialog_new(NULL, _("Print Message"), GNOME_PRINT_DIALOG_COPIES); + gtk_dialog_set_default_response(dialog, GNOME_PRINT_DIALOG_RESPONSE_PRINT); e_dialog_set_transient_for ((GtkWindow *) dialog, (GtkWidget *) emfv); g_signal_connect(dialog, "response", G_CALLBACK(emfv_print_response), data); @@ -1948,29 +1888,29 @@ int em_folder_view_print(EMFolderView *emfv, int preview) return 0; } -EMPopupTargetSelect * -em_folder_view_get_popup_target(EMFolderView *emfv, EMPopup *emp) +EMPopupTarget * +em_folder_view_get_popup_target(EMFolderView *emfv) { - EMPopupTargetSelect *t; + EMPopupTarget *t; - t = em_popup_target_new_select(emp, emfv->folder, emfv->folder_uri, message_list_get_selected(emfv->list)); - t->target.widget = (GtkWidget *)emfv; + t = em_popup_target_new_select(emfv->folder, emfv->folder_uri, message_list_get_selected(emfv->list)); + t->widget = (GtkWidget *)emfv; if (emfv->list->threaded) - t->target.mask &= ~EM_FOLDER_VIEW_SELECT_THREADED; + t->mask &= ~EM_FOLDER_VIEW_SELECT_THREADED; if (message_list_hidden(emfv->list) != 0) - t->target.mask &= ~EM_FOLDER_VIEW_SELECT_HIDDEN; + t->mask &= ~EM_FOLDER_VIEW_SELECT_HIDDEN; if (message_list_can_select(emfv->list, MESSAGE_LIST_SELECT_NEXT, 0, 0)) - t->target.mask &= ~EM_FOLDER_VIEW_SELECT_NEXT_MSG; + t->mask &= ~EM_FOLDER_VIEW_SELECT_NEXT_MSG; if (message_list_can_select(emfv->list, MESSAGE_LIST_SELECT_PREVIOUS, 0, 0)) - t->target.mask &= ~EM_FOLDER_VIEW_SELECT_PREV_MSG; + t->mask &= ~EM_FOLDER_VIEW_SELECT_PREV_MSG; /* See bug #54770 */ if (!emfv->hide_deleted) - t->target.mask &= ~EM_POPUP_SELECT_DELETE; + t->mask &= ~EM_POPUP_SELECT_DELETE; return t; } @@ -2034,27 +1974,14 @@ static void emfv_list_done_message_selected(CamelFolder *folder, const char *uid, CamelMimeMessage *msg, void *data) { EMFolderView *emfv = data; - EMEvent *eme; - EMEventTargetMessage *target; if (emfv->preview == NULL) { emfv->priv->nomarkseen = FALSE; - emfv_enable_menus(emfv); g_object_unref (emfv); + emfv_enable_menus(emfv); return; } - - /** @Event: message.reading - * @Title: Viewing a message - * @Target: EMEventTargetMessage - * - * message.reading is emitted whenever a user views a message. - */ - /* TODO: do we emit a message.reading with no message when we're looking at nothing or don't care? */ - eme = em_event_peek(); - target = em_event_target_new_message(eme, folder, msg, uid, 0); - e_event_emit((EEvent *)eme, "message.reading", (EEventTarget *)target); - + em_format_format((EMFormat *)emfv->preview, folder, uid, msg); if (emfv->priv->seen_id) @@ -2063,11 +1990,11 @@ emfv_list_done_message_selected(CamelFolder *folder, const char *uid, CamelMimeM if (msg && emfv->mark_seen && !emfv->priv->nomarkseen) { if (emfv->mark_seen_timeout > 0) { struct mst_t *mst; - + mst = g_new (struct mst_t, 1); mst->emfv = emfv; mst->uid = g_strdup (uid); - + emfv->priv->seen_id = g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE, emfv->mark_seen_timeout, (GSourceFunc)do_mark_seen, mst, (GDestroyNotify)mst_free); } else { @@ -2075,9 +2002,10 @@ emfv_list_done_message_selected(CamelFolder *folder, const char *uid, CamelMimeM } } + g_object_unref (emfv); emfv->priv->nomarkseen = FALSE; + emfv_enable_menus(emfv); - g_object_unref (emfv); } static void @@ -2139,6 +2067,10 @@ emfv_list_key_press(ETree *tree, int row, ETreePath path, int col, GdkEvent *ev, case GDK_ISO_Enter: em_folder_view_open_selected(emfv); break; + case GDK_Menu: + /* FIXME: location of popup */ + emfv_popup(emfv, NULL); + break; case '!': uids = message_list_get_selected(emfv->list); @@ -2161,26 +2093,6 @@ emfv_list_key_press(ETree *tree, int row, ETreePath path, int col, GdkEvent *ev, return TRUE; } -static gboolean -emfv_popup_menu (GtkWidget *widget) -{ - gboolean ret = FALSE; - EMFolderView *emfv = (EMFolderView *)widget; - - /* Try to bring up menu for preview html object. - Currently we cannot directly connect to html's "popup_menu" signal - since it doesn't work. - */ - - if (GTK_WIDGET_HAS_FOCUS (emfv->preview->formathtml.html)) - ret = em_format_html_display_popup_menu (emfv->preview); - - if (!ret) - emfv_popup (emfv, NULL); - - return TRUE; -} - static void emfv_list_selection_change(ETree *tree, EMFolderView *emfv) { @@ -2212,32 +2124,38 @@ emfv_format_link_clicked(EMFormatHTMLDisplay *efhd, const char *uri, EMFolderVie } } +struct _EMFVPopupItem { + EMPopupItem item; + + EMFolderView *emfv; + char *uri; +}; + static void -emp_uri_popup_link_copy(EPopup *ep, EPopupItem *pitem, void *data) +emp_uri_popup_link_copy(GtkWidget *w, struct _EMFVPopupItem *item) { - EMFolderView *emfv = data; - struct _EMFolderViewPrivate *p = emfv->priv; + struct _EMFolderViewPrivate *p = item->emfv->priv; g_free(p->selection_uri); - p->selection_uri = g_strdup(pitem->user_data); + p->selection_uri = g_strdup(item->uri); 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()); } -static EPopupItem emfv_uri_popups[] = { - { E_POPUP_ITEM, "00.uri.01", N_("_Copy Link Location"), emp_uri_popup_link_copy, NULL, NULL, EM_POPUP_URI_NOT_MAILTO }, +static struct _EMFVPopupItem emfv_uri_popups[] = { + { { EM_POPUP_ITEM, "00.uri.01", N_("_Copy Link Location"), G_CALLBACK(emp_uri_popup_link_copy), NULL, NULL, EM_POPUP_URI_NOT_MAILTO }, }, }; static void -emfv_uri_popup_free(EPopup *ep, GSList *list, void *data) +emfv_uri_popup_free(GSList *list) { while (list) { GSList *n = list->next; - struct _EPopupItem *item = list->data; + struct _EMFVPopupItem *item = list->data; - g_free(item->user_data); - item->user_data = NULL; + g_free(item->uri); + g_object_unref(item->emfv); g_slist_free_1(list); list = n; @@ -2248,7 +2166,7 @@ static int emfv_format_popup_event(EMFormatHTMLDisplay *efhd, GdkEventButton *event, const char *uri, CamelMimePart *part, EMFolderView *emfv) { EMPopup *emp; - EPopupTarget *target; + EMPopupTarget *target; GtkMenu *menu; if (uri == NULL && part == NULL) { @@ -2265,47 +2183,27 @@ emfv_format_popup_event(EMFormatHTMLDisplay *efhd, GdkEventButton *event, const /* FIXME: this maybe should just fit on em-html-display, it has access to the snooped part type */ - /** @HookPoint-EMPopup: Inline URI Context Menu - * @Id: org.gnome.evolution.mail.folderview.popup - * @Class: org.gnome.evolution.mail.popup:1.0 - * @Target: EMPopupTargetURI - * - * This is the context menu shown when clicking on inline URIs, - * including addresses or normal HTML links that are displayed inside - * the message view. - */ - - /** @HookPoint-EMPopup: Inline Object Context Menu - * @Id: org.gnome.evolution.mail.folderview.popup - * @Class: org.gnome.evolution.mail.popup:1.0 - * @Target: EMPopupTargetPart - * - * This is the context menu shown when clicking on inline - * content such as a picture. - */ - emp = em_popup_new("org.gnome.evolution.mail.folderview.popup"); + emp = em_popup_new("com.ximian.mail.folderview.popup.uri"); if (part) - target = (EPopupTarget *)em_popup_target_new_part(emp, part, NULL); + target = em_popup_target_new_part(part, NULL); else { GSList *menus = NULL; int i; - EMPopupTargetURI *t; - t = em_popup_target_new_uri(emp, uri); - target = (EPopupTarget *)t; + target = em_popup_target_new_uri(uri); for (i=0;i<sizeof(emfv_uri_popups)/sizeof(emfv_uri_popups[0]);i++) { - emfv_uri_popups[i].user_data = g_strdup(t->uri); + emfv_uri_popups[i].item.activate_data = &emfv_uri_popups[i]; + emfv_uri_popups[i].emfv = emfv; + g_object_ref(emfv); + emfv_uri_popups[i].uri = g_strdup(target->data.uri); menus = g_slist_prepend(menus, &emfv_uri_popups[i]); } - e_popup_add_items((EPopup *)emp, menus, NULL, emfv_uri_popup_free, emfv); + em_popup_add_items(emp, menus, (GDestroyNotify)emfv_uri_popup_free); } - menu = e_popup_create_menu_once((EPopup *)emp, target, 0); - if (event == NULL) - 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, event->time); + menu = em_popup_create_menu_once(emp, target, target->mask, target->mask); + gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event->button, event->time); return TRUE; } diff --git a/mail/em-format-html-display.c b/mail/em-format-html-display.c index 6f74fa0495..0f539fb3f1 100644 --- a/mail/em-format-html-display.c +++ b/mail/em-format-html-display.c @@ -52,7 +52,12 @@ #include <glade/glade.h> #include <libgnomevfs/gnome-vfs-mime-handlers.h> -#include <libgnome/gnome-i18n.h> + +#if 0 +#include <libgnomevfs/gnome-vfs-utils.h> +#include <libgnomevfs/gnome-vfs-mime-utils.h> +#include <libgnomevfs/gnome-vfs-mime.h> +#endif #include <bonobo/bonobo-control-frame.h> #include <bonobo/bonobo-stream-memory.h> @@ -72,7 +77,7 @@ /* should this be in e-util rather than gal? */ #include <gal/util/e-util.h> -#include <libedataserver/e-msgport.h> +#include <e-util/e-msgport.h> #include <e-util/e-gui-utils.h> #include <e-util/e-dialog-utils.h> #include <e-util/e-icon-factory.h> @@ -612,41 +617,6 @@ efhd_html_button_press_event (GtkWidget *widget, GdkEventButton *event, EMFormat return res; } -gboolean -em_format_html_display_popup_menu (EMFormatHTMLDisplay *efhd) -{ - GtkHTML *html; - HTMLEngine *e; - HTMLObject *obj; - const char *url; - gboolean res = FALSE; - gint offset; - EMFormatPURI *puri = NULL; - char *uri = NULL; - - html = efhd->formathtml.html; - e = html->engine; - if (!efhd->caret_mode) - obj = html_engine_get_focus_object (e, &offset); - else { - obj = e->cursor->object; - offset = e->cursor->offset; - } - - if ( obj != NULL - && ((url = html_object_get_src(obj)) != NULL - || (url = html_object_get_url(obj, offset)) != NULL)) { - uri = gtk_html_get_url_object_relative(html, obj, url); - puri = em_format_find_puri((EMFormat *)efhd, uri); - } - - 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) { @@ -875,6 +845,7 @@ static gboolean efhd_xpkcs7mime_button(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject) { GtkWidget *icon, *button; + GdkPixbuf *pixbuf; struct _smime_pobject *po = (struct _smime_pobject *)pobject; const char *name; @@ -884,7 +855,10 @@ efhd_xpkcs7mime_button(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObje else name = smime_encrypt_table[po->valid->encrypt.status].icon; - icon = e_icon_factory_get_image (name, E_ICON_SIZE_LARGE_TOOLBAR); + pixbuf = e_icon_factory_get_icon (name, E_ICON_SIZE_LARGE_TOOLBAR); + + icon = gtk_image_new_from_pixbuf (pixbuf); + g_object_unref(pixbuf); gtk_widget_show(icon); button = gtk_button_new(); @@ -963,17 +937,19 @@ static const EMFormatHandler *efhd_find_handler(EMFormat *emf, const char *mime_ { 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)); + if (efhd_use_component(mime_type)) { + if ((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); + 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; + handle = h; + } + } else { + handle = ((EMFormatClass *)efhd_parent)->find_handler(emf, mime_type); } return handle; @@ -1074,35 +1050,21 @@ static void efhd_format_source(EMFormat *emf, CamelStream *stream, CamelMimePart /* if it hasn't been processed yet, format the attachment */ static void -efhd_attachment_show(EPopup *ep, EPopupItem *item, void *data) +efhd_attachment_show(GtkWidget *w, struct _attach_puri *info) { - struct _attach_puri *info = data; - d(printf("show attachment button called\n")); info->shown = ~info->shown; em_format_set_inline(info->puri.format, info->puri.part_id, info->shown); } -static void -efhd_attachment_button_show(GtkWidget *w, void *data) -{ - efhd_attachment_show(NULL, NULL, data); -} - -static EPopupItem efhd_menu_items[] = { - { E_POPUP_BAR, "05.display", }, - { E_POPUP_ITEM, "05.display.00", N_("_View Inline"), efhd_attachment_show }, - { E_POPUP_ITEM, "05.display.00", N_("_Hide"), efhd_attachment_show }, +static EMPopupItem efhd_menu_items[] = { + { EM_POPUP_BAR, "05.display", }, + { EM_POPUP_ITEM, "05.display.00", N_("_View Inline"), G_CALLBACK(efhd_attachment_show) }, + { EM_POPUP_ITEM, "05.display.00", N_("_Hide"), G_CALLBACK(efhd_attachment_show) }, }; static void -efhd_menu_items_free(EPopup *ep, GSList *items, void *data) -{ - g_slist_free(items); -} - -static void efhd_popup_place_widget(GtkMenu *menu, int *x, int *y, gboolean *push_in, gpointer user_data) { GtkWidget *w = user_data; @@ -1118,8 +1080,8 @@ efhd_attachment_popup(GtkWidget *w, GdkEventButton *event, struct _attach_puri * GtkMenu *menu; GSList *menus = NULL; EMPopup *emp; - EMPopupTargetPart *target; - EPopupItem *item; + EMPopupTarget *target; + EMPopupItem *item; d(printf("attachment popup, button %d\n", event->button)); @@ -1128,29 +1090,23 @@ efhd_attachment_popup(GtkWidget *w, GdkEventButton *event, struct _attach_puri * return FALSE; } - /** @HookPoint-EMPopup: Attachment Button Context Menu - * @Id: org.gnome.evolution.mail.formathtmldisplay.popup - * @Class: org.gnome.evolution.mail.popup:1.0 - * @Target: EMPopupTargetPart - * - * This is the drop-down menu shown when a user clicks on the down arrow - * of the attachment button in inline mail content. - */ - emp = em_popup_new("org.gnome.evolution.mail.formathtmldisplay.popup"); - target = em_popup_target_new_part(emp, info->puri.part, info->handle?info->handle->mime_type:NULL); - target->target.widget = w; + emp = em_popup_new("com.ximian.mail.formathtmldisplay.popup.part"); + target = em_popup_target_new_part(info->puri.part, info->handle?info->handle->mime_type:NULL); + target->widget = w; /* add our local menus */ if (info->handle) { /* show/hide menus, only if we have an inline handler */ + efhd_menu_items[0].activate_data = info; menus = g_slist_prepend(menus, &efhd_menu_items[0]); item = &efhd_menu_items[info->shown?2:1]; + item->activate_data = info; menus = g_slist_prepend(menus, item); } - e_popup_add_items((EPopup *)emp, menus, NULL, efhd_menu_items_free, info); + em_popup_add_items(emp, menus, (GDestroyNotify)g_slist_free); - menu = e_popup_create_menu_once((EPopup *)emp, (EPopupTarget *)target, 0); + menu = em_popup_create_menu_once(emp, target, target->mask, target->mask); if (event) gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event->button, event->time); else @@ -1255,7 +1211,6 @@ efhd_attachment_button(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObje { NULL, 0, 0 }, { "text/uri-list", 0, 1 }, }; - AtkObject *a11y; /* FIXME: handle default shown case */ d(printf("adding attachment button/content\n")); @@ -1269,7 +1224,7 @@ efhd_attachment_button(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObje button = gtk_button_new(); if (info->handle) - g_signal_connect(button, "clicked", G_CALLBACK(efhd_attachment_button_show), info); + g_signal_connect(button, "clicked", G_CALLBACK(efhd_attachment_show), info); else { gtk_widget_set_sensitive(button, FALSE); GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_FOCUS); @@ -1335,11 +1290,6 @@ efhd_attachment_button(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObje button = gtk_button_new(); /*GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_FOCUS);*/ gtk_container_add((GtkContainer *)button, gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE)); - - a11y = gtk_widget_get_accessible (button); - atk_object_set_name (a11y, _("Attachment Button")); - - g_signal_connect(button, "button_press_event", G_CALLBACK(efhd_attachment_popup), info); g_signal_connect(button, "popup_menu", G_CALLBACK(efhd_attachment_popup_menu), info); g_signal_connect(button, "clicked", G_CALLBACK(efhd_attachment_popup_menu), info); diff --git a/mail/em-format-html.c b/mail/em-format-html.c index 6a473eb0df..b8699bbac1 100644 --- a/mail/em-format-html.c +++ b/mail/em-format-html.c @@ -31,9 +31,9 @@ #include <fcntl.h> #include <ctype.h> -#include <libedataserver/e-iconv.h> -#include <libedataserver/e-util.h> /* for e_utf8_strftime, what about e_time_format_time? */ -#include <libedataserver/e-time-utils.h> +#include <gal/util/e-iconv.h> +#include <gal/util/e-util.h> /* for e_utf8_strftime, what about e_time_format_time? */ +#include "e-util/e-time-utils.h" #include "e-util/e-icon-factory.h" #include <gtkhtml/gtkhtml.h> @@ -41,7 +41,9 @@ #include <gtkhtml/gtkhtml-stream.h> #include <gtkhtml/htmlengine.h> -#include <libgnome/gnome-i18n.h> +#include <libgnomevfs/gnome-vfs-utils.h> +#include <libgnomevfs/gnome-vfs-mime-utils.h> +#include <libgnomevfs/gnome-vfs-mime-handlers.h> #include <camel/camel-mime-message.h> #include <camel/camel-stream.h> @@ -59,7 +61,7 @@ #include <camel/camel-data-cache.h> #include <camel/camel-file-utils.h> -#include <libedataserver/e-msgport.h> +#include <e-util/e-msgport.h> #include "mail-component.h" #include "mail-config.h" @@ -658,7 +660,9 @@ efh_text_plain(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFo struct _EMFormatHTMLCache *efhc; camel_stream_printf (stream, - "<div style=\"border: solid #%06x 1px; background-color: #%06x; padding: 10px;\">\n", + "<table bgcolor=\"#%06x\" cellspacing=0 cellpadding=1 width=100%%><tr><td>\n" + "<table bgcolor=\"#%06x\" cellspacing=0 cellpadding=0 width=100%%><tr><td>\n" + "<table cellspacing=0 cellpadding=10><td><tr>\n", efh->frame_colour & 0xffffff, efh->content_colour & 0xffffff); flags = efh->text_html_flags; @@ -740,7 +744,10 @@ efh_text_plain(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFo } camel_object_unref(filtered_stream); - camel_stream_write_string(stream, "</div>\n"); + camel_stream_write_string(stream, + "</td></tr></table>\n" + "</td></tr></table>\n" + "</td></tr></table>\n"); } static void @@ -766,13 +773,18 @@ efh_text_enriched(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, E camel_object_unref(enriched); camel_stream_printf (stream, - "<div style=\"border: solid #%06x 1px; background-color: #%06x; padding: 10px;\">\n", + "<table bgcolor=\"#%06x\" cellspacing=0 cellpadding=1 width=100%%><tr><td>\n" + "<table bgcolor=\"#%06x\" cellspacing=0 cellpadding=0 width=100%%><tr><td>\n" + "<table cellspacing=0 cellpadding=10><td><tr>\n", efh->frame_colour & 0xffffff, efh->content_colour & 0xffffff); em_format_format_text((EMFormat *)efh, (CamelStream *)filtered_stream, dw); camel_object_unref(filtered_stream); - camel_stream_write_string(stream, "</div>"); + camel_stream_write_string(stream, + "</td></tr></table>\n" + "</td></tr></table>\n" + "</td></tr></table>\n"); } static void @@ -789,7 +801,8 @@ efh_text_html(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFor char *cid = NULL; camel_stream_printf (stream, - "<div style=\"border: solid #%06x 1px; background-color: #%06x;\">\n" + "<table bgcolor=\"#%06x\" cellspacing=0 cellpadding=1 width=100%%><tr><td>\n" + "<table bgcolor=\"#%06x\" cellspacing=0 cellpadding=0 width=100%%><tr><td>\n" "<!-- text/html -->\n", efh->frame_colour & 0xffffff, efh->content_colour & 0xffffff); @@ -820,7 +833,8 @@ efh_text_html(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFor d(printf("adding iframe, location %s\n", cid)); camel_stream_printf(stream, "<iframe src=\"%s\" frameborder=0 scrolling=no>could not get %s</iframe>\n" - "</div>\n", + "</td></tr></table>\n" + "</td></tr></table>\n", cid, cid); g_free(cid); } @@ -924,7 +938,9 @@ efh_message_deliverystatus(EMFormatHTML *efh, CamelStream *stream, CamelMimePart /* Yuck, this is copied from efh_text_plain */ camel_stream_printf (stream, - "<div style=\"border: solid #%06x 1px; background-color: #%06x; padding: 10px;\">\n", + "<table bgcolor=\"#%06x\" cellspacing=0 cellpadding=1 width=100%%><tr><td>\n" + "<table bgcolor=\"#%06x\" cellspacing=0 cellpadding=0 width=100%%><tr><td>\n" + "<table cellspacing=0 cellpadding=10><td><tr>\n", efh->frame_colour & 0xffffff, efh->content_colour & 0xffffff); filtered_stream = camel_stream_filter_new_with_stream(stream); @@ -937,7 +953,10 @@ efh_message_deliverystatus(EMFormatHTML *efh, CamelStream *stream, CamelMimePart camel_stream_flush((CamelStream *)filtered_stream); camel_stream_write_string(stream, "</tt>\n"); - camel_stream_write_string(stream, "</div>"); + camel_stream_write_string(stream, + "</td></tr></table>\n" + "</td></tr></table>\n" + "</td></tr></table>\n"); } static void @@ -1401,9 +1420,9 @@ efh_format_text_header (EMFormatHTML *emfh, CamelStream *stream, const char *lab fmt = "<tr><td>%s: %s</td></tr>"; } else { if (flags & EM_FORMAT_HEADER_BOLD) - fmt = "<tr><th align=\"right\" valign=\"top\" nowrap>%s:<b> </b></th><td>%s</td></tr>"; + fmt = "<tr><th align=\"right\" valign=\"top\">%s:<b> </b></th><td>%s</td></tr>"; else - fmt = "<tr><td align=\"right\" valign=\"top\" nowrap>%s:<b> </b></td><td>%s</td></tr>"; + fmt = "<tr><td align=\"right\" valign=\"top\">%s:<b> </b></td><td>%s</td></tr>"; } } diff --git a/mail/em-format.c b/mail/em-format.c index e331a03493..0ad9057b81 100644 --- a/mail/em-format.c +++ b/mail/em-format.c @@ -31,9 +31,8 @@ #include <libgnomevfs/gnome-vfs-mime.h> #include <libgnomevfs/gnome-vfs-mime-utils.h> #include <libgnomevfs/gnome-vfs-mime-handlers.h> -#include <libgnome/gnome-i18n.h> -#include <libedataserver/e-msgport.h> +#include <e-util/e-msgport.h> #include <camel/camel-url.h> #include <camel/camel-stream.h> #include <camel/camel-stream-mem.h> @@ -202,10 +201,8 @@ em_format_get_type(void) * @emfc: EMFormatClass * @info: Callback information. * - * Add a mime type handler to this class. This is only used by - * implementing classes. The @info.old pointer will automatically be - * setup to point to the old hanlder if one was already set. This can - * be used for overrides a fallback. + * Add a mime type handler to this class. This is only used by implementing + * classes. * * When a mime type described by @info is encountered, the callback will * be invoked. Note that @info may be extended by sub-classes if @@ -216,39 +213,26 @@ em_format_get_type(void) void em_format_class_add_handler(EMFormatClass *emfc, EMFormatHandler *info) { - d(printf("adding format handler to '%s' '%s'\n", g_type_name_from_class((GTypeClass *)emfc), info->mime_type)); - info->old = g_hash_table_lookup(emfc->type_handlers, info->mime_type); g_hash_table_insert(emfc->type_handlers, info->mime_type, info); + /* FIXME: do we care? This is really gui stuff */ + /* + if (info->applications == NULL) + info->applications = gnome_vfs_mime_get_short_list_applications(info->mime_type);*/ } + /** * em_format_class_remove_handler: - * @emfc: - * @info: - * - * Remove a handler. @info must be a value which was previously - * added. + * @emfc: EMFormatClass + * @mime_type: mime-type of handler to remove + * + * Remove a mime type handler from this class. This is only used by + * implementing classes. **/ void -em_format_class_remove_handler(EMFormatClass *emfc, EMFormatHandler *info) +em_format_class_remove_handler (EMFormatClass *emfc, const char *mime_type) { - EMFormatHandler *current; - - /* TODO: thread issues? */ - - current = g_hash_table_lookup(emfc->type_handlers, info->mime_type); - if (current == info) { - current = info->old; - if (current) - g_hash_table_insert(emfc->type_handlers, current->mime_type, current); - else - g_hash_table_remove(emfc->type_handlers, info->mime_type); - } else { - while (current && current->old != info) - current = current->old; - g_return_if_fail(current != NULL); - current->old = info->old; - } + g_hash_table_remove (emfc->type_handlers, mime_type); } /** @@ -328,8 +312,6 @@ em_format_add_puri(EMFormat *emf, size_t size, const char *cid, CamelMimePart *p EMFormatPURI *puri; const char *tmp; - d(printf("adding puri for part: %s\n", emf->part_id->str)); - g_assert(size >= sizeof(*puri)); puri = g_malloc0(size); @@ -485,8 +467,6 @@ emf_clear_puri_node(struct _EMFormatPURITree *node) pw = (EMFormatPURI *)node->uri_list.head; pn = pw->next; while (pn) { - if (pw->free) - pw->free(pw); g_free(pw->uri); g_free(pw->cid); g_free(pw->part_id); @@ -1381,7 +1361,7 @@ emf_multipart_related(EMFormat *emf, CamelStream *stream, CamelMimePart *part, c g_string_printf(emf->part_id, "%s", puri->part_id); em_format_part(emf, stream, puri->part); } else - d(printf("unreferenced uri generated by format code: %s\n", puri->uri?puri->uri:puri->cid)); + printf("unreferenced uri generated by format code: %s\n", puri->uri?puri->uri:puri->cid); } puri = purin; purin = purin->next; diff --git a/mail/em-format.h b/mail/em-format.h index a822809bc1..4cdfbdd66a 100644 --- a/mail/em-format.h +++ b/mail/em-format.h @@ -28,7 +28,7 @@ #define _EM_FORMAT_H #include <glib-object.h> -#include "libedataserver/e-msgport.h" +#include "e-util/e-msgport.h" struct _CamelStream; struct _CamelMimePart; @@ -53,70 +53,25 @@ typedef enum _em_format_mode_t { EM_FORMAT_SOURCE, } em_format_mode_t; -/** - * struct _EMFormatHandler - MIME type handler. - * - * @mime_type: Type this handler handles. - * @handler: The handler callback. - * @flags: Handling flags, see enum _em_format_handler_t. - * @old: The last handler set on this type. Allows overrides to - * fallback to previous implementation. - * - **/ +/* can be subclassed/extended ... */ struct _EMFormatHandler { char *mime_type; EMFormatFunc handler; guint32 flags; - - struct _EMFormatHandler *old; -}; - -/** - * enum _em_format_handler_t - Format handler flags. - * - * @EM_FORMAT_HANDLER_INLINE: This type should be shown expanded - * inline by default. - * @EM_FORMAT_HANDLER_INLINE_DISPOSITION: This type should always be - * shown inline, despite what the Content-Disposition suggests. - * - **/ -enum _em_format_handler_t { - EM_FORMAT_HANDLER_INLINE = 1<<0, - EM_FORMAT_HANDLER_INLINE_DISPOSITION = 1<<1, + GList *applications; /* gnome vfs short-list of applications, do we care? */ }; +/* inline by default */ +#define EM_FORMAT_HANDLER_INLINE (1<<0) +/* inline by default, and override content-disposition always */ +#define EM_FORMAT_HANDLER_INLINE_DISPOSITION (1<<1) typedef struct _EMFormatPURI EMFormatPURI; typedef void (*EMFormatPURIFunc)(EMFormat *md, struct _CamelStream *stream, EMFormatPURI *puri); -/** - * struct _EMFormatPURI - Pending URI object. - * - * @next: Double-linked list header. - * @prev: Double-linked list header. - * @free: May be set by allocator and will be called when no longer needed. - * @format: - * @uri: Calculated URI of the part, if the part has one in its - * Content-Location field. - * @cid: The RFC2046 Content-Id of the part. If none is present, a unique value - * is calculated from @part_id. - * @part_id: A unique identifier for each part. - * @func: Callback for when the URI is requested. The callback writes - * its data to the supplied stream. - * @part: - * @use_count: - * - * This is used for multipart/related, and other formatters which may - * need to include a reference to out-of-band data in the content - * stream. - * - * This object may be subclassed as a struct. - **/ struct _EMFormatPURI { - struct _EMFormatPURI *next; - struct _EMFormatPURI *prev; + struct _EMFormatPURI *next, *prev; - void (*free)(struct _EMFormatPURI *p); /* optional callback for freeing user-fields */ struct _EMFormat *format; char *uri; /* will be the location of the part, may be empty */ @@ -129,23 +84,9 @@ struct _EMFormatPURI { unsigned int use_count; /* used by multipart/related to see if it was accessed */ }; -/** - * struct _EMFormatPURITree - Pending URI visibility tree. - * - * @next: Double-linked list header. - * @prev: Double-linked list header. - * @parent: Parent in tree. - * @uri_list: List of EMFormatPURI objects at this level. - * @children: Child nodes of EMFormatPURITree. - * - * This structure is used internally to form a visibility tree of - * parts in the current formatting stream. This is to implement the - * part resolution rules for RFC2387 to implement multipart/related. - **/ +/* used to stack pending uri's for visibility (multipart/related) */ struct _EMFormatPURITree { - struct _EMFormatPURITree *next; - struct _EMFormatPURITree *prev; - struct _EMFormatPURITree *parent; + struct _EMFormatPURITree *next, *prev, *parent; EDList uri_list; EDList children; @@ -161,34 +102,6 @@ struct _EMFormatHeader { #define EM_FORMAT_HEADER_BOLD (1<<0) #define EM_FORMAT_HEADER_LAST (1<<4) /* reserve 4 slots */ -/** - * struct _EMFormat - Mail formatter object. - * - * @parent: - * @priv: - * @message: - * @folder: - * @uid: - * @part_id: - * @header_list: - * @session: - * @base url: - * @snoop_mime_type: - * @valid: - * @valid_parent: - * @inline_table: - * @pending_uri_table: - * @pending_uri_tree: - * @pending_uri_level: - * @mode: - * @charset: - * @default_charset: - * - * Most fields are private or read-only. - * - * This is the base MIME formatter class. It provides no formatting - * itself, but drives most of the basic types, including multipart / * types. - **/ struct _EMFormat { GObject parent; @@ -287,7 +200,7 @@ char *em_format_describe_part(struct _CamelMimePart *part, const char *mimetype) 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); +void em_format_class_remove_handler (EMFormatClass *emfc, const char *mime_type); #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); diff --git a/mail/em-junk-filter.c b/mail/em-junk-filter.c index 78fe042fdb..5885e5d0d6 100644 --- a/mail/em-junk-filter.c +++ b/mail/em-junk-filter.c @@ -33,37 +33,26 @@ #include <signal.h> #include <string.h> #include <pthread.h> -#include <signal.h> -#include <time.h> -#include <camel/camel-debug.h> #include <camel/camel-file-utils.h> #include <camel/camel-data-wrapper.h> #include <camel/camel-stream-fs.h> -#include <camel/camel-stream-mem.h> -#include <camel/camel-i18n.h> -#include <e-util/e-mktemp.h> #include "mail-session.h" #include "em-junk-filter.h" #include <gconf/gconf-client.h> -#define d(x) (camel_debug("junk")?(x):0) +#define d(x) x static pthread_mutex_t em_junk_sa_init_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t em_junk_sa_report_lock = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t em_junk_sa_preferred_socket_path_lock = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t em_junk_sa_spamd_restart_lock = PTHREAD_MUTEX_INITIALIZER; static const char *em_junk_sa_get_name (void); static gboolean em_junk_sa_check_junk (CamelMimeMessage *msg); static void em_junk_sa_report_junk (CamelMimeMessage *msg); static void em_junk_sa_report_notjunk (CamelMimeMessage *msg); static void em_junk_sa_commit_reports (void); -static void em_junk_sa_init (void); -static void em_junk_sa_finalize (void); -static void em_junk_sa_kill_spamd (void); static EMJunkPlugin spam_assassin_plugin = { { @@ -73,7 +62,6 @@ static EMJunkPlugin spam_assassin_plugin = { em_junk_sa_report_junk, em_junk_sa_report_notjunk, em_junk_sa_commit_reports, - em_junk_sa_init, }, NULL, NULL @@ -83,24 +71,14 @@ static gboolean em_junk_sa_tested = FALSE; static gboolean em_junk_sa_spamd_tested = FALSE; static gboolean em_junk_sa_use_spamc = FALSE; static gboolean em_junk_sa_available = FALSE; -static gboolean em_junk_sa_system_spamd_available = FALSE; -static gboolean em_junk_sa_new_daemon_started = FALSE; -static char *em_junk_sa_socket_path = NULL; -static char *em_junk_sa_spamd_pidfile = NULL; +static int em_junk_sa_spamd_port = -1; static char *em_junk_sa_spamc_binary = NULL; static GConfClient *em_junk_sa_gconf = NULL; /* volatile so not cached between threads */ static volatile gboolean em_junk_sa_local_only; static volatile gboolean em_junk_sa_use_daemon; -static char * em_junk_sa_preferred_socket_path; - -static char *em_junk_sa_spamc_binaries [3] = {"spamc", "/usr/sbin/spamc", NULL}; -static char *em_junk_sa_spamd_binaries [3] = {"spamd", "/usr/sbin/spamd", NULL}; - -#define SPAMD_RESTARTS_SIZE 8 -static time_t em_junk_sa_spamd_restarts [SPAMD_RESTARTS_SIZE] = {0, 0, 0, 0, 0, 0, 0, 0}; -static int em_junk_sa_spamd_restarts_count = 0; +static volatile int em_junk_sa_daemon_port; char *em_junk_sa_spamc_gconf_binary = NULL; char *em_junk_sa_spamd_gconf_binary = NULL; @@ -112,23 +90,23 @@ em_junk_sa_get_name (void) } static int -pipe_to_sa_full (CamelMimeMessage *msg, const char *in, char **argv, int rv_err, int wait_for_termination, GByteArray *output_buffer) +pipe_to_sa_with_error (CamelMimeMessage *msg, const char *in, char **argv, int rv_err) { - int result, status, errnosav, fds[2], out_fds[2]; + int result, status, errnosav, fds[2]; CamelStream *stream; char *program; pid_t pid; - - if (camel_debug_start ("junk")) { +#if d(!)0 + { int i; printf ("pipe_to_sa "); for (i = 0; argv[i]; i++) printf ("%s ", argv[i]); printf ("\n"); - camel_debug_end (); } +#endif program = g_find_program_in_path (argv [0]); if (program == NULL) { @@ -144,13 +122,6 @@ pipe_to_sa_full (CamelMimeMessage *msg, const char *in, char **argv, int rv_err, return rv_err; } - if (output_buffer && pipe (out_fds) == -1) { - errnosav = errno; - d(printf ("failed to create a pipe (for use with spamassassin: %s\n", strerror (errno))); - errno = errnosav; - return rv_err; - } - if (!(pid = fork ())) { /* child process */ int maxfd, fd, nullfd; @@ -158,14 +129,10 @@ pipe_to_sa_full (CamelMimeMessage *msg, const char *in, char **argv, int rv_err, nullfd = open ("/dev/null", O_WRONLY); if (dup2 (fds[0], STDIN_FILENO) == -1 || - dup2 (nullfd, STDERR_FILENO) == -1 || - (output_buffer == NULL && dup2 (nullfd, STDOUT_FILENO) == -1) || - (output_buffer != NULL && dup2 (out_fds[1], STDOUT_FILENO) == -1)) + dup2 (nullfd, STDOUT_FILENO) == -1 || + dup2 (nullfd, STDERR_FILENO) == -1) _exit (rv_err & 0377); - close (fds [0]); - if (output_buffer) - close (out_fds [1]); - + setsid (); maxfd = sysconf (_SC_OPEN_MAX); @@ -184,8 +151,6 @@ pipe_to_sa_full (CamelMimeMessage *msg, const char *in, char **argv, int rv_err, /* parent process */ close (fds[0]); - if (output_buffer) - close (out_fds [1]); if (msg) { stream = camel_stream_fs_new_with_fd (fds[1]); @@ -198,92 +163,54 @@ pipe_to_sa_full (CamelMimeMessage *msg, const char *in, char **argv, int rv_err, camel_write (fds[1], in, strlen (in)); close (fds[1]); } - - if (output_buffer) { - CamelStreamMem *memstream; - - stream = camel_stream_fs_new_with_fd (out_fds[0]); - - memstream = (CamelStreamMem *) camel_stream_mem_new (); - camel_stream_mem_set_byte_array (memstream, output_buffer); - - camel_stream_write_to_stream (stream, (CamelStream *) memstream); - camel_object_unref (stream); - g_byte_array_append (output_buffer, "", 1); - - d(printf ("child process output: %s len: %d\n", output_buffer->data, output_buffer->len)); - } - if (wait_for_termination) { - d(printf ("wait for child %d termination\n", pid)); - result = waitpid (pid, &status, 0); + result = waitpid (pid, &status, 0); - d(printf ("child %d terminated with result %d status %d exited %d exitstatus %d\n", pid, result, status, WIFEXITED (status), WEXITSTATUS (status))); - - if (result == -1 && errno == EINTR) { - /* child process is hanging... */ - kill (pid, SIGTERM); + 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); - if (result == 0) { - /* ...still hanging, set phasers to KILL */ - kill (pid, SIGKILL); - sleep (1); - result = waitpid (pid, &status, WNOHANG); - } } + } - if (result != -1 && WIFEXITED (status)) - return WEXITSTATUS (status); - else - return rv_err; - } else - return 0; + if (result != -1 && WIFEXITED (status)) + return WEXITSTATUS (status); + else + return rv_err; } static int pipe_to_sa (CamelMimeMessage *msg, const char *in, char **argv) { - return pipe_to_sa_full (msg, in, argv, -1, 1, NULL); -} - -static char * -em_junk_sa_get_socket_path () -{ - if (em_junk_sa_preferred_socket_path) - return em_junk_sa_preferred_socket_path; - else - return em_junk_sa_socket_path; + return pipe_to_sa_with_error (msg, in, argv, -1); } static gboolean -em_junk_sa_test_spamd_running (char *binary, gboolean system) +em_junk_sa_test_spamd_running (char *binary, int port) { - char *argv[5]; + char port_buf[12], *argv[5]; int i = 0; - gboolean rv; - - pthread_mutex_lock (&em_junk_sa_preferred_socket_path_lock); - - d(fprintf (stderr, "test if spamd is running (system %d) or using socket path %s\n", system, em_junk_sa_get_socket_path ())); + + d(fprintf (stderr, "test if spamd is running (port %d) using %s\n", port, binary)); argv[i++] = binary; argv[i++] = "-x"; - if (!system) { - argv[i++] = "-U"; - argv[i++] = em_junk_sa_get_socket_path (); + if (port > 0) { + sprintf (port_buf, "%d", port); + argv[i++] = "-p"; + argv[i++] = port_buf; } argv[i] = NULL; - rv = pipe_to_sa (NULL, "From test@127.0.0.1", argv) == 0; - - d(fprintf (stderr, "result: %d (%s)\n", rv, rv ? "success" : "failed")); - - pthread_mutex_unlock (&em_junk_sa_preferred_socket_path_lock); - - return rv; + return pipe_to_sa (NULL, "From test@127.0.0.1", argv) == 0; } static void @@ -306,93 +233,37 @@ em_junk_sa_test_spamassassin (void) #define MAX_SPAMD_PORTS 1 static gboolean -em_junk_sa_run_spamd (char *binary) +em_junk_sa_run_spamd (char *binary, int *port) { - char *argv[8]; - int i; - gboolean rv = FALSE; - - pthread_mutex_lock (&em_junk_sa_preferred_socket_path_lock); + char *argv[6]; + char port_buf[12]; + int i, p = em_junk_sa_daemon_port; d(fprintf (stderr, "looks like spamd is not running\n")); i = 0; argv[i++] = binary; - argv[i++] = "--socketpath"; - argv[i++] = em_junk_sa_get_socket_path (); + argv[i++] = "--port"; + argv[i++] = port_buf; if (em_junk_sa_local_only) argv[i++] = "--local"; - //argv[i++] = "--daemonize"; - argv[i++] = "--pidfile"; - argv[i++] = em_junk_sa_spamd_pidfile; + argv[i++] = "--daemonize"; argv[i] = NULL; - - d(fprintf (stderr, "trying to run %s with socket path %s\n", binary, em_junk_sa_get_socket_path ())); + + for (i = 0; i < MAX_SPAMD_PORTS; i++, p++) { + d(fprintf (stderr, "trying to run %s at port %d\n", binary, p)); - if (!pipe_to_sa_full (NULL, NULL, argv, -1, 0, NULL)) { - int i; - struct timespec time_req; - struct stat stat_buf; - - d(fprintf (stderr, "success\n")); - d(fprintf (stderr, "waiting for spamd to come up\n")); - - time_req.tv_sec = 0; - time_req.tv_nsec = 50000000; - - for (i = 0; i < 100; i ++) { - if (stat (em_junk_sa_get_socket_path (), &stat_buf) == 0) { - d(fprintf (stderr, "socket created\n")); - break; - } - nanosleep (&time_req, NULL); + snprintf (port_buf, 11, "%d", p); + if (!pipe_to_sa (NULL, NULL, argv)) { + d(fprintf (stderr, "success at port %d\n", p)); + *port = p; + return TRUE; } - d(fprintf (stderr, "waiting is over (after %dms)\n", 50*i)); - - rv = TRUE; } - pthread_mutex_unlock (&em_junk_sa_preferred_socket_path_lock); - - return rv; -} - -static void -em_junk_sa_start_own_daemon () -{ - int b; - - em_junk_sa_new_daemon_started = FALSE; - - em_junk_sa_socket_path = e_mktemp ("spamd-socket-path-XXXXXX"); - em_junk_sa_spamd_pidfile = e_mktemp ("spamd-pid-file-XXXXXX"); - - for (b = 0; em_junk_sa_spamd_binaries [b]; b ++) { - em_junk_sa_use_spamc = em_junk_sa_run_spamd (em_junk_sa_spamd_binaries [b]); - if (em_junk_sa_use_spamc) { - em_junk_sa_new_daemon_started = TRUE; - break; - } - } -} - -static void -em_junk_sa_find_spamc () -{ - if (em_junk_sa_use_spamc && em_junk_sa_new_daemon_started) { - int b; - - em_junk_sa_use_spamc = FALSE; - for (b = 0; em_junk_sa_spamc_binaries [b]; b ++) { - em_junk_sa_spamc_binary = em_junk_sa_spamc_binaries [b]; - if (em_junk_sa_test_spamd_running (em_junk_sa_spamc_binary, FALSE)) { - em_junk_sa_use_spamc = TRUE; - break; - } - } - } + return FALSE; } static void @@ -401,17 +272,20 @@ em_junk_sa_test_spamd (void) char *argv[4]; int i, b; gboolean try_system_spamd = TRUE; + gboolean new_daemon_started = FALSE; + char *spamc_binaries [3] = {"spamc", "/usr/sbin/spamc", NULL}; + char *spamd_binaries [3] = {"spamd", "/usr/sbin/spamd", NULL}; if (em_junk_sa_spamc_gconf_binary) { - em_junk_sa_spamc_binaries [0] = em_junk_sa_spamc_gconf_binary; - em_junk_sa_spamc_binaries [1] = NULL; + spamc_binaries [0] = em_junk_sa_spamc_gconf_binary; + spamc_binaries [1] = NULL; } - + if (em_junk_sa_spamd_gconf_binary) { - em_junk_sa_spamd_binaries [0] = em_junk_sa_spamd_gconf_binary; - em_junk_sa_spamd_binaries [1] = NULL; + spamd_binaries [0] = em_junk_sa_spamd_gconf_binary; + spamd_binaries [1] = NULL; try_system_spamd = FALSE; - } + } em_junk_sa_use_spamc = FALSE; @@ -430,36 +304,55 @@ em_junk_sa_test_spamd (void) /* try to use sytem spamd first */ if (try_system_spamd) { - for (b = 0; em_junk_sa_spamc_binaries [b]; b ++) { - em_junk_sa_spamc_binary = em_junk_sa_spamc_binaries [b]; - if (em_junk_sa_test_spamd_running (em_junk_sa_spamc_binary, TRUE)) { + for (b = 0; spamc_binaries [b]; b ++) { + em_junk_sa_spamc_binary = spamc_binaries [b]; + if (em_junk_sa_test_spamd_running (em_junk_sa_spamc_binary, -1)) { em_junk_sa_use_spamc = TRUE; - em_junk_sa_system_spamd_available = TRUE; + em_junk_sa_spamd_port = -1; break; } } } - /* if there's no system spamd running, try to use user one with user specified socket */ - if (!em_junk_sa_use_spamc && em_junk_sa_preferred_socket_path) { - for (b = 0; em_junk_sa_spamc_binaries [b]; b ++) { - em_junk_sa_spamc_binary = em_junk_sa_spamc_binaries [b]; - if (em_junk_sa_test_spamd_running (em_junk_sa_spamc_binary, FALSE)) { - em_junk_sa_use_spamc = TRUE; - em_junk_sa_system_spamd_available = FALSE; - break; + /* if there's no system spamd running, try to use user one on evo spamd port */ + if (!em_junk_sa_use_spamc) { + int port = em_junk_sa_daemon_port; + + for (i = 0; i < MAX_SPAMD_PORTS; i ++, port ++) { + for (b = 0; spamc_binaries [b]; b ++) { + em_junk_sa_spamc_binary = spamc_binaries [b]; + if (em_junk_sa_test_spamd_running (em_junk_sa_spamc_binary, port)) { + em_junk_sa_use_spamc = TRUE; + em_junk_sa_spamd_port = port; + break; + } } } } /* unsuccessful? try to run one ourselfs */ if (!em_junk_sa_use_spamc) - em_junk_sa_start_own_daemon (); - + for (b = 0; spamd_binaries [b]; b ++) { + em_junk_sa_use_spamc = em_junk_sa_run_spamd (spamd_binaries [b], &em_junk_sa_spamd_port); + if (em_junk_sa_use_spamc) { + new_daemon_started = TRUE; + break; + } + } + /* new daemon started => let find spamc binary */ - em_junk_sa_find_spamc (); + if (em_junk_sa_use_spamc && new_daemon_started) { + em_junk_sa_use_spamc = FALSE; + for (b = 0; spamc_binaries [b]; b ++) { + em_junk_sa_spamc_binary = spamc_binaries [b]; + if (em_junk_sa_test_spamd_running (em_junk_sa_spamc_binary, em_junk_sa_spamd_port)) { + em_junk_sa_use_spamc = TRUE; + break; + } + } + } - d(fprintf (stderr, "use spamd: %s\n", em_junk_sa_use_spamc ? "yes" : "no")); + d(fprintf (stderr, "use spamd %d at port %d with %s\n", em_junk_sa_use_spamc, em_junk_sa_spamd_port, em_junk_sa_spamc_binary)); em_junk_sa_spamd_tested = TRUE; } @@ -481,84 +374,23 @@ em_junk_sa_is_available (void) } static gboolean -em_junk_sa_check_respawn_too_fast () -{ - time_t time_now = time (NULL); - gboolean rv; - - pthread_mutex_lock (&em_junk_sa_spamd_restart_lock); - - if (em_junk_sa_spamd_restarts_count >= SPAMD_RESTARTS_SIZE) { - /* all restarts in last 5 minutes */ - rv = (time_now - em_junk_sa_spamd_restarts [em_junk_sa_spamd_restarts_count % SPAMD_RESTARTS_SIZE] < 5*60); - } else - rv = FALSE; - - em_junk_sa_spamd_restarts [em_junk_sa_spamd_restarts_count % SPAMD_RESTARTS_SIZE] = time_now; - em_junk_sa_spamd_restarts_count ++; - - pthread_mutex_unlock (&em_junk_sa_spamd_restart_lock); - - d(printf ("em_junk_sa_check_respawn_too_fast: %d\n", rv)); - - return rv; -} - -static gboolean -em_junk_sa_respawn_spamd () -{ - d(printf ("em_junk_sa_respawn_spamd\n")); - if (em_junk_sa_test_spamd_running (em_junk_sa_spamc_binary, em_junk_sa_system_spamd_available)) { - /* false alert */ - d(printf ("false alert, spamd still running\n")); - - return FALSE; - } - - d(printf ("going to kill old spamd and start new one\n")); - em_junk_sa_kill_spamd (); - - if (em_junk_sa_check_respawn_too_fast ()) { - g_warning ("respawning of spamd too fast => fallback to use spamassassin directly"); - - em_junk_sa_use_spamc = em_junk_sa_use_daemon = FALSE; - return FALSE; - } - - em_junk_sa_start_own_daemon (); - em_junk_sa_find_spamc (); - - d(printf ("%s\n", em_junk_sa_use_spamc ? "success" : "failed")); - - return em_junk_sa_use_spamc; -} - -static gboolean em_junk_sa_check_junk (CamelMimeMessage *msg) { - GByteArray *out = NULL; - char *argv[7], *to_free = NULL; - int i = 0, socket_i; - gboolean rv; - + char *argv[5], buf[12]; + int i = 0; + d(fprintf (stderr, "em_junk_sa_check_junk\n")); if (!em_junk_sa_is_available ()) return FALSE; - + if (em_junk_sa_use_spamc && em_junk_sa_use_daemon) { - out = g_byte_array_new (); argv[i++] = em_junk_sa_spamc_binary; argv[i++] = "-c"; - argv[i++] = "-t"; - argv[i++] = "60"; - if (!em_junk_sa_system_spamd_available) { - argv[i++] = "-U"; - - pthread_mutex_lock (&em_junk_sa_preferred_socket_path_lock); - socket_i = i; - argv[i++] = to_free = g_strdup (em_junk_sa_get_socket_path ()); - pthread_mutex_unlock (&em_junk_sa_preferred_socket_path_lock); + if (em_junk_sa_spamd_port != -1) { + sprintf (buf, "%d", em_junk_sa_spamd_port); + argv[i++] = "-p"; + argv[i++] = buf; } } else { argv [i++] = "spamassassin"; @@ -569,32 +401,7 @@ em_junk_sa_check_junk (CamelMimeMessage *msg) argv[i] = NULL; - rv = pipe_to_sa_full (msg, NULL, argv, 0, 1, out) != 0; - - if (!rv && out && !strcmp (out->data, "0/0\n")) { - /* an error occured */ - if (em_junk_sa_respawn_spamd ()) { - g_byte_array_set_size (out, 0); - - pthread_mutex_lock (&em_junk_sa_preferred_socket_path_lock); - g_free (to_free); - argv [socket_i] = to_free = g_strdup (em_junk_sa_get_socket_path ()); - pthread_mutex_unlock (&em_junk_sa_preferred_socket_path_lock); - - rv = pipe_to_sa_full (msg, NULL, argv, 0, 1, out) != 0; - } else if (!em_junk_sa_use_spamc) - /* in case respawning were too fast we fallback to spamassassin */ - rv = em_junk_sa_check_junk (msg); - } - - g_free (to_free); - - d(fprintf (stderr, "em_junk_sa_check_junk rv = %d\n", rv)); - - if (out) - g_byte_array_free (out, TRUE); - - return rv; + return pipe_to_sa_with_error (msg, NULL, argv, 0) != 0; } static void @@ -685,23 +492,13 @@ em_junk_sa_setting_notify(GConfClient *gconf, guint cnxn_id, GConfEntry *entry, em_junk_sa_local_only = gconf_value_get_bool(value); else if (!strcmp(tkey, "use_daemon")) em_junk_sa_use_daemon = gconf_value_get_bool(value); - else if (!strcmp(tkey, "socket_path")) { - pthread_mutex_lock (&em_junk_sa_preferred_socket_path_lock); - g_free (em_junk_sa_preferred_socket_path); - em_junk_sa_preferred_socket_path = g_strdup (gconf_value_get_string(value)); - pthread_mutex_unlock (&em_junk_sa_preferred_socket_path_lock); - } + else if (!strcmp(tkey, "daemon_port")) + em_junk_sa_daemon_port = gconf_value_get_int(value); } const EMJunkPlugin * em_junk_filter_get_plugin (void) { - return &spam_assassin_plugin; -} - -static void -em_junk_sa_init (void) -{ pthread_mutex_lock (&em_junk_sa_init_lock); if (!em_junk_sa_gconf) { @@ -710,11 +507,7 @@ em_junk_sa_init (void) em_junk_sa_local_only = gconf_client_get_bool (em_junk_sa_gconf, "/apps/evolution/mail/junk/sa/local_only", NULL); em_junk_sa_use_daemon = gconf_client_get_bool (em_junk_sa_gconf, "/apps/evolution/mail/junk/sa/use_daemon", NULL); - - pthread_mutex_lock (&em_junk_sa_preferred_socket_path_lock); - g_free (em_junk_sa_preferred_socket_path); - em_junk_sa_preferred_socket_path = g_strdup (gconf_client_get_string (em_junk_sa_gconf, "/apps/evolution/mail/junk/sa/socket_path", NULL)); - pthread_mutex_unlock (&em_junk_sa_preferred_socket_path_lock); + em_junk_sa_daemon_port = gconf_client_get_int (em_junk_sa_gconf, "/apps/evolution/mail/junk/sa/daemon_port", NULL); gconf_client_notify_add(em_junk_sa_gconf, "/apps/evolution/mail/junk/sa", (GConfClientNotifyFunc)em_junk_sa_setting_notify, @@ -726,47 +519,5 @@ em_junk_sa_init (void) pthread_mutex_unlock (&em_junk_sa_init_lock); - atexit (em_junk_sa_finalize); -} - -static void -em_junk_sa_kill_spamd (void) -{ - pthread_mutex_lock (&em_junk_sa_preferred_socket_path_lock); - g_free (em_junk_sa_preferred_socket_path); - em_junk_sa_preferred_socket_path = NULL; - pthread_mutex_unlock (&em_junk_sa_preferred_socket_path_lock); - - if (em_junk_sa_new_daemon_started) { - int fd = open (em_junk_sa_spamd_pidfile, O_RDONLY); - - if (fd != -1) { - char pid_str [16]; - int bytes; - - bytes = read (fd, pid_str, 15); - if (bytes > 0) { - int pid; - - pid_str [bytes] = 0; - pid = atoi (pid_str); - - if (pid > 0) { - kill (pid, SIGTERM); - d(fprintf (stderr, "em_junk_sa_finalize send SIGTERM to daemon with pid %d\n", pid)); - waitpid (pid, NULL, 0); - } - } - - close (fd); - } - } -} - -static void -em_junk_sa_finalize (void) -{ - d(fprintf (stderr, "em_junk_sa_finalize\n")); - - em_junk_sa_kill_spamd (); + return &spam_assassin_plugin; } diff --git a/mail/em-message-browser.c b/mail/em-message-browser.c index caf93e7e41..4f3a2aaa2c 100644 --- a/mail/em-message-browser.c +++ b/mail/em-message-browser.c @@ -41,7 +41,6 @@ #include "em-format-html-display.h" #include "em-message-browser.h" -#include "em-menu.h" #include "evolution-shell-component-utils.h" /* Pixmap stuff, sigh */ @@ -176,15 +175,6 @@ GtkWidget *em_message_browser_new(void) { EMMessageBrowser *emmb = g_object_new(em_message_browser_get_type(), 0); - /** @HookPoint-EMMenu: Standalone Mssage 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. - */ - ((EMFolderView *)emmb)->menu = em_menu_new("org.gnome.evolution.mail.messagebrowser"); - return (GtkWidget *)emmb; } diff --git a/mail/em-migrate.c b/mail/em-migrate.c index d2c9c1909c..87d200e2b8 100644 --- a/mail/em-migrate.c +++ b/mail/em-migrate.c @@ -42,7 +42,6 @@ #include <libgnome/gnome-config.h> #include <camel/camel.h> -#include <camel/camel-store.h> #include <camel/camel-session.h> #include <camel/camel-file-utils.h> #include <camel/camel-disco-folder.h> @@ -54,12 +53,13 @@ #include <libgnome/gnome-i18n.h> #include <gal/util/e-util.h> -#include <libedataserver/e-iconv.h> +#include <gal/util/e-iconv.h> #include <gal/util/e-xml-utils.h> #include "e-util/e-bconf-map.h" #include "e-util/e-account-list.h" #include "e-util/e-signature-list.h" +#include "e-util/e-path.h" #include "widgets/misc/e-error.h" #include "mail-config.h" @@ -2315,84 +2315,6 @@ em_migrate_folder_view_settings_1_4 (const char *evolution_dir, CamelException * return 0; } -#define SUBFOLDER_DIR_NAME "subfolders" -#define SUBFOLDER_DIR_NAME_LEN 10 - -static char * -e_path_to_physical (const char *prefix, const char *vpath) -{ - const char *p, *newp; - char *dp; - char *ppath; - int ppath_len; - int prefix_len; - - while (*vpath == '/') - vpath++; - if (!prefix) - prefix = ""; - - /* Calculate the length of the real path. */ - ppath_len = strlen (vpath); - ppath_len++; /* For the ending zero. */ - - prefix_len = strlen (prefix); - ppath_len += prefix_len; - ppath_len++; /* For the separating slash. */ - - /* Take account of the fact that we need to translate every - * separator into `subfolders/'. - */ - p = vpath; - while (1) { - newp = strchr (p, '/'); - if (newp == NULL) - break; - - ppath_len += SUBFOLDER_DIR_NAME_LEN; - ppath_len++; /* For the separating slash. */ - - /* Skip consecutive slashes. */ - while (*newp == '/') - newp++; - - p = newp; - }; - - ppath = g_malloc (ppath_len); - dp = ppath; - - memcpy (dp, prefix, prefix_len); - dp += prefix_len; - *(dp++) = '/'; - - /* Copy the mangled path. */ - p = vpath; - while (1) { - newp = strchr (p, '/'); - if (newp == NULL) { - strcpy (dp, p); - break; - } - - memcpy (dp, p, newp - p + 1); /* `+ 1' to copy the slash too. */ - dp += newp - p + 1; - - memcpy (dp, SUBFOLDER_DIR_NAME, SUBFOLDER_DIR_NAME_LEN); - dp += SUBFOLDER_DIR_NAME_LEN; - - *(dp++) = '/'; - - /* Skip consecutive slashes. */ - while (*newp == '/') - newp++; - - p = newp; - } - - return ppath; -} - static int em_migrate_imap_cmeta_1_4(const char *evolution_dir, CamelException *ex) { @@ -2481,7 +2403,6 @@ em_migrate_1_4 (const char *evolution_dir, xmlDocPtr filters, xmlDocPtr vfolders path = g_build_filename (evolution_dir, "mail", NULL); camel_init (path, TRUE); - camel_provider_init(); session = (EMMigrateSession *) em_migrate_session_new (path); g_free (path); diff --git a/mail/em-popup.c b/mail/em-popup.c index bf3a017097..28e5121c51 100644 --- a/mail/em-popup.c +++ b/mail/em-popup.c @@ -40,10 +40,9 @@ #include <libgnome/gnome-url.h> #include <libgnomevfs/gnome-vfs-mime.h> -#include <libgnome/gnome-i18n.h> #include "em-popup.h" -#include "libedataserver/e-msgport.h" +#include "e-util/e-msgport.h" #include <e-util/e-icon-factory.h> #include "em-utils.h" #include "em-composer-utils.h" @@ -64,69 +63,71 @@ #include <gal/util/e-util.h> -static void emp_standard_menu_factory(EPopup *emp, void *data); +static void emp_standard_menu_factory(EMPopup *emp, EMPopupTarget *target, void *data); + +struct _EMPopupFactory { + struct _EMPopupFactory *next, *prev; + + char *menuid; + EMPopupFactoryFunc factory; + void *factory_data; +}; + +struct _menu_node { + struct _menu_node *next, *prev; + + GSList *menu; + GDestroyNotify freefunc; +}; + +struct _EMPopupPrivate { + EDList menus; +}; + +static EDList emp_factories = E_DLIST_INITIALISER(emp_factories); static GObjectClass *emp_parent; static void emp_init(GObject *o) { - /*EMPopup *emp = (EMPopup *)o; */ -} + EMPopup *emp = (EMPopup *)o; + struct _EMPopupPrivate *p; -static void -emp_finalise(GObject *o) -{ - ((GObjectClass *)emp_parent)->finalize(o); + p = emp->priv = g_malloc0(sizeof(struct _EMPopupPrivate)); + + e_dlist_init(&p->menus); } static void -emp_target_free(EPopup *ep, EPopupTarget *t) +emp_finalise(GObject *o) { - switch (t->type) { - case EM_POPUP_TARGET_SELECT: { - EMPopupTargetSelect *s = (EMPopupTargetSelect *)t; - - if (s->folder) - camel_object_unref(s->folder); - g_free(s->uri); - if (s->uids) - em_utils_uids_free(s->uids); - break; } - case EM_POPUP_TARGET_URI: { - EMPopupTargetURI *s = (EMPopupTargetURI *)t; + EMPopup *emp = (EMPopup *)o; + struct _EMPopupPrivate *p = emp->priv; + struct _menu_node *mnode, *nnode; - g_free(s->uri); - break; } - case EM_POPUP_TARGET_PART: { - EMPopupTargetPart *s = (EMPopupTargetPart *)t; + g_free(emp->menuid); - camel_object_unref(s->part); - g_free(s->mime_type); - break; } - case EM_POPUP_TARGET_FOLDER: { - EMPopupTargetFolder *s = (EMPopupTargetFolder *)t; - - g_free(s->uri); - break; } - case EM_POPUP_TARGET_ATTACHMENTS: { - EMPopupTargetAttachments *s = (EMPopupTargetAttachments *)t; + mnode = (struct _menu_node *)p->menus.head; + nnode = mnode->next; + while (nnode) { + if (mnode->freefunc) + mnode->freefunc(mnode->menu); - g_slist_foreach(s->attachments, (GFunc)g_object_unref, NULL); - g_slist_free(s->attachments); - break; } + g_free(mnode); + mnode = nnode; + nnode = nnode->next; } - ((EPopupClass *)emp_parent)->target_free(ep, t); + g_free(p); + + ((GObjectClass *)emp_parent)->finalize(o); } static void 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 @@ -143,8 +144,11 @@ em_popup_get_type(void) sizeof(EMPopup), 0, (GInstanceInitFunc)emp_init }; - emp_parent = g_type_class_ref(e_popup_get_type()); - type = g_type_register_static(e_popup_get_type(), "EMPopup", &info, 0); + emp_parent = g_type_class_ref(G_TYPE_OBJECT); + type = g_type_register_static(G_TYPE_OBJECT, "EMPopup", &info, 0); + + /* FIXME: this should probably sit somewhere in global setup */ + em_popup_static_add_factory(NULL, (EMPopupFactoryFunc)emp_standard_menu_factory, NULL); } return type; @@ -154,12 +158,291 @@ EMPopup *em_popup_new(const char *menuid) { EMPopup *emp = g_object_new(em_popup_get_type(), 0); - e_popup_construct(&emp->popup, menuid); + emp->menuid = g_strdup(menuid); return emp; } /** + * em_popup_add_items: + * @emp: + * @items: + * @freefunc: + * + * Add new EMPopupItems to the menu's. Any with the same path + * will override previously defined menu items, at menu building + * time. + **/ +void +em_popup_add_items(EMPopup *emp, GSList *items, GDestroyNotify freefunc) +{ + struct _menu_node *node; + + node = g_malloc(sizeof(*node)); + node->menu = items; + node->freefunc = freefunc; + e_dlist_addtail(&emp->priv->menus, (EDListNode *)node); +} + +/** + * em_popup_add_static_items: + * @emp: + * @target: Target of this menu. + * + * Will load up any matching menu items from an installed + * popup factory. If the menuid of @emp is NULL, then this + * has no effect. + * + **/ +void +em_popup_add_static_items(EMPopup *emp, EMPopupTarget *target) +{ + struct _EMPopupFactory *f; + + if (emp->menuid == NULL || target == NULL) + return; + + /* setup the menu itself */ + f = (struct _EMPopupFactory *)emp_factories.head; + while (f->next) { + if (f->menuid == NULL + || !strcmp(f->menuid, emp->menuid)) { + f->factory(emp, target, f->factory_data); + } + f = f->next; + } +} + +static int +emp_cmp(const void *ap, const void *bp) +{ + struct _EMPopupItem *a = *((void **)ap); + struct _EMPopupItem *b = *((void **)bp); + + return strcmp(a->path, b->path); +} + +/** + * em_popup_create: + * @menuitems: + * @hide_mask: used to hide menu items, not sure of it's utility, + * since you could just 'not add them' in the first place. Saves + * copying logic anyway. + * @disable_mask: used to disable menu items. + * + * TEMPORARY code to create a menu from a list of items. + * + * The menu items are merged based on their path element, and + * built into a menu tree. + * + * Return value: + **/ +GtkMenu * +em_popup_create_menu(EMPopup *emp, guint32 hide_mask, guint32 disable_mask) +{ + struct _EMPopupPrivate *p = emp->priv; + struct _menu_node *mnode, *nnode; + GPtrArray *items = g_ptr_array_new(); + GSList *l; + GString *ppath = g_string_new(""); + GtkMenu *topmenu; + GHashTable *menu_hash = g_hash_table_new(g_str_hash, g_str_equal), + *group_hash = g_hash_table_new(g_str_hash, g_str_equal); + /*char *domain = NULL;*/ + int i; + + /* FIXME: need to override old ones with new names */ + mnode = (struct _menu_node *)p->menus.head; + nnode = mnode->next; + while (nnode) { + for (l=mnode->menu; l; l = l->next) + g_ptr_array_add(items, l->data); + mnode = nnode; + nnode = nnode->next; + } + + qsort(items->pdata, items->len, sizeof(items->pdata[0]), emp_cmp); + + topmenu = (GtkMenu *)gtk_menu_new(); + for (i=0;i<items->len;i++) { + GtkWidget *label; + struct _EMPopupItem *item = items->pdata[i]; + GtkMenu *thismenu; + GtkMenuItem *menuitem; + char *tmp; + + /* for bar's, the mask is exclusive or */ + if (item->mask) { + if ((item->type & EM_POPUP_TYPE_MASK) == EM_POPUP_BAR) { + if ((item->mask & hide_mask) == item->mask) + continue; + } else if (item->mask & hide_mask) + continue; + } + + g_string_truncate(ppath, 0); + tmp = strrchr(item->path, '/'); + if (tmp) { + g_string_append_len(ppath, item->path, tmp-item->path); + thismenu = g_hash_table_lookup(menu_hash, ppath->str); + g_assert(thismenu != NULL); + } else { + thismenu = topmenu; + } + + switch (item->type & EM_POPUP_TYPE_MASK) { + case EM_POPUP_ITEM: + if (item->image) { + GdkPixbuf *pixbuf; + GtkWidget *image; + + pixbuf = e_icon_factory_get_icon ((char *)item->image, E_ICON_SIZE_MENU); + image = gtk_image_new_from_pixbuf (pixbuf); + g_object_unref (pixbuf); + + gtk_widget_show(image); + menuitem = (GtkMenuItem *)gtk_image_menu_item_new(); + gtk_image_menu_item_set_image((GtkImageMenuItem *)menuitem, image); + } else { + menuitem = (GtkMenuItem *)gtk_menu_item_new(); + } + break; + case EM_POPUP_TOGGLE: + menuitem = (GtkMenuItem *)gtk_check_menu_item_new(); + gtk_check_menu_item_set_active((GtkCheckMenuItem *)menuitem, item->type & EM_POPUP_ACTIVE); + break; + case EM_POPUP_RADIO: + menuitem = (GtkMenuItem *)gtk_radio_menu_item_new(g_hash_table_lookup(group_hash, ppath->str)); + g_hash_table_insert(group_hash, ppath->str, gtk_radio_menu_item_get_group((GtkRadioMenuItem *)menuitem)); + gtk_check_menu_item_set_active((GtkCheckMenuItem *)menuitem, item->type & EM_POPUP_ACTIVE); + break; + case EM_POPUP_IMAGE: + menuitem = (GtkMenuItem *)gtk_image_menu_item_new(); + gtk_image_menu_item_set_image((GtkImageMenuItem *)menuitem, item->image); + break; + case EM_POPUP_SUBMENU: { + GtkMenu *submenu = (GtkMenu *)gtk_menu_new(); + + g_hash_table_insert(menu_hash, item->path, submenu); + menuitem = (GtkMenuItem *)gtk_menu_item_new(); + gtk_menu_item_set_submenu(menuitem, (GtkWidget *)submenu); + break; } + case EM_POPUP_BAR: + /* TODO: double-bar, end-bar stuff? */ + menuitem = (GtkMenuItem *)gtk_separator_menu_item_new(); + break; + default: + continue; + } + + if (item->label) { + label = gtk_label_new_with_mnemonic(_(item->label)); + gtk_misc_set_alignment((GtkMisc *)label, 0.0, 0.5); + gtk_widget_show(label); + gtk_container_add((GtkContainer *)menuitem, label); + } + + if (item->activate) + g_signal_connect(menuitem, "activate", item->activate, item->activate_data); + + gtk_menu_shell_append((GtkMenuShell *)thismenu, (GtkWidget *)menuitem); + + if (item->mask & disable_mask) + gtk_widget_set_sensitive((GtkWidget *)menuitem, FALSE); + + gtk_widget_show((GtkWidget *)menuitem); + } + + g_string_free(ppath, TRUE); + g_ptr_array_free(items, TRUE); + g_hash_table_destroy(menu_hash); + g_hash_table_destroy(group_hash); + + return topmenu; +} + +static void +emp_popup_done(GtkWidget *w, EMPopup *emp) +{ + gtk_widget_destroy(w); + g_object_unref(emp); +} + +/** + * em_popup_create_menu_once: + * @emp: EMPopup, once the menu is shown, this cannot be + * considered a valid pointer. + * @target: If set, the target of the selection. Static menu + * items will be added. The target will be freed once complete. + * @hide_mask: + * @disable_mask: + * + * Like popup_create_menu, but automatically sets up the menu + * so that it is destroyed once a selection takes place, and + * the EMPopup is unreffed. + * + * Return value: A menu, to popup. + **/ +GtkMenu * +em_popup_create_menu_once(EMPopup *emp, EMPopupTarget *target, guint32 hide_mask, guint32 disable_mask) +{ + GtkMenu *menu; + + if (target) + em_popup_add_static_items(emp, target); + + menu = em_popup_create_menu(emp, hide_mask, disable_mask); + + if (target) + g_signal_connect_swapped(menu, "selection_done", G_CALLBACK(em_popup_target_free), target); + g_signal_connect(menu, "selection_done", G_CALLBACK(emp_popup_done), emp); + + return menu; +} + +/* ********************************************************************** */ + +/** + * em_popup_static_add_factory: + * @menuid: + * @func: + * @data: + * + * Add a popup factory which will be called to add_items() any + * extra menu's if wants to do the current PopupTarget. + * + * TODO: Make the menuid a pattern? + * + * Return value: A handle to the factory. + **/ +EMPopupFactory * +em_popup_static_add_factory(const char *menuid, EMPopupFactoryFunc func, void *data) +{ + struct _EMPopupFactory *f = g_malloc0(sizeof(*f)); + + f->menuid = g_strdup(menuid); + f->factory = func; + f->factory_data = data; + e_dlist_addtail(&emp_factories, (EDListNode *)f); + + return f; +} + +/** + * em_popup_static_remove_factory: + * @f: + * + * Remove a popup factory. + **/ +void +em_popup_static_remove_factory(EMPopupFactory *f) +{ + e_dlist_remove((EDListNode *)f); + g_free(f->menuid); + g_free(f); +} + +/** * em_popup_target_new_select: * @folder: The selection will ref this for the life of it. * @folder_uri: @@ -169,20 +452,21 @@ EMPopup *em_popup_new(const char *menuid) * * Return value: **/ -EMPopupTargetSelect * -em_popup_target_new_select(EMPopup *emp, struct _CamelFolder *folder, const char *folder_uri, GPtrArray *uids) +EMPopupTarget * +em_popup_target_new_select(struct _CamelFolder *folder, const char *folder_uri, GPtrArray *uids) { - EMPopupTargetSelect *t = e_popup_target_new(&emp->popup, EM_POPUP_TARGET_SELECT, sizeof(*t)); + EMPopupTarget *t = g_malloc0(sizeof(*t)); guint32 mask = ~0; int i; const char *tmp; - t->uids = uids; - t->folder = folder; - t->uri = g_strdup(folder_uri); + t->type = EM_POPUP_TARGET_SELECT; + t->data.select.uids = uids; + t->data.select.folder = folder; + t->data.select.folder_uri = g_strdup(folder_uri); if (folder == NULL) { - t->target.mask = mask; + t->mask = mask; return t; } @@ -206,31 +490,34 @@ em_popup_target_new_select(EMPopup *emp, struct _CamelFolder *folder, const char for (i = 0; i < uids->len; i++) { CamelMessageInfo *info = camel_folder_get_message_info(folder, uids->pdata[i]); - guint32 flags; if (info == NULL) continue; - flags = camel_message_info_flags(info); - if (flags & CAMEL_MESSAGE_SEEN) + if (info->flags & CAMEL_MESSAGE_SEEN) mask &= ~EM_POPUP_SELECT_MARK_UNREAD; else mask &= ~EM_POPUP_SELECT_MARK_READ; - if (flags & CAMEL_MESSAGE_DELETED) + if (info->flags & CAMEL_MESSAGE_DELETED) mask &= ~EM_POPUP_SELECT_UNDELETE; else mask &= ~EM_POPUP_SELECT_DELETE; - if (flags & CAMEL_MESSAGE_FLAGGED) + if (info->flags & CAMEL_MESSAGE_FLAGGED) mask &= ~EM_POPUP_SELECT_MARK_UNIMPORTANT; else mask &= ~EM_POPUP_SELECT_MARK_IMPORTANT; - tmp = camel_message_info_user_tag(info, "follow-up"); + if (info->flags & CAMEL_MESSAGE_JUNK) + mask &= ~EM_POPUP_SELECT_MARK_NOJUNK; + else + mask &= ~EM_POPUP_SELECT_MARK_JUNK; + + tmp = camel_tag_get (&info->user_tags, "follow-up"); if (tmp && *tmp) { mask &= ~EM_POPUP_SELECT_FLAG_CLEAR; - tmp = camel_message_info_user_tag(info, "completed-on"); + tmp = camel_tag_get(&info->user_tags, "completed-on"); if (tmp == NULL || *tmp == 0) mask &= ~EM_POPUP_SELECT_FLAG_COMPLETED; } else @@ -244,18 +531,19 @@ em_popup_target_new_select(EMPopup *emp, struct _CamelFolder *folder, const char camel_folder_free_message_info(folder, info); } - t->target.mask = mask; + t->mask = mask; return t; } -EMPopupTargetURI * -em_popup_target_new_uri(EMPopup *emp, const char *uri) +EMPopupTarget * +em_popup_target_new_uri(const char *uri) { - EMPopupTargetURI *t = e_popup_target_new(&emp->popup, EM_POPUP_TARGET_URI, sizeof(*t)); + EMPopupTarget *t = g_malloc0(sizeof(*t)); guint32 mask = ~0; - t->uri = g_strdup(uri); + t->type = EM_POPUP_TARGET_URI; + t->data.uri = g_strdup(uri); if (g_ascii_strncasecmp(uri, "http:", 5) == 0 || g_ascii_strncasecmp(uri, "https:", 6) == 0) @@ -265,46 +553,48 @@ em_popup_target_new_uri(EMPopup *emp, const char *uri) else mask &= ~EM_POPUP_URI_NOT_MAILTO; - t->target.mask = mask; + t->mask = mask; return t; } -EMPopupTargetPart * -em_popup_target_new_part(EMPopup *emp, struct _CamelMimePart *part, const char *mime_type) +EMPopupTarget * +em_popup_target_new_part(struct _CamelMimePart *part, const char *mime_type) { - EMPopupTargetPart *t = e_popup_target_new(&emp->popup, EM_POPUP_TARGET_PART, sizeof(*t)); + EMPopupTarget *t = g_malloc0(sizeof(*t)); guint32 mask = ~0; - t->part = part; + t->type = EM_POPUP_TARGET_PART; + t->data.part.part = part; camel_object_ref(part); if (mime_type) - t->mime_type = g_strdup(mime_type); + t->data.part.mime_type = g_strdup(mime_type); else - t->mime_type = camel_data_wrapper_get_mime_type((CamelDataWrapper *)part); + t->data.part.mime_type = camel_data_wrapper_get_mime_type((CamelDataWrapper *)part); - camel_strdown(t->mime_type); + camel_strdown(t->data.part.mime_type); if (CAMEL_IS_MIME_MESSAGE(camel_medium_get_content_object((CamelMedium *)part))) mask &= ~EM_POPUP_PART_MESSAGE; - if (strncmp(t->mime_type, "image/", 6) == 0) + if (strncmp(t->data.part.mime_type, "image/", 6) == 0) mask &= ~EM_POPUP_PART_IMAGE; - t->target.mask = mask; + t->mask = mask; return t; } /* TODO: This should be based on the CamelFolderInfo, but ... em-folder-tree doesn't keep it? */ -EMPopupTargetFolder * -em_popup_target_new_folder (EMPopup *emp, const char *uri, guint32 info_flags, guint32 popup_flags) +EMPopupTarget * +em_popup_target_new_folder (const char *uri, guint32 info_flags, guint32 popup_flags) { - EMPopupTargetFolder *t = e_popup_target_new(&emp->popup, EM_POPUP_TARGET_FOLDER, sizeof(*t)); + EMPopupTarget *t = g_malloc0(sizeof(*t)); guint32 mask = ~0; CamelURL *url; - t->uri = g_strdup(uri); + t->type = EM_POPUP_TARGET_FOLDER; + t->data.folder.folder_uri = g_strdup(uri); if (popup_flags & EM_POPUP_FOLDER_STORE) mask &= ~(EM_POPUP_FOLDER_STORE|EM_POPUP_FOLDER_INFERIORS); @@ -339,63 +629,91 @@ em_popup_target_new_folder (EMPopup *emp, const char *uri, guint32 info_flags, g camel_url_free(url); done: - t->target.mask = mask; + t->mask = mask; return t; } -/** - * em_popup_target_new_attachments: - * @emp: - * @attachments: A list of EMsgComposerAttachment objects, reffed for - * the list. Will be unreff'd once finished with. - * - * Owns the list @attachments and their items after they're passed in. - * - * Return value: - **/ -EMPopupTargetAttachments * -em_popup_target_new_attachments(EMPopup *emp, GSList *attachments) +void +em_popup_target_free(EMPopupTarget *t) { - EMPopupTargetAttachments *t = e_popup_target_new(&emp->popup, EM_POPUP_TARGET_ATTACHMENTS, sizeof(*t)); - guint32 mask = ~0; - int len = g_slist_length(attachments); - - t->attachments = attachments; - if (len > 0) - mask &= ~ EM_POPUP_ATTACHMENTS_MANY; - if (len == 1) - mask &= ~ EM_POPUP_ATTACHMENTS_ONE; - t->target.mask = mask; + switch (t->type) { + case EM_POPUP_TARGET_SELECT: + if (t->data.select.folder) + camel_object_unref(t->data.select.folder); + g_free(t->data.select.folder_uri); + if (t->data.select.uids) + em_utils_uids_free(t->data.select.uids); + break; + case EM_POPUP_TARGET_URI: + g_free(t->data.uri); + break; + case EM_POPUP_TARGET_PART: + camel_object_unref(t->data.part.part); + g_free(t->data.part.mime_type); + break; + case EM_POPUP_TARGET_FOLDER: + g_free(t->data.folder.folder_uri); + break; + } - return t; + g_free(t); } /* ********************************************************************** */ +#if 0 +/* TODO: flesh these out where possible */ +static void +emp_popup_open(GtkWidget *w, EMFolderView *emfv) +{ + em_folder_view_open_selected(emfv); +} + +static void +emp_popup_edit (GtkWidget *w, EMPopupTarget *t) +{ + if (!em_utils_check_user_can_send_mail(t->widget)) + return; + + em_utils_edit_messages(t->widget, t->data.select.folder, em_utils_uids_copy(t->data.select.uids), FALSE); +} + static void -emp_part_popup_saveas(EPopup *ep, EPopupItem *item, void *data) +emp_popup_saveas(GtkWidget *w, EMPopupTarget *t) { - EMPopupTargetPart *t = (EMPopupTargetPart *)ep->target; + em_utils_save_messages(t->widget, t->data.select.folder, em_utils_uids_copy(t->data.select.uids)); +} - em_utils_save_part(ep->target->widget, _("Save As..."), t->part); +static EMPopupItem emp_standard_select_popups[] = { + /*{ EM_POPUP_ITEM, "00.select.00", N_("_Open"), G_CALLBACK(emp_popup_open), NULL, NULL, 0 },*/ + { EM_POPUP_ITEM, "00.select.01", N_("_Edit as New Message..."), G_CALLBACK(emp_popup_edit), NULL, NULL, EM_POPUP_SELECT_EDIT }, + { EM_POPUP_ITEM, "00.select.02", N_("_Save As..."), G_CALLBACK(emp_popup_saveas), NULL, "stock_save-as", 0 }, +}; +#endif + +/* ********************************************************************** */ + +static void +emp_part_popup_saveas(GtkWidget *w, EMPopupTarget *t) +{ + em_utils_save_part(w, _("Save As..."), t->data.part.part); } static void -emp_part_popup_set_background(EPopup *ep, EPopupItem *item, void *data) +emp_part_popup_set_background(GtkWidget *w, EMPopupTarget *t) { - EMPopupTargetPart *t = (EMPopupTargetPart *)ep->target; GConfClient *gconf; char *str, *filename, *path, *extension; unsigned int i=1; - filename = g_strdup(camel_mime_part_get_filename(t->part)); + filename = g_strdup(camel_mime_part_get_filename(t->data.part.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(t->part); + ct = camel_mime_part_get_content_type(t->data.part.part); g_free (filename); filename = g_strdup_printf (_("untitled_image.%s"), ct->subtype); } @@ -419,7 +737,7 @@ emp_part_popup_set_background(EPopup *ep, EPopupItem *item, void *data) g_free(filename); - if (em_utils_save_part_to_file(ep->target->widget, path, t->part)) { + if (em_utils_save_part_to_file(w, path, t->data.part.part)) { gconf = gconf_client_get_default(); /* if the filename hasn't changed, blank the filename before @@ -449,68 +767,64 @@ emp_part_popup_set_background(EPopup *ep, EPopupItem *item, void *data) } static void -emp_part_popup_reply_sender(EPopup *ep, EPopupItem *item, void *data) +emp_part_popup_reply_sender (GtkWidget *w, EMPopupTarget *t) { - EMPopupTargetPart *t = (EMPopupTargetPart *)ep->target; CamelMimeMessage *message; - message = (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *)t->part); - em_utils_reply_to_message(NULL, NULL, message, REPLY_MODE_SENDER, NULL); + message = (CamelMimeMessage *) camel_medium_get_content_object ((CamelMedium *) t->data.part.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) +emp_part_popup_reply_list (GtkWidget *w, EMPopupTarget *t) { - EMPopupTargetPart *t = (EMPopupTargetPart *)ep->target; CamelMimeMessage *message; - message = (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *)t->part); - em_utils_reply_to_message(NULL, NULL, message, REPLY_MODE_LIST, NULL); + message = (CamelMimeMessage *) camel_medium_get_content_object ((CamelMedium *) t->data.part.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) +emp_part_popup_reply_all (GtkWidget *w, EMPopupTarget *t) { - EMPopupTargetPart *t = (EMPopupTargetPart *)ep->target; CamelMimeMessage *message; - message = (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *)t->part); - em_utils_reply_to_message(NULL, NULL, message, REPLY_MODE_ALL, NULL); + message = (CamelMimeMessage *) camel_medium_get_content_object ((CamelMedium *) t->data.part.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) +emp_part_popup_forward (GtkWidget *w, EMPopupTarget *t) { - EMPopupTargetPart *t = (EMPopupTargetPart *)ep->target; CamelMimeMessage *message; /* TODO: have a emfv specific override so we can get the parent folder uri */ - message = (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *) t->part); - em_utils_forward_message(message, NULL); + message = (CamelMimeMessage *) camel_medium_get_content_object ((CamelMedium *) t->data.part.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, "stock_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, "stock_mail-reply" , 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, "stock_mail-reply-to-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, "stock_mail-forward", EM_POPUP_PART_MESSAGE }, + { EM_POPUP_ITEM, "00.part.00", N_("_Save As..."), G_CALLBACK(emp_part_popup_saveas), NULL, "stock_save-as", 0 }, + { EM_POPUP_ITEM, "00.part.10", N_("Set as _Background"), G_CALLBACK(emp_part_popup_set_background), NULL, NULL, EM_POPUP_PART_IMAGE }, + { EM_POPUP_BAR, "10.part", NULL, NULL, NULL, NULL, EM_POPUP_PART_MESSAGE }, + { EM_POPUP_ITEM, "10.part.00", N_("_Reply to sender"), G_CALLBACK(emp_part_popup_reply_sender), NULL, "stock_mail-reply" , EM_POPUP_PART_MESSAGE }, + { EM_POPUP_ITEM, "10.part.01", N_("Reply to _List"), G_CALLBACK(emp_part_popup_reply_list), NULL, NULL, EM_POPUP_PART_MESSAGE}, + { EM_POPUP_ITEM, "10.part.03", N_("Reply to _All"), G_CALLBACK(emp_part_popup_reply_all), NULL, "stock_mail-reply-to-all", EM_POPUP_PART_MESSAGE}, + { EM_POPUP_BAR, "20.part", NULL, NULL, NULL, NULL, EM_POPUP_PART_MESSAGE }, + { EM_POPUP_ITEM, "20.part.00", N_("_Forward"), G_CALLBACK(emp_part_popup_forward), NULL, "stock_mail-forward", EM_POPUP_PART_MESSAGE }, + }; -static const EPopupItem emp_standard_part_apps_bar = { E_POPUP_BAR, "99.object" }; +static const EMPopupItem emp_standard_part_apps_bar = { EM_POPUP_BAR, "99.object" }; /* ********************************************************************** */ static void -emp_uri_popup_link_open(EPopup *ep, EPopupItem *item, void *data) +emp_uri_popup_link_open(GtkWidget *w, EMPopupTarget *t) { - EMPopupTargetURI *t = (EMPopupTargetURI *)ep->target; GError *err = NULL; - gnome_url_show(t->uri, &err); + gnome_url_show(t->data.uri, &err); if (err) { g_warning("gnome_url_show: %s", err->message); g_error_free(err); @@ -518,36 +832,33 @@ emp_uri_popup_link_open(EPopup *ep, EPopupItem *item, void *data) } static void -emp_uri_popup_address_send(EPopup *ep, EPopupItem *item, void *data) +emp_uri_popup_address_send (GtkWidget *w, EMPopupTarget *t) { - 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); + em_utils_compose_new_message_with_mailto (t->data.uri, NULL); } static void -emp_uri_popup_address_add(EPopup *ep, EPopupItem *item, void *data) +emp_uri_popup_address_add(GtkWidget *w, EMPopupTarget *t) { - EMPopupTargetURI *t = (EMPopupTargetURI *)ep->target; CamelURL *url; - url = camel_url_new(t->uri, NULL); + url = camel_url_new(t->data.uri, NULL); if (url == NULL) { - g_warning("cannot parse url '%s'", t->uri); + g_warning("cannot parse url '%s'", t->data.uri); return; } if (url->path && url->path[0]) - em_utils_add_address(ep->target->widget, url->path); + em_utils_add_address(w, 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_NOT_MAILTO }, - { E_POPUP_ITEM, "00.uri.10", N_("Se_nd message to..."), emp_uri_popup_address_send, NULL, NULL, EM_POPUP_URI_MAILTO }, - { E_POPUP_ITEM, "00.uri.20", N_("_Add to Addressbook"), emp_uri_popup_address_add, NULL, NULL, EM_POPUP_URI_MAILTO }, +static EMPopupItem emp_standard_uri_popups[] = { + { EM_POPUP_ITEM, "00.uri.00", N_("_Open Link in Browser"), G_CALLBACK(emp_uri_popup_link_open), NULL, NULL, EM_POPUP_URI_NOT_MAILTO }, + { EM_POPUP_ITEM, "00.uri.10", N_("Se_nd message to..."), G_CALLBACK(emp_uri_popup_address_send), NULL, NULL, EM_POPUP_URI_MAILTO }, + { EM_POPUP_ITEM, "00.uri.20", N_("_Add to Addressbook"), G_CALLBACK(emp_uri_popup_address_add), NULL, NULL, EM_POPUP_URI_MAILTO }, }; /* ********************************************************************** */ @@ -556,21 +867,23 @@ static EPopupItem emp_standard_uri_popups[] = { #include <libgnomevfs/gnome-vfs-mime-handlers.h> - EMPopupTargetPart *target; +struct _open_in_item { + EMPopupItem item; + EMPopupTarget *target; + GnomeVFSMimeApplication *app; +}; static void -emp_apps_open_in(EPopup *ep, EPopupItem *item, void *data) +emp_apps_open_in(GtkWidget *w, struct _open_in_item *item) { char *path; - EMPopupTargetPart *target = (EMPopupTargetPart *)ep->target; - path = em_utils_temp_save_part(target->target.widget, target->part); + path = em_utils_temp_save_part(item->target->widget, item->target->data.part.part); if (path) { - GnomeVFSMimeApplication *app = item->user_data; - int douri = (app->expects_uris == GNOME_VFS_MIME_APPLICATION_ARGUMENT_TYPE_URIS); + int douri = (item->app->expects_uris == GNOME_VFS_MIME_APPLICATION_ARGUMENT_TYPE_URIS); char *command; - if (app->requires_terminal) { + if (item->app->requires_terminal) { char *term, *args = NULL; GConfClient *gconf; @@ -583,11 +896,11 @@ emp_apps_open_in(EPopup *ep, EPopupItem *item, void *data) return; command = g_strdup_printf ("%s%s%s %s %s%s &", term, args ? " " : "", args ? args : "", - app->command, douri ? "file://" : "", path); + item->app->command, douri ? "file://" : "", path); g_free (term); g_free (args); } else { - command = g_strdup_printf ("%s %s%s &", app->command, douri ? "file://" : "", path); + command = g_strdup_printf ("%s %s%s &", item->app->command, douri ? "file://" : "", path); } /* FIXME: Do not use system here */ @@ -598,14 +911,14 @@ emp_apps_open_in(EPopup *ep, EPopupItem *item, void *data) } static void -emp_apps_popup_free(EPopup *ep, GSList *free_list, void *data) +emp_apps_popup_free(GSList *free_list) { while (free_list) { GSList *n = free_list->next; - EPopupItem *item = free_list->data; + struct _open_in_item *item = free_list->data; - g_free(item->path); - g_free(item->label); + g_free(item->item.path); + g_free(item->item.label); g_free(item); g_slist_free_1(free_list); @@ -614,19 +927,13 @@ emp_apps_popup_free(EPopup *ep, GSList *free_list, void *data) } static void -emp_standard_items_free(EPopup *ep, GSList *items, void *data) -{ - g_slist_free(items); -} - -static void -emp_standard_menu_factory(EPopup *emp, void *data) +emp_standard_menu_factory(EMPopup *emp, EMPopupTarget *target, void *data) { int i, len; - EPopupItem *items; + EMPopupItem *items; GSList *menus = NULL; - switch (emp->target->type) { + switch (target->type) { #if 0 case EM_POPUP_TARGET_SELECT: return; @@ -634,21 +941,18 @@ emp_standard_menu_factory(EPopup *emp, void *data) len = LEN(emp_standard_select_popups); break; #endif - case EM_POPUP_TARGET_URI: { - /*EMPopupTargetURI *t = (EMPopupTargetURI *)target;*/ - + case EM_POPUP_TARGET_URI: items = emp_standard_uri_popups; len = LEN(emp_standard_uri_popups); - break; } + break; case EM_POPUP_TARGET_PART: { - EMPopupTargetPart *t = (EMPopupTargetPart *)emp->target; - GList *apps = gnome_vfs_mime_get_short_list_applications(t->mime_type); + GList *apps = gnome_vfs_mime_get_short_list_applications(target->data.part.mime_type); /* FIXME: use the snoop_part stuff from em-format.c */ - if (apps == NULL && strcmp(t->mime_type, "application/octet-stream") == 0) { + if (apps == NULL && strcmp(target->data.part.mime_type, "application/octet-stream") == 0) { const char *filename, *name_type; - filename = camel_mime_part_get_filename(t->part); + filename = camel_mime_part_get_filename(target->data.part.part); if (filename) { /* GNOME-VFS will misidentify TNEF attachments as MPEG */ @@ -670,23 +974,25 @@ emp_standard_menu_factory(EPopup *emp, void *data) for (l = apps, i = 0; l; l = l->next, i++) { GnomeVFSMimeApplication *app = l->data; - EPopupItem *item; + struct _open_in_item *item; if (app->requires_terminal) continue; 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..."), app->name); - item->activate = emp_apps_open_in; - item->user_data = app; + item->item.type = EM_POPUP_ITEM; + item->item.path = g_strdup_printf("99.object.%02d", i); + item->item.label = g_strdup_printf(_("Open in %s..."), app->name); + item->item.activate = G_CALLBACK(emp_apps_open_in); + item->item.activate_data = item; + item->target = target; + item->app = 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); + em_popup_add_items(emp, open_menus, (GDestroyNotify)emp_apps_popup_free); g_string_free(label, TRUE); g_list_free(apps); @@ -701,137 +1007,12 @@ emp_standard_menu_factory(EPopup *emp, void *data) } for (i=0;i<len;i++) { - if ((items[i].visible & emp->target->mask) == 0) + if ((items[i].mask & target->mask) == 0) { + items[i].activate_data = target; 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 */ - -/* -<e-plugin - class="org.gnome.mail.plugin.popup:1.0" - id="org.gnome.mail.plugin.popup.item:1.0" - type="shlib" - location="/opt/gnome2/lib/camel/1.0/libcamelimap.so" - name="imap" - description="IMAP4 and IMAP4v1 mail store"> - <hook class="org.gnome.mail.popupMenu:1.0" - handler="HandlePopup"> - <menu id="any" target="select"> - <item - type="item|toggle|radio|image|submenu|bar" - active - path="foo/bar" - label="label" - icon="foo" - mask="select_one" - activate="emp_view_emacs"/> - </menu> - </extension> - -*/ - -static void *emph_parent_class; -#define emph ((EMPopupHook *)eph) - -static const EPopupHookTargetMask emph_select_masks[] = { - { "one", EM_POPUP_SELECT_ONE }, - { "many", EM_POPUP_SELECT_MANY }, - { "mark_read", EM_POPUP_SELECT_MARK_READ }, - { "mark_unread", EM_POPUP_SELECT_MARK_UNREAD }, - { "delete", EM_POPUP_SELECT_DELETE }, - { "undelete", EM_POPUP_SELECT_UNDELETE }, - { "mailing_list", EM_POPUP_SELECT_MAILING_LIST }, - { "resend", EM_POPUP_SELECT_EDIT }, - { "mark_important", EM_POPUP_SELECT_MARK_IMPORTANT }, - { "mark_unimportant", EM_POPUP_SELECT_MARK_UNIMPORTANT }, - { "flag_followup", EM_POPUP_SELECT_FLAG_FOLLOWUP }, - { "flag_completed", EM_POPUP_SELECT_FLAG_COMPLETED }, - { "flag_clear", EM_POPUP_SELECT_FLAG_CLEAR }, - { "add_sender", EM_POPUP_SELECT_ADD_SENDER }, - { "folder", EM_POPUP_SELECT_FOLDER }, - { 0 } -}; - -static const EPopupHookTargetMask emph_uri_masks[] = { - { "http", EM_POPUP_URI_HTTP }, - { "mailto", EM_POPUP_URI_MAILTO }, - { "notmailto", EM_POPUP_URI_NOT_MAILTO }, - { 0 } -}; - -static const EPopupHookTargetMask emph_part_masks[] = { - { "message", EM_POPUP_PART_MESSAGE }, - { "image", EM_POPUP_PART_IMAGE }, - { 0 } -}; - -static const EPopupHookTargetMask emph_folder_masks[] = { - { "folder", EM_POPUP_FOLDER_FOLDER }, - { "store", EM_POPUP_FOLDER_STORE }, - { "inferiors", EM_POPUP_FOLDER_INFERIORS }, - { "delete", EM_POPUP_FOLDER_DELETE }, - { "select", EM_POPUP_FOLDER_SELECT }, - { 0 } -}; - -static const EPopupHookTargetMask emph_attachments_masks[] = { - { "one", EM_POPUP_ATTACHMENTS_ONE }, - { "many", EM_POPUP_ATTACHMENTS_MANY }, - { 0 } -}; - -static const EPopupHookTargetMap emph_targets[] = { - { "select", EM_POPUP_TARGET_SELECT, emph_select_masks }, - { "uri", EM_POPUP_TARGET_URI, emph_uri_masks }, - { "part", EM_POPUP_TARGET_PART, emph_part_masks }, - { "folder", EM_POPUP_TARGET_FOLDER, emph_folder_masks }, - { "attachments", EM_POPUP_TARGET_ATTACHMENTS, emph_attachments_masks }, - { 0 } -}; - -static void -emph_finalise(GObject *o) -{ - /*EPluginHook *eph = (EPluginHook *)o;*/ - - ((GObjectClass *)emph_parent_class)->finalize(o); -} - -static void -emph_class_init(EPluginHookClass *klass) -{ - int i; - - ((GObjectClass *)klass)->finalize = emph_finalise; - ((EPluginHookClass *)klass)->id = "org.gnome.evolution.mail.popup:1.0"; - - for (i=0;emph_targets[i].type;i++) - e_popup_hook_class_add_target_map((EPopupHookClass *)klass, &emph_targets[i]); - - ((EPopupHookClass *)klass)->popup_class = g_type_class_ref(em_popup_get_type()); -} - -GType -em_popup_hook_get_type(void) -{ - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof(EMPopupHookClass), NULL, NULL, (GClassInitFunc) emph_class_init, NULL, NULL, - sizeof(EMPopupHook), 0, (GInstanceInitFunc) NULL, - }; - - emph_parent_class = g_type_class_ref(e_popup_hook_get_type()); - type = g_type_register_static(e_popup_hook_get_type(), "EMPopupHook", &info, 0); - } - - return type; + em_popup_add_items(emp, menus, (GDestroyNotify)g_slist_free); } diff --git a/mail/em-subscribe-editor.c b/mail/em-subscribe-editor.c index 92588c76f9..ab0b098b36 100644 --- a/mail/em-subscribe-editor.c +++ b/mail/em-subscribe-editor.c @@ -43,7 +43,6 @@ #include "mail-config.h" #include <glade/glade.h> -#include <libgnome/gnome-i18n.h> #include <gtk/gtkdialog.h> #include <gtk/gtkscrolledwindow.h> @@ -300,7 +299,9 @@ sub_fill_level(EMSubscribe *sub, CamelFolderInfo *info, GtkTreeIter *parent, in gtk_tree_store_append(treestore, &iter, parent); node = g_malloc0(sizeof(*node)); node->info = fi; - state = (fi->flags & CAMEL_FOLDER_SUBSCRIBED) != 0; + /* FIXME: CAMEL_FOLDER_SUBSCRIBED not implemented properly in imap */ + state = camel_store_folder_subscribed(sub->store, fi->full_name); + /* state = (fi->flags & CAMEL_FOLDER_SUBSCRIBED) != 0; */ gtk_tree_store_set(treestore, &iter, 0, state, 1, fi->name, 2, node, -1); if ((fi->flags & CAMEL_FOLDER_NOINFERIORS) == 0) { node->path = gtk_tree_model_get_path((GtkTreeModel *)treestore, &iter); @@ -844,7 +845,7 @@ GtkDialog *em_subscribe_editor_new(void) se->dialog = (GtkDialog *)glade_xml_get_widget (xml, "subscribe_dialog"); g_signal_connect(se->dialog, "destroy", G_CALLBACK(sub_editor_destroy), se); - gtk_widget_ensure_style ((GtkWidget *)se->dialog); + gtk_widget_realize ((GtkWidget *)se->dialog); gtk_container_set_border_width ((GtkContainer *) ((GtkDialog *)se->dialog)->action_area, 12); gtk_container_set_border_width ((GtkContainer *) ((GtkDialog *)se->dialog)->vbox, 0); diff --git a/mail/em-utils.c b/mail/em-utils.c index 0236f2e329..b31ba4ad78 100644 --- a/mail/em-utils.c +++ b/mail/em-utils.c @@ -44,13 +44,13 @@ #include <libgnomevfs/gnome-vfs-mime.h> #include <libgnomevfs/gnome-vfs-mime-utils.h> #include <libgnomevfs/gnome-vfs-mime-handlers.h> -#include <libgnome/gnome-i18n.h> #include "mail-component.h" #include "mail-mt.h" #include "mail-ops.h" #include "mail-tools.h" #include "mail-config.h" +#include "mail-config-druid.h" #include "message-tag-followup.h" #include <e-util/e-mktemp.h> @@ -63,7 +63,6 @@ #include "em-utils.h" #include "em-composer-utils.h" #include "em-format-quote.h" -#include "em-account-editor.h" static void emu_save_part_done (CamelMimePart *part, char *name, int done, void *data); @@ -179,18 +178,19 @@ druid_destroy_cb (gpointer user_data, GObject *deadbeef) gboolean em_utils_configure_account (GtkWidget *parent) { - EMAccountEditor *emae; - - emae = em_account_editor_new(NULL, EMAE_DRUID); + MailConfigDruid *druid; + + druid = mail_config_druid_new (); + if (parent != NULL) - e_dialog_set_transient_for((GtkWindow *)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(); + e_dialog_set_transient_for ((GtkWindow *) druid, parent); + + g_object_weak_ref ((GObject *) druid, (GWeakNotify) druid_destroy_cb, NULL); + gtk_widget_show ((GtkWidget *) druid); + gtk_grab_add ((GtkWidget *) druid); + gtk_main (); - return mail_config_is_configured(); + return mail_config_is_configured (); } /** @@ -696,10 +696,8 @@ em_utils_flag_for_followup (GtkWidget *parent, CamelFolder *folder, GPtrArray *u info = camel_folder_get_message_info (folder, uids->pdata[0]); if (info) { - const CamelTag *tags = camel_message_info_user_tags(info); - - if (tags) - message_tag_editor_set_tag_list (MESSAGE_TAG_EDITOR (editor), tags); + if (info->user_tags) + message_tag_editor_set_tag_list (MESSAGE_TAG_EDITOR (editor), info->user_tags); camel_folder_free_message_info (folder, info); } } diff --git a/mail/mail-account-gui.c b/mail/mail-account-gui.c new file mode 100644 index 0000000000..a2ee0c0fb3 --- /dev/null +++ b/mail/mail-account-gui.c @@ -0,0 +1,2531 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: + * Dan Winship <danw@ximian.com> + * Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2001 Ximian, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <glib.h> + +#include <string.h> +#include <stdarg.h> +#include <sys/stat.h> + +#include <gconf/gconf-client.h> + +#include <gtk/gtkentry.h> +#include <gtk/gtktogglebutton.h> +#include <gtk/gtktextbuffer.h> +#include <gtk/gtktextview.h> +#include <gtk/gtkcheckbutton.h> +#include <gtk/gtkspinbutton.h> +#include <gtk/gtkmenuitem.h> +#include <gtk/gtkoptionmenu.h> +#include <gtk/gtknotebook.h> +#include <gtk/gtkhbox.h> +#include <gtk/gtkdialog.h> +#include <gtk/gtkstock.h> +#ifdef USE_GTKFILECHOOSER +#include <gtk/gtkfilechooser.h> +#include <gtk/gtkradiobutton.h> +#include <libgnomeui/gnome-file-entry.h> +#endif + +#include <e-util/e-account-list.h> +#include <e-util/e-signature-list.h> + +#include <widgets/misc/e-error.h> + +#include "em-account-prefs.h" +#include "em-folder-selection-button.h" +#include "mail-account-gui.h" +#include "mail-session.h" +#include "mail-send-recv.h" +#include "mail-signature-editor.h" +#include "mail-component.h" +#include "em-utils.h" +#include "em-composer-prefs.h" +#include "mail-config.h" +#include "mail-ops.h" +#include "mail-mt.h" + +#if defined (HAVE_NSS) +#include "smime/gui/e-cert-selector.h" +#endif + +#define d(x) + +static void save_service (MailAccountGuiService *gsvc, GHashTable *extra_conf, EAccountService *service); +static void service_changed (GtkEntry *entry, gpointer user_data); + +struct { + char *label; + char *value; +} ssl_options[] = { + { N_("Always"), "always" }, + { N_("Whenever Possible"), "when-possible" }, + { N_("Never"), "never" } +}; + +static int num_ssl_options = sizeof (ssl_options) / sizeof (ssl_options[0]); + +static gboolean +is_email (const char *address) +{ + /* This is supposed to check if the address's domain could be + an FQDN but alas, it's not worth the pain and suffering. */ + const char *at; + + at = strchr (address, '@'); + /* make sure we have an '@' and that it's not the first or last char */ + if (!at || at == address || *(at + 1) == '\0') + return FALSE; + + return TRUE; +} + +static GtkWidget * +get_focused_widget (GtkWidget *def, ...) +{ + GtkWidget *widget, *ret = NULL; + va_list args; + + va_start (args, def); + widget = va_arg (args, GtkWidget *); + while (widget) { + if (GTK_WIDGET_HAS_FOCUS (widget)) { + ret = widget; + break; + } + + widget = va_arg (args, GtkWidget *); + } + va_end (args); + + if (ret) + return ret; + else + return def; +} + +gboolean +mail_account_gui_identity_complete (MailAccountGui *gui, GtkWidget **incomplete) +{ + const char *text; + + text = gtk_entry_get_text (gui->full_name); + if (!text || !*text) { + if (incomplete) + *incomplete = get_focused_widget (GTK_WIDGET (gui->full_name), + GTK_WIDGET (gui->email_address), + GTK_WIDGET (gui->reply_to), + NULL); + return FALSE; + } + + text = gtk_entry_get_text (gui->email_address); + if (!text || !is_email (text)) { + if (incomplete) + *incomplete = get_focused_widget (GTK_WIDGET (gui->email_address), + GTK_WIDGET (gui->full_name), + GTK_WIDGET (gui->reply_to), + NULL); + return FALSE; + } + + /* make sure that if the reply-to field is filled in, that it is valid */ + text = gtk_entry_get_text (gui->reply_to); + if (text && *text && !is_email (text)) { + if (incomplete) + *incomplete = get_focused_widget (GTK_WIDGET (gui->reply_to), + GTK_WIDGET (gui->email_address), + GTK_WIDGET (gui->full_name), + NULL); + return FALSE; + } + + return TRUE; +} + +static void +auto_detected_foreach (gpointer key, gpointer value, gpointer user_data) +{ + g_free (key); + g_free (value); +} + +static void +check_button_state (GtkToggleButton *button, gpointer data) +{ + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button))) + gtk_widget_set_sensitive (GTK_WIDGET (data), TRUE); + else + gtk_widget_set_sensitive (GTK_WIDGET (data), FALSE); +} + + +static gboolean +populate_text_entry (GtkTextView *view, const char *filename) +{ + FILE *fd; + char *filebuf; + GtkTextIter iter; + GtkTextBuffer *buffer; + int count; + + g_return_val_if_fail (filename != NULL , FALSE); + + fd = fopen (filename, "r"); + + if (!fd) { + /* FIXME: Should never come here */ + return FALSE; + } + + filebuf = g_malloc (1024); + + buffer = gtk_text_buffer_new (NULL); + gtk_text_buffer_get_start_iter (buffer, &iter); + + while (!feof (fd) && !ferror (fd)) { + count = fread (filebuf, 1, sizeof (filebuf), fd); + gtk_text_buffer_insert (buffer, &iter, filebuf, count); + } + gtk_text_view_set_buffer (GTK_TEXT_VIEW (view), + GTK_TEXT_BUFFER (buffer)); + fclose (fd); + g_free (filebuf); + return TRUE; +} + +static gboolean +display_license (CamelProvider *prov) +{ + GladeXML *xml; + GtkWidget *top_widget; + GtkTextView *text_entry; + GtkButton *button_yes, *button_no; + GtkCheckButton *check_button; + GtkResponseType response = GTK_RESPONSE_NONE; + GtkLabel *top_label; + char *label_text, *dialog_title; + gboolean status; + + xml = glade_xml_new (EVOLUTION_GLADEDIR "/mail-dialogs.glade", "lic_dialog", NULL); + + top_widget = glade_xml_get_widget (xml, "lic_dialog"); + text_entry = GTK_TEXT_VIEW (glade_xml_get_widget (xml, "textview1")); + if (!(status = populate_text_entry (GTK_TEXT_VIEW (text_entry), prov->license_file))) + goto failed; + + gtk_text_view_set_editable (GTK_TEXT_VIEW (text_entry), FALSE); + + button_yes = GTK_BUTTON (glade_xml_get_widget (xml, "lic_yes_button")); + gtk_widget_set_sensitive (GTK_WIDGET (button_yes), FALSE); + + button_no = GTK_BUTTON (glade_xml_get_widget (xml, "lic_no_button")); + + check_button = GTK_CHECK_BUTTON (glade_xml_get_widget (xml, "lic_checkbutton")); + + top_label = GTK_LABEL (glade_xml_get_widget (xml, "lic_top_label")); + + label_text = g_strdup_printf (_("\nPlease read carefully the license agreement\n" + "for %s displayed below\n" + "and tick the check box for accepting it\n"), prov->license); + + gtk_label_set_label (top_label, label_text); + + dialog_title = g_strdup_printf (_("%s License Agreement"), prov->license); + + gtk_window_set_title (GTK_WINDOW (top_widget), dialog_title); + + g_signal_connect (check_button, "toggled", G_CALLBACK (check_button_state), button_yes); + + response = gtk_dialog_run (GTK_DIALOG (top_widget)); + + g_free (label_text); + g_free (dialog_title); + + failed: + gtk_widget_destroy (top_widget); + g_object_unref (xml); + + return (response == GTK_RESPONSE_ACCEPT); +} + +static gboolean +service_complete (MailAccountGuiService *service, GHashTable *extra_config, GtkWidget **incomplete) +{ + const CamelProvider *prov = service->provider; + GtkWidget *path; + const char *text; + + if (!prov) + return TRUE; + + /* transports don't have a path */ + if (service->path) + path = GTK_WIDGET (service->path); + else + path = NULL; + + if (CAMEL_PROVIDER_NEEDS (prov, CAMEL_URL_PART_HOST)) { + text = gtk_entry_get_text (service->hostname); + if (!text || !*text) { + if (incomplete) + *incomplete = get_focused_widget (GTK_WIDGET (service->hostname), + GTK_WIDGET (service->username), + path, + NULL); + return FALSE; + } + } + + if (CAMEL_PROVIDER_NEEDS (prov, CAMEL_URL_PART_USER)) { + text = gtk_entry_get_text (service->username); + if (!text || !*text) { + if (incomplete) + *incomplete = get_focused_widget (GTK_WIDGET (service->username), + GTK_WIDGET (service->hostname), + path, + NULL); + return FALSE; + } + } + + if (CAMEL_PROVIDER_NEEDS (prov, CAMEL_URL_PART_PATH)) { + if (!path) { + d(printf ("aagh, transports aren't supposed to have paths.\n")); + return TRUE; + } + + text = gtk_entry_get_text (service->path); + if (!text || !*text) { + if (incomplete) + *incomplete = get_focused_widget (GTK_WIDGET (service->path), + GTK_WIDGET (service->hostname), + GTK_WIDGET (service->username), + NULL); + return FALSE; + } + } + + return TRUE; +} + +static gboolean +mail_account_gui_check_for_license (CamelProvider *prov) +{ + GConfClient *gconf; + gboolean accepted = TRUE, status; + GSList * providers_list, *l, *n; + char *provider; + + if (prov->flags & CAMEL_PROVIDER_HAS_LICENSE) { + gconf = mail_config_get_gconf_client (); + + providers_list = gconf_client_get_list (gconf, "/apps/evolution/mail/licenses", GCONF_VALUE_STRING, NULL); + + for (l = providers_list, accepted = FALSE; l && !accepted; l = g_slist_next (l)) + accepted = (strcmp ((char *)l->data, prov->protocol) == 0); + if (!accepted) { + /* Since the license is not yet accepted, pop-up a + * dialog to display the license agreement and check + * if the user accepts it + */ + + if ((accepted = display_license (prov)) == TRUE) { + provider = g_strdup (prov->protocol); + providers_list = g_slist_append (providers_list, + provider); + status = gconf_client_set_list (gconf, + "/apps/evolution/mail/licenses", + GCONF_VALUE_STRING, + providers_list, NULL); + } + } + l = providers_list; + while (l) { + n = g_slist_next (l); + g_free (l->data); + g_slist_free_1 (l); + l = n; + } + } + return accepted; +} + +gboolean +mail_account_gui_source_complete (MailAccountGui *gui, GtkWidget **incomplete) +{ + return service_complete (&gui->source, gui->extra_config, incomplete); +} + +void +mail_account_gui_auto_detect_extra_conf (MailAccountGui *gui) +{ + MailAccountGuiService *service = &gui->source; + CamelProvider *prov = service->provider; + GHashTable *auto_detected; + GtkWidget *path; + CamelURL *url; + char *text; + const char *tmp; + + if (!prov) + return; + + /* transports don't have a path */ + if (service->path) + path = GTK_WIDGET (service->path); + else + path = NULL; + + url = g_new0 (CamelURL, 1); + camel_url_set_protocol (url, prov->protocol); + + if (CAMEL_PROVIDER_ALLOWS (prov, CAMEL_URL_PART_HOST)) { + text = g_strdup (gtk_entry_get_text (service->hostname)); + if (*text) { + char *port; + + port = strchr (text, ':'); + if (port) { + *port++ = '\0'; + camel_url_set_port (url, atoi (port)); + } + + camel_url_set_host (url, text); + } + g_free (text); + } + + if (CAMEL_PROVIDER_ALLOWS (prov, CAMEL_URL_PART_USER)) { + text = g_strdup (gtk_entry_get_text (service->username)); + g_strstrip (text); + camel_url_set_user (url, text); + g_free (text); + } + + if (path && CAMEL_PROVIDER_ALLOWS (prov, CAMEL_URL_PART_PATH)) { + tmp = gtk_entry_get_text (service->path); + if (tmp && *tmp) + camel_url_set_path (url, tmp); + } + + camel_provider_auto_detect (prov, url, &auto_detected, NULL); + camel_url_free (url); + + if (auto_detected) { + CamelProviderConfEntry *entries; + GtkToggleButton *toggle; + GtkSpinButton *spin; + GtkEntry *entry; + char *value; + int i; + + entries = service->provider->extra_conf; + + for (i = 0; entries[i].type != CAMEL_PROVIDER_CONF_END; i++) { + GtkWidget *enable_widget = NULL; + + if (!entries[i].name) + continue; + + value = g_hash_table_lookup (auto_detected, entries[i].name); + if (!value) + continue; + + switch (entries[i].type) { + case CAMEL_PROVIDER_CONF_CHECKBOX: + toggle = g_hash_table_lookup (gui->extra_config, entries[i].name); + gtk_toggle_button_set_active (toggle, atoi (value)); + enable_widget = (GtkWidget *)toggle; + break; + + case CAMEL_PROVIDER_CONF_ENTRY: + entry = g_hash_table_lookup (gui->extra_config, entries[i].name); + if (value) + gtk_entry_set_text (entry, value); + enable_widget = (GtkWidget *)entry; + break; + + case CAMEL_PROVIDER_CONF_CHECKSPIN: + { + gboolean enable; + double val; + char *name; + + toggle = g_hash_table_lookup (gui->extra_config, entries[i].name); + name = g_strdup_printf ("%s_value", entries[i].name); + spin = g_hash_table_lookup (gui->extra_config, name); + g_free (name); + + enable = *value++ == 'y'; + gtk_toggle_button_set_active (toggle, enable); + g_assert (*value == ':'); + val = strtod (++value, NULL); + gtk_spin_button_set_value (spin, val); + enable_widget = (GtkWidget *)spin; + } + break; + default: + break; + } + + if (enable_widget) + gtk_widget_set_sensitive(enable_widget, e_account_writable_option(gui->account, prov->protocol, entries[i].name)); + + } + + g_hash_table_foreach (auto_detected, auto_detected_foreach, NULL); + g_hash_table_destroy (auto_detected); + } +} + +gboolean +mail_account_gui_transport_complete (MailAccountGui *gui, GtkWidget **incomplete) +{ + if (!gui->transport.provider) { + if (incomplete) + *incomplete = GTK_WIDGET (gui->transport.type); + return FALSE; + } + + /* If it's both source and transport, there's nothing extra to + * configure on the transport page. + */ + if (CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (gui->transport.provider)) { + if (gui->transport.provider == gui->source.provider) + return TRUE; + if (incomplete) + *incomplete = GTK_WIDGET (gui->transport.type); + return FALSE; + } + + if (!service_complete (&gui->transport, NULL, incomplete)) + return FALSE; + + /* FIXME? */ + if (gtk_toggle_button_get_active (gui->transport.needs_auth) && + CAMEL_PROVIDER_ALLOWS (gui->transport.provider, CAMEL_URL_PART_USER)) { + const char *text = gtk_entry_get_text (gui->transport.username); + + if (!text || !*text) { + if (incomplete) + *incomplete = get_focused_widget (GTK_WIDGET (gui->transport.username), + GTK_WIDGET (gui->transport.hostname), + NULL); + return FALSE; + } + } + + return TRUE; +} + +gboolean +mail_account_gui_management_complete (MailAccountGui *gui, GtkWidget **incomplete) +{ + const char *text; + + text = gtk_entry_get_text (gui->account_name); + if (text && *text) + return TRUE; + + if (incomplete) + *incomplete = GTK_WIDGET (gui->account_name); + + return FALSE; +} + + +static void +service_authtype_changed (GtkWidget *widget, gpointer user_data) +{ + MailAccountGuiService *service = user_data; + CamelServiceAuthType *authtype; + + service->authitem = widget; + authtype = g_object_get_data ((GObject *) widget, "authtype"); + + gtk_widget_set_sensitive (GTK_WIDGET (service->remember), authtype->need_password); +} + +static void +build_auth_menu (MailAccountGuiService *service, GList *all_authtypes, + GList *supported_authtypes, gboolean check_supported) +{ + GtkWidget *menu, *item, *first = NULL; + CamelServiceAuthType *current, *authtype, *sauthtype; + int history = 0, i; + GList *l, *s; + + if (service->authitem) + current = g_object_get_data ((GObject *) service->authitem, "authtype"); + else + current = NULL; + + service->authitem = NULL; + + menu = gtk_menu_new (); + + for (l = all_authtypes, i = 0; l; l = l->next, i++) { + authtype = l->data; + + item = gtk_menu_item_new_with_label (authtype->name); + for (s = supported_authtypes; s; s = s->next) { + sauthtype = s->data; + if (!strcmp (authtype->name, sauthtype->name)) + break; + } + + if (check_supported && !s) { + gtk_widget_set_sensitive (item, FALSE); + } else if (current && !strcmp (authtype->name, current->name)) { + first = item; + history = i; + } else if (!first) { + first = item; + history = i; + } + + g_object_set_data ((GObject *) item, "authtype", authtype); + g_signal_connect (item, "activate", G_CALLBACK (service_authtype_changed), service); + + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + + gtk_widget_show (item); + } + + gtk_option_menu_remove_menu (service->authtype); + gtk_option_menu_set_menu (service->authtype, menu); + + if (first) { + gtk_option_menu_set_history (service->authtype, history); + g_signal_emit_by_name (first, "activate"); + } +} + +static void +transport_provider_set_available (MailAccountGui *gui, CamelProvider *provider, + gboolean available) +{ + GtkWidget *menuitem; + + menuitem = g_object_get_data ((GObject *) gui->transport.type, provider->protocol); + g_return_if_fail (menuitem != NULL); + + gtk_widget_set_sensitive (menuitem, available); + + if (available) { + gpointer number = g_object_get_data ((GObject *) menuitem, "number"); + + g_signal_emit_by_name (menuitem, "activate"); + gtk_option_menu_set_history (gui->transport.type, GPOINTER_TO_UINT (number)); + } +} + +static void +source_type_changed (GtkWidget *widget, gpointer user_data) +{ + MailAccountGui *gui = user_data; + GtkWidget *file_entry, *label, *frame, *dwidget = NULL; + CamelProvider *provider; + gboolean writeable; + gboolean license_accepted = TRUE; + + provider = g_object_get_data ((GObject *) widget, "provider"); + + /* If the previously-selected provider has a linked transport, + * disable it. + */ + if (gui->source.provider && + CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (gui->source.provider)) + transport_provider_set_available (gui, gui->source.provider, FALSE); + + gui->source.provider = provider; + + if (gui->source.provider) { + writeable = e_account_writable_option (gui->account, gui->source.provider->protocol, "auth"); + gtk_widget_set_sensitive ((GtkWidget *) gui->source.authtype, writeable); + gtk_widget_set_sensitive ((GtkWidget *) gui->source.check_supported, writeable); + + writeable = e_account_writable_option (gui->account, gui->source.provider->protocol, "use_ssl"); + gtk_widget_set_sensitive ((GtkWidget *) gui->source.use_ssl, writeable); + + writeable = e_account_writable (gui->account, E_ACCOUNT_SOURCE_SAVE_PASSWD); + gtk_widget_set_sensitive ((GtkWidget *) gui->source.remember, writeable); + } + + if (provider) + gtk_label_set_text (gui->source.description, provider->description); + else + gtk_label_set_text (gui->source.description, ""); + + if (gui->source.provider) + license_accepted = mail_account_gui_check_for_license (gui->source.provider); + + frame = glade_xml_get_widget (gui->xml, "source_frame"); + if (provider && license_accepted) { + gtk_widget_show (frame); + + /* hostname */ + label = glade_xml_get_widget (gui->xml, "source_host_label"); + + if (CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_HOST)) { + dwidget = GTK_WIDGET (gui->source.hostname); + gtk_widget_show (GTK_WIDGET (gui->source.hostname)); + gtk_widget_show (label); + } else { + gtk_widget_hide (GTK_WIDGET (gui->source.hostname)); + gtk_widget_hide (label); + } + + /* username */ + label = glade_xml_get_widget (gui->xml, "source_user_label"); + + if (CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_USER)) { + if (!dwidget) + dwidget = GTK_WIDGET (gui->source.username); + gtk_widget_show (GTK_WIDGET (gui->source.username)); + gtk_widget_show (label); + } else { + gtk_widget_hide (GTK_WIDGET (gui->source.username)); + gtk_widget_hide (label); + } + + /* path */ + label = glade_xml_get_widget (gui->xml, "source_path_label"); + file_entry = glade_xml_get_widget (gui->xml, "source_path_entry"); + + if (CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_PATH)) { + if (!dwidget) + dwidget = GTK_WIDGET (gui->source.path); + + gtk_widget_show (GTK_WIDGET (file_entry)); + gtk_widget_show (label); + } else { + gtk_entry_set_text (gui->source.path, ""); + gtk_widget_hide (GTK_WIDGET (file_entry)); + gtk_widget_hide (label); + } + + /* ssl */ +#ifdef HAVE_SSL + gtk_widget_hide (gui->source.no_ssl); + if (provider && provider->flags & CAMEL_PROVIDER_SUPPORTS_SSL) { + gtk_widget_show (gui->source.ssl_frame); + gtk_widget_show (gui->source.ssl_hbox); + } else { + gtk_widget_hide (gui->source.ssl_frame); + gtk_widget_hide (gui->source.ssl_hbox); + } +#else + gtk_widget_hide (gui->source.ssl_hbox); + gtk_widget_show (gui->source.no_ssl); +#endif + + /* auth */ + frame = glade_xml_get_widget (gui->xml, "source_auth_frame"); + if (provider && CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_AUTH)) { + build_auth_menu (&gui->source, provider->authtypes, NULL, FALSE); + gtk_widget_show (frame); + } else + gtk_widget_hide (frame); + } else { + gtk_widget_hide (frame); + frame = glade_xml_get_widget (gui->xml, "source_auth_frame"); + gtk_widget_hide (frame); + } + + g_signal_emit_by_name (gui->source.username, "changed"); + + if (dwidget) + gtk_widget_grab_focus (dwidget); + + mail_account_gui_build_extra_conf (gui, gui && gui->account && gui->account->source ? gui->account->source->url : NULL); + + if (provider && CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (provider)) + transport_provider_set_available (gui, provider, TRUE); +} + + +static void +transport_needs_auth_toggled (GtkToggleButton *toggle, gpointer data) +{ + MailAccountGui *gui = data; + gboolean need = gtk_toggle_button_get_active (toggle); + GtkWidget *widget; + + widget = glade_xml_get_widget (gui->xml, "transport_auth_frame"); + gtk_widget_set_sensitive (widget, need); + if (need) + service_changed (NULL, &gui->transport); +} + +static void +transport_type_changed (GtkWidget *widget, gpointer user_data) +{ + MailAccountGui *gui = user_data; + CamelProvider *provider; + GtkWidget *label, *frame; + gboolean writeable; + + provider = g_object_get_data ((GObject *) widget, "provider"); + gui->transport.provider = provider; + + if (gui->transport.provider) { + writeable = e_account_writable_option (gui->account, gui->transport.provider->protocol, "auth"); + gtk_widget_set_sensitive ((GtkWidget *) gui->transport.authtype, writeable); + gtk_widget_set_sensitive ((GtkWidget *) gui->transport.check_supported, writeable); + + writeable = e_account_writable_option (gui->account, gui->transport.provider->protocol, "use_ssl"); + gtk_widget_set_sensitive ((GtkWidget *) gui->transport.use_ssl, writeable); + + writeable = e_account_writable (gui->account, E_ACCOUNT_TRANSPORT_SAVE_PASSWD); + gtk_widget_set_sensitive ((GtkWidget *) gui->transport.remember, writeable); + } + + /* description */ + gtk_label_set_text (gui->transport.description, provider->description); + + frame = glade_xml_get_widget (gui->xml, "transport_frame"); + if (!CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (provider) && + (CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_HOST) || + (CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_AUTH) && + !CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_AUTH)))) { + gtk_widget_show (frame); + + label = glade_xml_get_widget (gui->xml, "transport_host_label"); + if (CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_HOST)) { + gtk_widget_show (GTK_WIDGET (gui->transport.hostname)); + gtk_widget_show (label); + } else { + gtk_widget_hide (GTK_WIDGET (gui->transport.hostname)); + gtk_widget_hide (label); + } + + /* ssl */ +#ifdef HAVE_SSL + gtk_widget_hide (gui->transport.no_ssl); + if (provider && provider->flags & CAMEL_PROVIDER_SUPPORTS_SSL) { + gtk_widget_show (gui->transport.ssl_frame); + gtk_widget_show (gui->transport.ssl_hbox); + } else { + gtk_widget_hide (gui->transport.ssl_frame); + gtk_widget_hide (gui->transport.ssl_hbox); + } +#else + gtk_widget_hide (gui->transport.ssl_hbox); + gtk_widget_show (gui->transport.no_ssl); +#endif + + /* auth */ + if (CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_AUTH) && + !CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_AUTH)) + gtk_widget_show (GTK_WIDGET (gui->transport.needs_auth)); + else + gtk_widget_hide (GTK_WIDGET (gui->transport.needs_auth)); + } else + gtk_widget_hide (frame); + + frame = glade_xml_get_widget (gui->xml, "transport_auth_frame"); + if (!CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (provider) && + CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_AUTH)) { + gtk_widget_show (frame); + + label = glade_xml_get_widget (gui->xml, "transport_user_label"); + if (CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_USER)) { + gtk_widget_show (GTK_WIDGET (gui->transport.username)); + gtk_widget_show (label); + } else { + gtk_widget_hide (GTK_WIDGET (gui->transport.username)); + gtk_widget_hide (label); + } + + build_auth_menu (&gui->transport, provider->authtypes, NULL, FALSE); + transport_needs_auth_toggled (gui->transport.needs_auth, gui); + } else + gtk_widget_hide (frame); + + g_signal_emit_by_name (gui->transport.hostname, "changed"); +} + +static void +service_changed (GtkEntry *entry, gpointer user_data) +{ + MailAccountGuiService *service = user_data; + + gtk_widget_set_sensitive (GTK_WIDGET (service->check_supported), + service_complete (service, NULL, NULL)); +} + +/* the fun of async ... */ +struct _service_check_data { + MailAccountGuiService *gsvc; + GtkWidget *dialog; + GtkWidget *window; + + int id; + gulong destroy_id; + int destroyed:1; +}; + +static void +service_check_done(const char *url, CamelProviderType type, GList *types, void *data) +{ + struct _service_check_data *sd = data; + + if (!sd->destroyed) { + gtk_widget_set_sensitive(sd->window, TRUE); + build_auth_menu(sd->gsvc, sd->gsvc->provider->authtypes, types, TRUE); + } + + if (sd->dialog) { + gtk_widget_destroy(sd->dialog); + sd->dialog = NULL; + } + + if (sd->destroy_id) + g_signal_handler_disconnect(sd->window, sd->destroy_id); + + g_free(sd); +} + +static void +service_check_response(GtkDialog *d, int button, struct _service_check_data *sd) +{ + mail_msg_cancel(sd->id); + + gtk_widget_destroy(sd->dialog); + sd->dialog = NULL; +} + +static void +service_check_destroy(GtkWindow *w, struct _service_check_data *sd) +{ + sd->destroy_id = 0; + sd->destroyed = TRUE; + mail_msg_cancel(sd->id); +} + +static void +service_check_supported (GtkButton *button, gpointer user_data) +{ + MailAccountGuiService *gsvc = user_data; + EAccountService *service; + GtkWidget *dialog; + GtkWidget *authitem; + struct _service_check_data *sd; + + sd = g_malloc0(sizeof(*sd)); + sd->id = -1; + sd->gsvc = gsvc; + + /* This is sort of a hack, when checking for supported AUTH + types we don't want to use whatever authtype is selected + because it may not be available. */ + service = g_malloc0(sizeof(*service)); + authitem = gsvc->authitem; + gsvc->authitem = NULL; + save_service (gsvc, NULL, service); + gsvc->authitem = authitem; + + sd->window = gtk_widget_get_toplevel((GtkWidget *)button); + sd->destroy_id = g_signal_connect(sd->window, "destroy", G_CALLBACK(service_check_destroy), sd); + + gtk_widget_set_sensitive(sd->window, FALSE); + dialog = gtk_dialog_new_with_buttons(_("Connecting to server..."), + (GtkWindow *)sd->window, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + NULL); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), + gtk_label_new(_("Connecting to server...")), + TRUE, TRUE, 10); + g_signal_connect(dialog, "response", G_CALLBACK(service_check_response), sd); + gtk_widget_show_all(dialog); + + sd->dialog = dialog; + sd->id = mail_check_service(service->url, gsvc->provider_type, service_check_done, sd); + + g_free (service->url); + g_free (service); +} + + +static void +toggle_sensitivity (GtkToggleButton *toggle, GtkWidget *widget) +{ + gtk_widget_set_sensitive (widget, gtk_toggle_button_get_active (toggle)); +} + +/* Returns true if the widget is enabled */ +static gboolean +setup_toggle (GtkWidget *widget, const char *depname, MailAccountGui *gui) +{ + GtkToggleButton *toggle; + + if (!strcmp (depname, "UNIMPLEMENTED")) { + gtk_widget_set_sensitive (widget, FALSE); + return FALSE; + } + + toggle = g_hash_table_lookup (gui->extra_config, depname); + g_signal_connect (toggle, "toggled", G_CALLBACK (toggle_sensitivity), widget); + toggle_sensitivity (toggle, widget); + + return gtk_toggle_button_get_active(toggle); +} + +void +mail_account_gui_build_extra_conf (MailAccountGui *gui, const char *url_string) +{ + CamelURL *url; + GtkWidget *mailcheck_frame, *mailcheck_hbox; + GtkWidget *hostname_label, *username_label, *path_label; + GtkWidget *hostname, *username, *path; + GtkTable *main_table, *cur_table; + CamelProviderConfEntry *entries; + GList *child, *next; + char *name; + int i, rows; + + if (url_string) + url = camel_url_new (url_string, NULL); + else + url = NULL; + + hostname_label = glade_xml_get_widget (gui->xml, "source_host_label"); + gtk_label_set_text_with_mnemonic (GTK_LABEL (hostname_label), _("_Host:")); + hostname = glade_xml_get_widget (gui->xml, "source_host"); + + username_label = glade_xml_get_widget (gui->xml, "source_user_label"); + gtk_label_set_text_with_mnemonic (GTK_LABEL (username_label), _("User_name:")); + username = glade_xml_get_widget (gui->xml, "source_user"); + + path_label = glade_xml_get_widget (gui->xml, "source_path_label"); + gtk_label_set_text_with_mnemonic (GTK_LABEL (path_label), _("_Path:")); + path = glade_xml_get_widget (gui->xml, "source_path"); + + /* Remove the contents of the extra_table except for the + * mailcheck_frame. + */ + main_table = (GtkTable *) glade_xml_get_widget (gui->xml, "extra_table"); + gtk_container_set_border_width ((GtkContainer *) main_table, 12); + gtk_table_set_row_spacings (main_table, 6); + gtk_table_set_col_spacings (main_table, 8); + mailcheck_frame = glade_xml_get_widget (gui->xml, "extra_mailcheck_frame"); + child = gtk_container_get_children (GTK_CONTAINER (main_table)); + while (child != NULL) { + next = child->next; + if (child->data != (gpointer) mailcheck_frame) + gtk_container_remove (GTK_CONTAINER (main_table), child->data); + g_list_free_1 (child); + child = next; + } + + gtk_table_resize (main_table, 1, 2); + + /* Remove any additional mailcheck items. */ + cur_table = (GtkTable *) glade_xml_get_widget (gui->xml, "extra_mailcheck_table"); + gtk_container_set_border_width ((GtkContainer *) cur_table, 12); + gtk_table_set_row_spacings (cur_table, 6); + gtk_table_set_col_spacings (cur_table, 8); + mailcheck_hbox = glade_xml_get_widget (gui->xml, "extra_mailcheck_hbox"); + child = gtk_container_get_children (GTK_CONTAINER (cur_table)); + while (child != NULL) { + next = child->next; + if (child->data != (gpointer) mailcheck_hbox) + gtk_container_remove (GTK_CONTAINER (cur_table), child->data); + g_list_free_1 (child); + child = next; + } + + gtk_table_resize (cur_table, 1, 2); + + if (!gui->source.provider) { + gtk_widget_set_sensitive (GTK_WIDGET (main_table), FALSE); + if (url) + camel_url_free (url); + return; + } else + gtk_widget_set_sensitive(GTK_WIDGET(main_table), e_account_writable(gui->account, E_ACCOUNT_SOURCE_URL)); + + /* Set up our hash table. */ + if (gui->extra_config) + g_hash_table_destroy (gui->extra_config); + gui->extra_config = g_hash_table_new (g_str_hash, g_str_equal); + + entries = gui->source.provider->extra_conf; + if (!entries) + goto done; + + cur_table = main_table; + rows = main_table->nrows; + for (i = 0; ; i++) { + GtkWidget *enable_widget = NULL; + int enabled = TRUE; + + switch (entries[i].type) { + case CAMEL_PROVIDER_CONF_SECTION_START: + { + GtkWidget *frame, *label; + char *markup; + + if (entries[i].name && !strcmp (entries[i].name, "mailcheck")) { + cur_table = (GtkTable *) glade_xml_get_widget (gui->xml, "extra_mailcheck_table"); + rows = cur_table->nrows; + break; + } + + markup = g_strdup_printf ("<span weight=\"bold\">%s</span>", entries[i].text); + label = gtk_label_new (NULL); + gtk_label_set_markup ((GtkLabel *) label, markup); + gtk_label_set_justify ((GtkLabel *) label, GTK_JUSTIFY_LEFT); + gtk_label_set_use_markup ((GtkLabel *) label, TRUE); + gtk_misc_set_alignment ((GtkMisc *) label, 0.0, 0.5); + gtk_widget_show (label); + g_free (markup); + + cur_table = (GtkTable *) gtk_table_new (0, 2, FALSE); + gtk_container_set_border_width ((GtkContainer *) cur_table, 12); + gtk_table_set_row_spacings (cur_table, 6); + gtk_table_set_col_spacings (cur_table, 8); + gtk_widget_show ((GtkWidget *) cur_table); + + frame = gtk_vbox_new (FALSE, 0); + gtk_box_pack_start ((GtkBox *) frame, label, FALSE, FALSE, 0); + gtk_box_pack_start ((GtkBox *) frame, (GtkWidget *) cur_table, FALSE, FALSE, 0); + gtk_widget_show (frame); + + gtk_table_attach (main_table, frame, 0, 2, + rows, rows + 1, + GTK_EXPAND | GTK_FILL, 0, 0, 0); + + rows = 0; + + break; + } + case CAMEL_PROVIDER_CONF_SECTION_END: + cur_table = main_table; + rows = main_table->nrows; + break; + + case CAMEL_PROVIDER_CONF_LABEL: + if (entries[i].name && entries[i].text) { + GtkWidget *label; + + if (!strcmp (entries[i].name, "username")) { + gtk_label_set_text_with_mnemonic (GTK_LABEL (username_label), entries[i].text); + enable_widget = username_label; + } else if (!strcmp (entries[i].name, "hostname")) { + gtk_label_set_text_with_mnemonic (GTK_LABEL (hostname_label), entries[i].text); + enable_widget = hostname_label; + } else if (!strcmp (entries[i].name, "path")) { + gtk_label_set_text_with_mnemonic (GTK_LABEL (path_label), entries[i].text); + enable_widget = path_label; + } else { + /* make a new label */ + label = gtk_label_new (entries[i].text); + gtk_table_resize (cur_table, cur_table->nrows + 1, 2); + gtk_table_attach (cur_table, label, 0, 2, rows, rows + 1, + GTK_EXPAND | GTK_FILL, 0, 0, 0); + rows++; + enable_widget = label; + } + } + break; + + case CAMEL_PROVIDER_CONF_CHECKBOX: + { + GtkWidget *checkbox; + gboolean active; + + checkbox = gtk_check_button_new_with_label (entries[i].text); + if (url) + active = camel_url_get_param (url, entries[i].name) != NULL; + else + active = atoi (entries[i].value); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbox), active); + + gtk_table_attach (cur_table, checkbox, 0, 2, rows, rows + 1, + GTK_EXPAND | GTK_FILL, 0, 0, 0); + rows++; + g_hash_table_insert (gui->extra_config, entries[i].name, checkbox); + if (entries[i].depname) + enabled = setup_toggle(checkbox, entries[i].depname, gui); + + enable_widget = checkbox; + break; + } + + case CAMEL_PROVIDER_CONF_ENTRY: + { + GtkWidget *label, *entry; + const char *text; + + if (!strcmp (entries[i].name, "username")) { + gtk_label_set_text_with_mnemonic (GTK_LABEL (username_label), entries[i].text); + label = username_label; + entry = username; + } else if (!strcmp (entries[i].name, "hostname")) { + gtk_label_set_text_with_mnemonic (GTK_LABEL (hostname_label), entries[i].text); + label = hostname_label; + entry = hostname; + } else if (!strcmp (entries[i].name, "path")) { + gtk_label_set_text_with_mnemonic (GTK_LABEL (path_label), entries[i].text); + label = path_label; + entry = path; + } else { + /* make a new text entry with label */ + label = gtk_label_new (entries[i].text); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0); + entry = gtk_entry_new (); + + gtk_table_attach (cur_table, label, 0, 1, rows, rows + 1, + GTK_FILL, 0, 0, 0); + gtk_table_attach (cur_table, entry, 1, 2, rows, rows + 1, + GTK_EXPAND | GTK_FILL, 0, 0, 0); + rows++; + } + + if (url) + text = camel_url_get_param (url, entries[i].name); + else + text = entries[i].value; + + if (text) + gtk_entry_set_text (GTK_ENTRY (entry), text); + + if (entries[i].depname) { + setup_toggle (entry, entries[i].depname, gui); + enabled = setup_toggle (label, entries[i].depname, gui); + } + + g_hash_table_insert (gui->extra_config, entries[i].name, entry); + + enable_widget = entry; + break; + } + + case CAMEL_PROVIDER_CONF_CHECKSPIN: + { + GtkWidget *hbox, *checkbox, *spin, *label; + GtkObject *adj; + char *data, *pre, *post, *p; + double min, def, max; + gboolean enable; + + /* FIXME: this is pretty fucked... */ + data = entries[i].text; + p = strstr (data, "%s"); + g_return_if_fail (p != NULL); + + pre = g_strndup (data, p - data); + post = p + 2; + + data = entries[i].value; + enable = *data++ == 'y'; + g_return_if_fail (*data == ':'); + min = strtod (data + 1, &data); + g_return_if_fail (*data == ':'); + def = strtod (data + 1, &data); + g_return_if_fail (*data == ':'); + max = strtod (data + 1, NULL); + + if (url) { + const char *val; + + val = camel_url_get_param (url, entries[i].name); + if (!val) + enable = FALSE; + else { + enable = TRUE; + def = atof (val); + } + } + + hbox = gtk_hbox_new (FALSE, 0); + checkbox = gtk_check_button_new_with_label (pre); + g_free (pre); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbox), enable); + adj = gtk_adjustment_new (def, min, max, 1, 1, 1); + spin = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 1, 0); + label = gtk_label_new (post); + + gtk_box_pack_start (GTK_BOX (hbox), checkbox, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), spin, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 4); + + gtk_table_attach (cur_table, hbox, 0, 2, rows, rows + 1, + GTK_EXPAND | GTK_FILL, 0, 0, 0); + rows++; + g_hash_table_insert (gui->extra_config, entries[i].name, checkbox); + name = g_strdup_printf ("%s_value", entries[i].name); + g_hash_table_insert (gui->extra_config, name, spin); + if (entries[i].depname) { + setup_toggle (checkbox, entries[i].depname, gui); + setup_toggle (spin, entries[i].depname, gui); + enabled = setup_toggle (label, entries[i].depname, gui); + } + + enable_widget = hbox; + break; + } + + case CAMEL_PROVIDER_CONF_HIDDEN: + break; + + case CAMEL_PROVIDER_CONF_END: + goto done; + } + + if (enabled && enable_widget) + gtk_widget_set_sensitive(enable_widget, e_account_writable_option(gui->account, gui->source.provider->protocol, entries[i].name)); + } + + done: + gtk_widget_show_all (GTK_WIDGET (main_table)); + if (url) + camel_url_free (url); +} + +static void +extract_values (MailAccountGuiService *source, GHashTable *extra_config, CamelURL *url) +{ + CamelProviderConfEntry *entries; + GtkToggleButton *toggle; + GtkEntry *entry; + GtkSpinButton *spin; + char *name; + int i; + + if (!source->provider || !source->provider->extra_conf) + return; + entries = source->provider->extra_conf; + + for (i = 0; ; i++) { + if (entries[i].depname) { + toggle = g_hash_table_lookup (extra_config, entries[i].depname); + if (!toggle || !gtk_toggle_button_get_active (toggle)) + continue; + } + + switch (entries[i].type) { + case CAMEL_PROVIDER_CONF_CHECKBOX: + toggle = g_hash_table_lookup (extra_config, entries[i].name); + if (gtk_toggle_button_get_active (toggle)) + camel_url_set_param (url, entries[i].name, ""); + break; + + case CAMEL_PROVIDER_CONF_ENTRY: + if (strcmp (entries[i].name, "username") == 0 + || strcmp (entries[i].name, "hostname") == 0 + || strcmp (entries[i].name, "path") == 0) { + break; + } + entry = g_hash_table_lookup (extra_config, entries[i].name); + camel_url_set_param (url, entries[i].name, gtk_entry_get_text (entry)); + break; + + case CAMEL_PROVIDER_CONF_CHECKSPIN: + toggle = g_hash_table_lookup (extra_config, entries[i].name); + if (!gtk_toggle_button_get_active (toggle)) + break; + name = g_strdup_printf ("%s_value", entries[i].name); + spin = g_hash_table_lookup (extra_config, name); + g_free (name); + name = g_strdup_printf ("%d", gtk_spin_button_get_value_as_int (spin)); + camel_url_set_param (url, entries[i].name, name); + g_free (name); + break; + + case CAMEL_PROVIDER_CONF_HIDDEN: + if (entries[i].value) + camel_url_set_param (url, entries[i].name, entries[i].value); + break; + + case CAMEL_PROVIDER_CONF_END: + return; + + default: + break; + } + } +} + +static void +folder_selected (EMFolderSelectionButton *button, gpointer user_data) +{ + char **folder_name = user_data; + + g_free (*folder_name); + *folder_name = g_strdup(em_folder_selection_button_get_selection(button)); +} + +static void +default_folders_clicked (GtkButton *button, gpointer user_data) +{ + MailAccountGui *gui = user_data; + + /* Drafts folder */ + g_free (gui->drafts_folder_uri); + gui->drafts_folder_uri = g_strdup(mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_DRAFTS)); + em_folder_selection_button_set_selection((EMFolderSelectionButton *)gui->drafts_folder_button, gui->drafts_folder_uri); + + /* Sent folder */ + g_free (gui->sent_folder_uri); + gui->sent_folder_uri = g_strdup(mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_SENT)); + em_folder_selection_button_set_selection((EMFolderSelectionButton *)gui->sent_folder_button, gui->sent_folder_uri); +} + +GtkWidget *mail_account_gui_folder_selector_button_new (char *widget_name, char *string1, char *string2, int int1, int int2); + +GtkWidget * +mail_account_gui_folder_selector_button_new (char *widget_name, + char *string1, char *string2, + int int1, int int2) +{ + return (GtkWidget *)em_folder_selection_button_new(_("Select Folder"), NULL); +} + +static gboolean +setup_service (MailAccountGui *gui, MailAccountGuiService *gsvc, EAccountService *service) +{ + CamelURL *url = camel_url_new (service->url, NULL); + gboolean has_auth = FALSE; + + if (url == NULL || gsvc->provider == NULL) + return FALSE; + + if (url->user && CAMEL_PROVIDER_ALLOWS (gsvc->provider, CAMEL_URL_PART_USER)) + gtk_entry_set_text (gsvc->username, url->user); + + if (url->host && CAMEL_PROVIDER_ALLOWS (gsvc->provider, CAMEL_URL_PART_HOST)) { + char *hostname; + + if (url->port) + hostname = g_strdup_printf ("%s:%d", url->host, url->port); + else + hostname = g_strdup (url->host); + + gtk_entry_set_text (gsvc->hostname, hostname); + g_free (hostname); + } + + if (url->path && CAMEL_PROVIDER_ALLOWS (gsvc->provider, CAMEL_URL_PART_PATH)) + gtk_entry_set_text (gsvc->path, url->path); + + if (gsvc->provider->flags & CAMEL_PROVIDER_SUPPORTS_SSL) { + GList *children, *item; + const char *use_ssl; + int i; + + use_ssl = camel_url_get_param (url, "use_ssl"); + if (!use_ssl) + use_ssl = "never"; + else if (!*use_ssl) /* old config code just used an empty string as the value */ + use_ssl = "always"; + + children = gtk_container_get_children(GTK_CONTAINER (gtk_option_menu_get_menu (gsvc->use_ssl))); + for (item = children, i = 0; item; item = item->next, i++) { + if (!strcmp (use_ssl, ssl_options[i].value)) { + gtk_option_menu_set_history (gsvc->use_ssl, i); + g_signal_emit_by_name (item->data, "activate", gsvc); + break; + } + } + } + + if (url->authmech && CAMEL_PROVIDER_ALLOWS (gsvc->provider, CAMEL_URL_PART_AUTH)) { + GList *children, *item; + CamelServiceAuthType *authtype; + int i; + + children = gtk_container_get_children(GTK_CONTAINER (gtk_option_menu_get_menu (gsvc->authtype))); + for (item = children, i = 0; item; item = item->next, i++) { + authtype = g_object_get_data ((GObject *) item->data, "authtype"); + if (!authtype) + continue; + if (!strcmp (authtype->authproto, url->authmech)) { + gtk_option_menu_set_history (gsvc->authtype, i); + g_signal_emit_by_name (item->data, "activate"); + break; + } + } + g_list_free (children); + + has_auth = TRUE; + } + camel_url_free (url); + + gtk_toggle_button_set_active (gsvc->remember, service->save_passwd); + + gtk_widget_set_sensitive((GtkWidget *)gsvc->authtype, e_account_writable_option(gui->account, gsvc->provider->protocol, "auth")); + gtk_widget_set_sensitive((GtkWidget *)gsvc->use_ssl, e_account_writable_option(gui->account, gsvc->provider->protocol, "use_ssl")); + + return has_auth; +} + +static gint +provider_compare (const CamelProvider *p1, const CamelProvider *p2) +{ + /* sort providers based on "location" (ie. local or remote) */ + if (p1->flags & CAMEL_PROVIDER_IS_REMOTE) { + if (p2->flags & CAMEL_PROVIDER_IS_REMOTE) + return 0; + return -1; + } else { + if (p2->flags & CAMEL_PROVIDER_IS_REMOTE) + return 1; + return 0; + } +} + +static void +ssl_option_activate (GtkWidget *widget, gpointer user_data) +{ + MailAccountGuiService *service = user_data; + + service->ssl_selected = widget; +} + +static void +construct_ssl_menu (MailAccountGuiService *service) +{ + GtkWidget *menu, *item = NULL; + int i; + + menu = gtk_menu_new (); + + for (i = 0; i < num_ssl_options; i++) { + item = gtk_menu_item_new_with_label (_(ssl_options[i].label)); + g_object_set_data ((GObject *) item, "use_ssl", ssl_options[i].value); + g_signal_connect (item, "activate", G_CALLBACK (ssl_option_activate), service); + gtk_widget_show (item); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + } + + gtk_option_menu_remove_menu (service->use_ssl); + gtk_option_menu_set_menu (service->use_ssl, menu); + + gtk_option_menu_set_history (service->use_ssl, i - 1); + g_signal_emit_by_name (item, "activate", service); +} + +static void +sig_activate (GtkWidget *item, MailAccountGui *gui) +{ + ESignature *sig; + + sig = g_object_get_data ((GObject *) item, "sig"); + + gui->sig_uid = sig ? sig->uid : NULL; +} + +static void +signature_added (ESignatureList *signatures, ESignature *sig, MailAccountGui *gui) +{ + GtkWidget *menu, *item; + + menu = gtk_option_menu_get_menu (gui->sig_menu); + if (sig->autogen) + item = gtk_menu_item_new_with_label (_("Autogenerated")); + else + item = gtk_menu_item_new_with_label (sig->name); + g_object_set_data ((GObject *) item, "sig", sig); + g_signal_connect (item, "activate", G_CALLBACK (sig_activate), gui); + gtk_widget_show (item); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + + gtk_option_menu_set_history (gui->sig_menu, g_list_length (GTK_MENU_SHELL (menu)->children)); +} + +static void +signature_removed (ESignatureList *signatures, ESignature *sig, MailAccountGui *gui) +{ + GtkWidget *menu; + ESignature *cur; + GList *items; + + if (gui->sig_uid == sig->uid) + gui->sig_uid = NULL; + + menu = gtk_option_menu_get_menu (gui->sig_menu); + items = GTK_MENU_SHELL (menu)->children; + while (items != NULL) { + cur = g_object_get_data (items->data, "sig"); + if (cur == sig) { + gtk_widget_destroy (items->data); + break; + } + items = items->next; + } +} + +static void +menu_item_set_label (GtkMenuItem *item, const char *label) +{ + GtkWidget *widget; + + widget = gtk_bin_get_child ((GtkBin *) item); + if (GTK_IS_LABEL (widget)) + gtk_label_set_text ((GtkLabel *) widget, label); +} + +static void +signature_changed (ESignatureList *signatures, ESignature *sig, MailAccountGui *gui) +{ + GtkWidget *menu; + ESignature *cur; + GList *items; + + menu = gtk_option_menu_get_menu (gui->sig_menu); + items = GTK_MENU_SHELL (menu)->children; + while (items != NULL) { + cur = g_object_get_data (items->data, "sig"); + if (cur == sig) { + menu_item_set_label (items->data, sig->name); + break; + } + items = items->next; + } +} + +static void +clear_menu (GtkWidget *menu) +{ + while (GTK_MENU_SHELL (menu)->children) + gtk_container_remove (GTK_CONTAINER (menu), GTK_MENU_SHELL (menu)->children->data); +} + +static void +sig_fill_menu (MailAccountGui *gui) +{ + ESignatureList *signatures; + GtkWidget *menu, *item; + EIterator *it; + + menu = gtk_option_menu_get_menu (gui->sig_menu); + clear_menu (menu); + + item = gtk_menu_item_new_with_label (_("None")); + gtk_widget_show (item); + g_signal_connect (item, "activate", G_CALLBACK (sig_activate), gui); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + + signatures = mail_config_get_signatures (); + it = e_list_get_iterator ((EList *) signatures); + + while (e_iterator_is_valid (it)) { + ESignature *sig; + + sig = (ESignature *) e_iterator_get (it); + signature_added (signatures, sig, gui); + e_iterator_next (it); + } + + g_object_unref (it); + + gui->sig_added_id = g_signal_connect (signatures, "signature-added", G_CALLBACK (signature_added), gui); + gui->sig_removed_id = g_signal_connect (signatures, "signature-removed", G_CALLBACK (signature_removed), gui); + gui->sig_changed_id = g_signal_connect (signatures, "signature-changed", G_CALLBACK (signature_changed), gui); + + gtk_option_menu_set_history (gui->sig_menu, 0); +} + +static void +sig_switch_to_list (GtkWidget *w, MailAccountGui *gui) +{ + gtk_window_set_transient_for (GTK_WINDOW (gtk_widget_get_toplevel (w)), NULL); + gdk_window_raise (GTK_WIDGET (gui->dialog)->window); + gtk_notebook_set_current_page (GTK_NOTEBOOK (glade_xml_get_widget (gui->dialog->gui, "notebook")), 3); +} + +static void +sig_add_new_signature (GtkWidget *w, MailAccountGui *gui) +{ + GConfClient *gconf; + gboolean send_html; + GtkWidget *parent; + + if (!gui->dialog) + return; + + sig_switch_to_list (w, gui); + + gconf = mail_config_get_gconf_client (); + send_html = gconf_client_get_bool (gconf, "/apps/evolution/mail/composer/send_html", NULL); + + parent = gtk_widget_get_toplevel (w); + parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL; + + em_composer_prefs_new_signature ((GtkWindow *) parent, send_html); +} + +static void +select_account_signature (MailAccountGui *gui) +{ + ESignature *sig, *cur; + GtkWidget *menu; + GList *items; + int i = 0; + + if (!gui->account->id->sig_uid || !(sig = mail_config_get_signature_by_uid (gui->account->id->sig_uid))) + return; + + menu = gtk_option_menu_get_menu (gui->sig_menu); + items = GTK_MENU_SHELL (menu)->children; + while (items != NULL) { + cur = g_object_get_data (items->data, "sig"); + if (cur == sig) { + gtk_option_menu_set_history (gui->sig_menu, i); + gtk_menu_item_activate (items->data); + break; + } + items = items->next; + i++; + } +} + +static void +prepare_signatures (MailAccountGui *gui) +{ + GtkWidget *button; + + gui->sig_menu = (GtkOptionMenu *) glade_xml_get_widget (gui->xml, "sigOption"); + sig_fill_menu (gui); + + button = glade_xml_get_widget (gui->xml, "sigAddNew"); + g_signal_connect (button, "clicked", G_CALLBACK (sig_add_new_signature), gui); + + if (!gui->dialog) { + gtk_widget_hide (glade_xml_get_widget (gui->xml, "sigLabel")); + gtk_widget_hide (glade_xml_get_widget (gui->xml, "sigOption")); + gtk_widget_hide (glade_xml_get_widget (gui->xml, "sigAddNew")); + } + + select_account_signature (gui); +} + +#if defined (HAVE_NSS) +static void +smime_changed(MailAccountGui *gui) +{ + int act; + const char *tmp; + + tmp = gtk_entry_get_text(gui->smime_sign_key); + act = tmp && tmp[0]; + gtk_widget_set_sensitive((GtkWidget *)gui->smime_sign_key_clear, act); + gtk_widget_set_sensitive((GtkWidget *)gui->smime_sign_default, act); + if (!act) + gtk_toggle_button_set_active(gui->smime_sign_default, FALSE); + + tmp = gtk_entry_get_text(gui->smime_encrypt_key); + act = tmp && tmp[0]; + gtk_widget_set_sensitive((GtkWidget *)gui->smime_encrypt_key_clear, act); + gtk_widget_set_sensitive((GtkWidget *)gui->smime_encrypt_default, act); + gtk_widget_set_sensitive((GtkWidget *)gui->smime_encrypt_to_self, act); + if (!act) { + gtk_toggle_button_set_active(gui->smime_encrypt_default, FALSE); + gtk_toggle_button_set_active(gui->smime_encrypt_to_self, FALSE); + } +} + +static void +smime_sign_key_selected(GtkWidget *dialog, const char *key, MailAccountGui *gui) +{ + if (key != NULL) { + gtk_entry_set_text(gui->smime_sign_key, key); + smime_changed(gui); + } + + gtk_widget_destroy(dialog); +} + +static void +smime_sign_key_select(GtkWidget *button, MailAccountGui *gui) +{ + GtkWidget *w; + + w = e_cert_selector_new(E_CERT_SELECTOR_SIGNER, gtk_entry_get_text(gui->smime_sign_key)); + gtk_window_set_modal((GtkWindow *)w, TRUE); + gtk_window_set_transient_for((GtkWindow *)w, (GtkWindow *)gui->dialog); + g_signal_connect(w, "selected", G_CALLBACK(smime_sign_key_selected), gui); + gtk_widget_show(w); +} + +static void +smime_sign_key_clear(GtkWidget *w, MailAccountGui *gui) +{ + gtk_entry_set_text(gui->smime_sign_key, ""); + smime_changed(gui); +} + +static void +smime_encrypt_key_selected(GtkWidget *dialog, const char *key, MailAccountGui *gui) +{ + if (key != NULL) { + gtk_entry_set_text(gui->smime_encrypt_key, key); + smime_changed(gui); + } + + gtk_widget_destroy(dialog); +} + +static void +smime_encrypt_key_select(GtkWidget *button, MailAccountGui *gui) +{ + GtkWidget *w; + + w = e_cert_selector_new(E_CERT_SELECTOR_SIGNER, gtk_entry_get_text(gui->smime_encrypt_key)); + gtk_window_set_modal((GtkWindow *)w, TRUE); + gtk_window_set_transient_for((GtkWindow *)w, (GtkWindow *)gui->dialog); + g_signal_connect(w, "selected", G_CALLBACK(smime_encrypt_key_selected), gui); + gtk_widget_show(w); +} + +static void +smime_encrypt_key_clear(GtkWidget *w, MailAccountGui *gui) +{ + gtk_entry_set_text(gui->smime_encrypt_key, ""); + smime_changed(gui); +} +#endif + +#ifdef USE_GTKFILECHOOSER +static void +select_file_toggled (GtkToggleButton *toggle, GtkFileChooser *chooser) +{ + GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; + + if (gtk_toggle_button_get_active (toggle)) + action = GTK_FILE_CHOOSER_ACTION_OPEN; + + gtk_file_chooser_set_action (chooser, action); +} + +static void +browse_clicked (GnomeFileEntry *fentry, MailAccountGui *gui) +{ + GtkWidget *check; + struct stat st; + char *path; + + if (GTK_IS_FILE_CHOOSER (fentry->fsw)) { + check = gtk_check_button_new_with_label (_("Select a file")); + g_signal_connect (check, "toggled", G_CALLBACK (select_file_toggled), fentry->fsw); + gtk_widget_show (check); + gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (fentry->fsw), check); + + path = gnome_file_entry_get_full_path (fentry, TRUE); + if (path && stat (path, &st) == 0 && S_ISREG (st.st_mode)) + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE); + else + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), FALSE); + gtk_toggle_button_toggled (GTK_TOGGLE_BUTTON (check)); + g_free (path); + } + + g_signal_handlers_disconnect_by_func (fentry, G_CALLBACK (fentry), gui); +} +#endif /* USE_GTKFILECHOOSER */ + +MailAccountGui * +mail_account_gui_new (EAccount *account, EMAccountPrefs *dialog) +{ + MailAccountGui *gui; + GtkWidget *fileentry; + + g_object_ref (account); + + gui = g_new0 (MailAccountGui, 1); + gui->account = account; + gui->dialog = dialog; + gui->xml = glade_xml_new (EVOLUTION_GLADEDIR "/mail-config.glade", NULL, NULL); + +#ifdef USE_GTKFILECHOOSER + /* KLUDGE: If this Evolution was built with GtkFileChooser support, the user + * won't be able to create some types of local accounts because GtkFileChooser + * must be set to allow selection of one or the other of file vs folder. + * However, some providers allow the selection of files *or* folders. */ + fileentry = glade_xml_get_widget (gui->xml, "source_path_entry"); + g_signal_connect_after (fileentry, "browse-clicked", G_CALLBACK (browse_clicked), gui); +#endif + + /* Management */ + gui->account_name = GTK_ENTRY (glade_xml_get_widget (gui->xml, "management_name")); + gui->default_account = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui->xml, "management_default")); + if (account->name) + gtk_entry_set_text (gui->account_name, account->name); + if (!mail_config_get_default_account () + || (account == mail_config_get_default_account ())) + gtk_toggle_button_set_active (gui->default_account, TRUE); + + /* Identity */ + gui->full_name = GTK_ENTRY (glade_xml_get_widget (gui->xml, "identity_full_name")); + gui->email_address = GTK_ENTRY (glade_xml_get_widget (gui->xml, "identity_address")); + gui->reply_to = GTK_ENTRY (glade_xml_get_widget (gui->xml, "identity_reply_to")); + gui->organization = GTK_ENTRY (glade_xml_get_widget (gui->xml, "identity_organization")); + + if (account->id->name) + gtk_entry_set_text (gui->full_name, account->id->name); + if (account->id->address) + gtk_entry_set_text (gui->email_address, account->id->address); + if (account->id->reply_to) + gtk_entry_set_text (gui->reply_to, account->id->reply_to); + if (account->id->organization) + gtk_entry_set_text (gui->organization, account->id->organization); + + prepare_signatures (gui); + + /* Source */ + gui->source.provider_type = CAMEL_PROVIDER_STORE; + gui->source.container = glade_xml_get_widget(gui->xml, "source_vbox"); + gui->source.type = GTK_OPTION_MENU (glade_xml_get_widget (gui->xml, "source_type_omenu")); + gui->source.description = GTK_LABEL (glade_xml_get_widget (gui->xml, "source_description")); + gui->source.hostname = GTK_ENTRY (glade_xml_get_widget (gui->xml, "source_host")); + g_signal_connect (gui->source.hostname, "changed", + G_CALLBACK (service_changed), &gui->source); + gui->source.username = GTK_ENTRY (glade_xml_get_widget (gui->xml, "source_user")); + g_signal_connect (gui->source.username, "changed", + G_CALLBACK (service_changed), &gui->source); + gui->source.path = GTK_ENTRY (glade_xml_get_widget (gui->xml, "source_path")); + g_signal_connect (gui->source.path, "changed", + G_CALLBACK (service_changed), &gui->source); + gui->source.ssl_frame = glade_xml_get_widget (gui->xml, "source_security_frame"); + gtk_widget_hide (gui->source.ssl_frame); + gui->source.ssl_hbox = glade_xml_get_widget (gui->xml, "source_ssl_hbox"); + gui->source.use_ssl = GTK_OPTION_MENU (glade_xml_get_widget (gui->xml, "source_use_ssl")); + construct_ssl_menu (&gui->source); + gui->source.no_ssl = glade_xml_get_widget (gui->xml, "source_ssl_disabled"); + gui->source.authtype = GTK_OPTION_MENU (glade_xml_get_widget (gui->xml, "source_auth_omenu")); + gui->source.remember = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui->xml, "source_remember_password")); + gui->source.check_supported = GTK_BUTTON (glade_xml_get_widget (gui->xml, "source_check_supported")); + g_signal_connect (gui->source.check_supported, "clicked", + G_CALLBACK (service_check_supported), &gui->source); + gui->source_auto_check = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui->xml, "extra_auto_check")); + gui->source_auto_check_min = GTK_SPIN_BUTTON (glade_xml_get_widget (gui->xml, "extra_auto_check_min")); + + /* Transport */ + gui->transport.provider_type = CAMEL_PROVIDER_TRANSPORT; + gui->transport.container = glade_xml_get_widget(gui->xml, "transport_vbox"); + gui->transport.type = GTK_OPTION_MENU (glade_xml_get_widget (gui->xml, "transport_type_omenu")); + gui->transport.description = GTK_LABEL (glade_xml_get_widget (gui->xml, "transport_description")); + gui->transport.hostname = GTK_ENTRY (glade_xml_get_widget (gui->xml, "transport_host")); + g_signal_connect (gui->transport.hostname, "changed", + G_CALLBACK (service_changed), &gui->transport); + gui->transport.username = GTK_ENTRY (glade_xml_get_widget (gui->xml, "transport_user")); + g_signal_connect (gui->transport.username, "changed", + G_CALLBACK (service_changed), &gui->transport); + gui->transport.ssl_frame = glade_xml_get_widget (gui->xml, "transport_security_frame"); + gtk_widget_hide (gui->transport.ssl_frame); + gui->transport.ssl_hbox = glade_xml_get_widget (gui->xml, "transport_ssl_hbox"); + gui->transport.use_ssl = GTK_OPTION_MENU (glade_xml_get_widget (gui->xml, "transport_use_ssl")); + construct_ssl_menu (&gui->transport); + gui->transport.no_ssl = glade_xml_get_widget (gui->xml, "transport_ssl_disabled"); + gui->transport.needs_auth = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui->xml, "transport_needs_auth")); + g_signal_connect (gui->transport.needs_auth, "toggled", + G_CALLBACK (transport_needs_auth_toggled), gui); + gui->transport.authtype = GTK_OPTION_MENU (glade_xml_get_widget (gui->xml, "transport_auth_omenu")); + gui->transport.remember = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui->xml, "transport_remember_password")); + gui->transport.check_supported = GTK_BUTTON (glade_xml_get_widget (gui->xml, "transport_check_supported")); + g_signal_connect (gui->transport.check_supported, "clicked", + G_CALLBACK (service_check_supported), &gui->transport); + + /* Drafts folder */ + gui->drafts_folder_button = GTK_BUTTON (glade_xml_get_widget (gui->xml, "drafts_button")); + g_signal_connect (gui->drafts_folder_button, "selected", G_CALLBACK (folder_selected), &gui->drafts_folder_uri); + if (account->drafts_folder_uri) + gui->drafts_folder_uri = em_uri_to_camel (account->drafts_folder_uri); + else + gui->drafts_folder_uri = g_strdup(mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_DRAFTS)); + em_folder_selection_button_set_selection((EMFolderSelectionButton *)gui->drafts_folder_button, gui->drafts_folder_uri); + gtk_widget_show ((GtkWidget *) gui->drafts_folder_button); + + /* Sent folder */ + gui->sent_folder_button = GTK_BUTTON (glade_xml_get_widget (gui->xml, "sent_button")); + g_signal_connect (gui->sent_folder_button, "selected", G_CALLBACK (folder_selected), &gui->sent_folder_uri); + if (account->sent_folder_uri) + gui->sent_folder_uri = em_uri_to_camel (account->sent_folder_uri); + else + gui->sent_folder_uri = g_strdup(mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_SENT)); + em_folder_selection_button_set_selection((EMFolderSelectionButton *)gui->sent_folder_button, gui->sent_folder_uri); + gtk_widget_show ((GtkWidget *) gui->sent_folder_button); + + /* Special Folders "Reset Defaults" button */ + gui->restore_folders_button = (GtkButton *)glade_xml_get_widget (gui->xml, "default_folders_button"); + g_signal_connect (gui->restore_folders_button, "clicked", G_CALLBACK (default_folders_clicked), gui); + + /* Always Cc */ + gui->always_cc = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui->xml, "always_cc")); + gtk_toggle_button_set_active (gui->always_cc, account->always_cc); + gui->cc_addrs = GTK_ENTRY (glade_xml_get_widget (gui->xml, "cc_addrs")); + if (account->cc_addrs) + gtk_entry_set_text (gui->cc_addrs, account->cc_addrs); + + /* Always Bcc */ + gui->always_bcc = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui->xml, "always_bcc")); + gtk_toggle_button_set_active (gui->always_bcc, account->always_bcc); + gui->bcc_addrs = GTK_ENTRY (glade_xml_get_widget (gui->xml, "bcc_addrs")); + if (account->bcc_addrs) + gtk_entry_set_text (gui->bcc_addrs, account->bcc_addrs); + + /* Security */ + gui->pgp_key = GTK_ENTRY (glade_xml_get_widget (gui->xml, "pgp_key")); + if (account->pgp_key) + gtk_entry_set_text (gui->pgp_key, account->pgp_key); + gui->pgp_encrypt_to_self = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui->xml, "pgp_encrypt_to_self")); + gtk_toggle_button_set_active (gui->pgp_encrypt_to_self, account->pgp_encrypt_to_self); + gui->pgp_always_sign = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui->xml, "pgp_always_sign")); + gtk_toggle_button_set_active (gui->pgp_always_sign, account->pgp_always_sign); + gui->pgp_no_imip_sign = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui->xml, "pgp_no_imip_sign")); + gtk_toggle_button_set_active (gui->pgp_no_imip_sign, account->pgp_no_imip_sign); + gui->pgp_always_trust = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui->xml, "pgp_always_trust")); + gtk_toggle_button_set_active (gui->pgp_always_trust, account->pgp_always_trust); + +#if defined (HAVE_NSS) + gui->smime_sign_key = (GtkEntry *)glade_xml_get_widget (gui->xml, "smime_sign_key"); + if (account->smime_sign_key) + gtk_entry_set_text(gui->smime_sign_key, account->smime_sign_key); + gui->smime_sign_key_select = (GtkButton *)glade_xml_get_widget (gui->xml, "smime_sign_key_select"); + gui->smime_sign_key_clear = (GtkButton *)glade_xml_get_widget (gui->xml, "smime_sign_key_clear"); + g_signal_connect(gui->smime_sign_key_select, "clicked", G_CALLBACK(smime_sign_key_select), gui); + g_signal_connect(gui->smime_sign_key_clear, "clicked", G_CALLBACK(smime_sign_key_clear), gui); + + gui->smime_sign_default = (GtkToggleButton *)glade_xml_get_widget (gui->xml, "smime_sign_default"); + gtk_toggle_button_set_active(gui->smime_sign_default, account->smime_sign_default); + + gui->smime_encrypt_key = (GtkEntry *)glade_xml_get_widget (gui->xml, "smime_encrypt_key"); + if (account->smime_encrypt_key) + gtk_entry_set_text(gui->smime_encrypt_key, account->smime_encrypt_key); + gui->smime_encrypt_key_select = (GtkButton *)glade_xml_get_widget (gui->xml, "smime_encrypt_key_select"); + gui->smime_encrypt_key_clear = (GtkButton *)glade_xml_get_widget (gui->xml, "smime_encrypt_key_clear"); + g_signal_connect(gui->smime_encrypt_key_select, "clicked", G_CALLBACK(smime_encrypt_key_select), gui); + g_signal_connect(gui->smime_encrypt_key_clear, "clicked", G_CALLBACK(smime_encrypt_key_clear), gui); + + gui->smime_encrypt_default = (GtkToggleButton *)glade_xml_get_widget (gui->xml, "smime_encrypt_default"); + gtk_toggle_button_set_active(gui->smime_encrypt_default, account->smime_encrypt_default); + gui->smime_encrypt_to_self = (GtkToggleButton *)glade_xml_get_widget (gui->xml, "smime_encrypt_to_self"); + gtk_toggle_button_set_active(gui->smime_encrypt_to_self, account->smime_encrypt_to_self); + smime_changed(gui); +#else + { + /* Since we don't have NSS, hide the S/MIME config options */ + GtkWidget *frame; + + frame = glade_xml_get_widget (gui->xml, "smime_vbox"); + gtk_widget_destroy (frame); + } +#endif /* HAVE_NSS */ + + return gui; +} + +void +mail_account_gui_setup (MailAccountGui *gui, GtkWidget *top) +{ + GtkWidget *stores, *transports, *item, *none; + GtkWidget *fstore = NULL, *ftransport = NULL; + int si = 0, hstore = 0, ti = 0, htransport = 0; + int max_width = 0; + char *max_authname = NULL; + char *source_proto, *transport_proto; + GList *providers, *l; + gboolean writeable; + + printf("account gui setup\n"); + + if (gui->account->source && gui->account->source->url) { + source_proto = gui->account->source->url; + source_proto = g_strndup (source_proto, strcspn (source_proto, ":")); + } else + source_proto = NULL; + + if (gui->account->transport && gui->account->transport->url) { + transport_proto = gui->account->transport->url; + transport_proto = g_strndup (transport_proto, strcspn (transport_proto, ":")); + } else + transport_proto = NULL; + + /* Construct source/transport option menus */ + stores = gtk_menu_new (); + transports = gtk_menu_new (); + + /* add a "None" option to the stores menu */ + none = item = gtk_menu_item_new_with_label (_("None")); + g_object_set_data ((GObject *) item, "provider", NULL); + g_signal_connect (item, "activate", G_CALLBACK (source_type_changed), gui); + gtk_menu_shell_append(GTK_MENU_SHELL(stores), item); + gtk_widget_show (item); + si++; + + providers = camel_provider_list(TRUE); + + /* sort the providers, remote first */ + providers = g_list_sort (providers, (GCompareFunc) provider_compare); + + for (l = providers; l; l = l->next) { + CamelProvider *provider = l->data; + + if (!(!strcmp (provider->domain, "mail") || !strcmp (provider->domain, "news"))) + continue; + + item = NULL; + if (provider->object_types[CAMEL_PROVIDER_STORE] && provider->flags & CAMEL_PROVIDER_IS_SOURCE) { + item = gtk_menu_item_new_with_label (provider->name); + g_object_set_data ((GObject *) gui->source.type, provider->protocol, item); + g_object_set_data ((GObject *) item, "provider", provider); + g_object_set_data ((GObject *) item, "number", GUINT_TO_POINTER (si)); + g_signal_connect (item, "activate", G_CALLBACK (source_type_changed), gui); + + gtk_menu_shell_append(GTK_MENU_SHELL(stores), item); + + gtk_widget_show (item); + + if (!fstore) { + fstore = item; + hstore = si; + } + + if (source_proto && !g_ascii_strcasecmp (provider->protocol, source_proto)) { + fstore = item; + hstore = si; + } + + si++; + } + + if (provider->object_types[CAMEL_PROVIDER_TRANSPORT]) { + item = gtk_menu_item_new_with_label (provider->name); + g_object_set_data ((GObject *) gui->transport.type, provider->protocol, item); + g_object_set_data ((GObject *) item, "provider", provider); + g_object_set_data ((GObject *) item, "number", GUINT_TO_POINTER (ti)); + g_signal_connect (item, "activate", G_CALLBACK (transport_type_changed), gui); + + gtk_menu_shell_append(GTK_MENU_SHELL(transports), item); + + gtk_widget_show (item); + + if (CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (provider)) + gtk_widget_set_sensitive (item, FALSE); + + if (!ftransport + && !CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (provider)) { + ftransport = item; + htransport = ti; + } + + if (transport_proto && !g_ascii_strcasecmp (provider->protocol, transport_proto)) { + ftransport = item; + htransport = ti; + } + + ti++; + } + + if (item && provider->authtypes) { + /*GdkFont *font = GTK_WIDGET (item)->style->font;*/ + CamelServiceAuthType *at; + int width; + GList *a; + + for (a = provider->authtypes; a; a = a->next) { + at = a->data; + + /* Just using string length is probably good enough, + as we only use the width of the widget, not the string */ + /*width = gdk_string_width (font, at->name);*/ + width = strlen(at->name) * 14; + if (width > max_width) { + max_authname = at->name; + max_width = width; + } + } + } + } + g_list_free (providers); + + if (!fstore || !source_proto) { + fstore = none; + hstore = 0; + } + + /* set the menus on the optionmenus */ + gtk_option_menu_remove_menu (gui->source.type); + gtk_option_menu_set_menu (gui->source.type, stores); + + gtk_option_menu_remove_menu (gui->transport.type); + gtk_option_menu_set_menu (gui->transport.type, transports); + + /* Force the authmenus to the width of the widest element */ + if (max_authname) { + GtkWidget *menu; + GtkRequisition size_req; + + menu = gtk_menu_new (); + item = gtk_menu_item_new_with_label (max_authname); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + gtk_widget_show_all (menu); + gtk_option_menu_set_menu (gui->source.authtype, menu); + gtk_widget_show (GTK_WIDGET (gui->source.authtype)); + gtk_widget_size_request (GTK_WIDGET (gui->source.authtype), + &size_req); + + gtk_widget_set_size_request (GTK_WIDGET (gui->source.authtype), + size_req.width, -1); + gtk_widget_set_size_request (GTK_WIDGET (gui->transport.authtype), + size_req.width, -1); + } + + if (top != NULL) { + gtk_widget_show (top); + } + + if (fstore) { + g_signal_emit_by_name (fstore, "activate"); + gtk_option_menu_set_history (gui->source.type, hstore); + } + + if (ftransport) { + g_signal_emit_by_name (ftransport, "activate"); + gtk_option_menu_set_history (gui->transport.type, htransport); + } + + if (source_proto) { + setup_service (gui, &gui->source, gui->account->source); + gui->source.provider_type = CAMEL_PROVIDER_STORE; + g_free (source_proto); + if (gui->account->source->auto_check) { + gtk_toggle_button_set_active (gui->source_auto_check, TRUE); + gtk_spin_button_set_value (gui->source_auto_check_min, + gui->account->source->auto_check_time); + } + } + + if (transport_proto) { + if (setup_service (gui, &gui->transport, gui->account->transport)) + gtk_toggle_button_set_active (gui->transport.needs_auth, TRUE); + gui->transport.provider_type = CAMEL_PROVIDER_TRANSPORT; + g_free (transport_proto); + } + + /* FIXME: drive by table?? */ + if (!e_account_writable (gui->account, E_ACCOUNT_SOURCE_URL)) { + gtk_widget_set_sensitive (gui->source.container, FALSE); + } else { + gtk_widget_set_sensitive (gui->source.container, TRUE); + + if (gui->source.provider) { + writeable = e_account_writable_option (gui->account, gui->source.provider->protocol, "auth"); + gtk_widget_set_sensitive ((GtkWidget *) gui->source.authtype, writeable); + gtk_widget_set_sensitive ((GtkWidget *) gui->source.check_supported, writeable); + + writeable = e_account_writable_option (gui->account, gui->source.provider->protocol, "use_ssl"); + gtk_widget_set_sensitive ((GtkWidget *) gui->source.use_ssl, writeable); + + writeable = e_account_writable (gui->account, E_ACCOUNT_SOURCE_SAVE_PASSWD); + gtk_widget_set_sensitive ((GtkWidget *) gui->source.remember, writeable); + } + } + + if (!e_account_writable (gui->account, E_ACCOUNT_TRANSPORT_URL)) { + gtk_widget_set_sensitive (gui->transport.container, FALSE); + } else { + gtk_widget_set_sensitive (gui->transport.container, TRUE); + + if (gui->transport.provider) { + writeable = e_account_writable_option (gui->account, gui->transport.provider->protocol, "auth"); + gtk_widget_set_sensitive ((GtkWidget *) gui->transport.authtype, writeable); + gtk_widget_set_sensitive ((GtkWidget *) gui->transport.check_supported, writeable); + + writeable = e_account_writable_option (gui->account, gui->transport.provider->protocol, "use_ssl"); + gtk_widget_set_sensitive ((GtkWidget *) gui->transport.use_ssl, writeable); + + writeable = e_account_writable (gui->account, E_ACCOUNT_TRANSPORT_SAVE_PASSWD); + gtk_widget_set_sensitive ((GtkWidget *) gui->transport.remember, writeable); + } + } + + gtk_widget_set_sensitive((GtkWidget *)gui->drafts_folder_button, e_account_writable(gui->account, E_ACCOUNT_DRAFTS_FOLDER_URI)); + gtk_widget_set_sensitive((GtkWidget *)gui->sent_folder_button, e_account_writable(gui->account, E_ACCOUNT_SENT_FOLDER_URI)); + gtk_widget_set_sensitive((GtkWidget *)gui->restore_folders_button, + e_account_writable(gui->account, E_ACCOUNT_SENT_FOLDER_URI) + || e_account_writable(gui->account, E_ACCOUNT_DRAFTS_FOLDER_URI)); + gtk_widget_set_sensitive((GtkWidget *)gui->sig_menu, e_account_writable(gui->account, E_ACCOUNT_ID_SIGNATURE)); + gtk_widget_set_sensitive(glade_xml_get_widget(gui->xml, "sigAddNew"), + gconf_client_key_is_writable(mail_config_get_gconf_client(), + "/apps/evolution/mail/signatures", NULL)); + gtk_widget_set_sensitive((GtkWidget *)gui->source_auto_check, e_account_writable(gui->account, E_ACCOUNT_SOURCE_AUTO_CHECK)); + gtk_widget_set_sensitive((GtkWidget *)gui->source_auto_check_min, e_account_writable(gui->account, E_ACCOUNT_SOURCE_AUTO_CHECK_TIME)); +} + +static void +save_service (MailAccountGuiService *gsvc, GHashTable *extra_config, EAccountService *service) +{ + CamelURL *url; + const char *str; + + if (!gsvc->provider) { + g_free (service->url); + service->url = NULL; + return; + } + + url = g_new0 (CamelURL, 1); + url->protocol = g_strdup (gsvc->provider->protocol); + + if (CAMEL_PROVIDER_ALLOWS (gsvc->provider, CAMEL_URL_PART_USER)) { + str = gtk_entry_get_text (gsvc->username); + if (str && *str) + url->user = g_strstrip (g_strdup (str)); + } + + if (CAMEL_PROVIDER_ALLOWS (gsvc->provider, CAMEL_URL_PART_AUTH) && url->user) { + if (gsvc->needs_auth == NULL || gtk_toggle_button_get_active(gsvc->needs_auth)) { + CamelServiceAuthType *authtype; + + authtype = g_object_get_data(G_OBJECT(gsvc->authitem), "authtype"); + if (authtype && authtype->authproto && *authtype->authproto) + url->authmech = g_strdup (authtype->authproto); + } + + if (gsvc->remember) + service->save_passwd = gtk_toggle_button_get_active (gsvc->remember); + } + + if (CAMEL_PROVIDER_ALLOWS (gsvc->provider, CAMEL_URL_PART_HOST)) { + char *pport; + + str = gtk_entry_get_text (gsvc->hostname); + if (str && *str) { + pport = strchr (str, ':'); + if (pport) { + url->host = g_strndup (str, pport - str); + url->port = atoi (pport + 1); + } else + url->host = g_strdup (str); + } + } + + if (CAMEL_PROVIDER_ALLOWS (gsvc->provider, CAMEL_URL_PART_PATH)) { + str = gtk_entry_get_text (gsvc->path); + if (str && *str) + url->path = g_strdup (str); + } + + if (gsvc->provider->flags & CAMEL_PROVIDER_SUPPORTS_SSL) { + const char *use_ssl; + + use_ssl = g_object_get_data(G_OBJECT(gsvc->ssl_selected), "use_ssl"); + + /* set the value to either "always" or "when-possible" + but don't bother setting it for "never" */ + if (strcmp (use_ssl, "never")) + camel_url_set_param (url, "use_ssl", use_ssl); + } + + if (extra_config) + extract_values (gsvc, extra_config, url); + + g_free (service->url); + service->url = camel_url_to_string (url, 0); + + /* Temporary until keep_on_server moves into the POP provider */ + if (camel_url_get_param (url, "keep_on_server")) + service->keep_on_server = TRUE; + + camel_url_free (url); +} + +static void +add_new_store (char *uri, CamelStore *store, void *user_data) +{ + MailComponent *component = mail_component_peek (); + EAccount *account = user_data; + + if (store == NULL) + return; + + mail_component_add_store (component, store, account->name); +} + +gboolean +mail_account_gui_save (MailAccountGui *gui) +{ + EAccount *account, *new; + CamelProvider *provider = NULL; + gboolean is_new = FALSE; + const char *new_name; + gboolean is_storage; + + if (!mail_account_gui_identity_complete (gui, NULL) || + !mail_account_gui_source_complete (gui, NULL) || + !mail_account_gui_transport_complete (gui, NULL) || + !mail_account_gui_management_complete (gui, NULL)) + return FALSE; + + new = gui->account; + + /* this would happen at an inconvenient time in the druid, + * but the druid performs its own check so this can't happen + * here. */ + + new_name = gtk_entry_get_text (gui->account_name); + account = mail_config_get_account_by_name (new_name); + + if (account && account != new) { + e_error_run((GtkWindow *)gtk_widget_get_toplevel((GtkWidget *)gui->account_name), + "mail:account-notunique", NULL); + return FALSE; + } + + account = new; + + new = e_account_new (); + new->name = g_strdup (new_name); + new->enabled = account->enabled; + + /* construct the identity */ + new->id->name = g_strdup (gtk_entry_get_text (gui->full_name)); + new->id->address = g_strdup (gtk_entry_get_text (gui->email_address)); + new->id->reply_to = g_strdup (gtk_entry_get_text (gui->reply_to)); + new->id->organization = g_strdup (gtk_entry_get_text (gui->organization)); + + /* signatures */ + new->id->sig_uid = g_strdup (gui->sig_uid); + + /* source */ + save_service (&gui->source, gui->extra_config, new->source); + if (new->source->url) + provider = camel_provider_get(new->source->url, NULL); + + new->source->auto_check = gtk_toggle_button_get_active (gui->source_auto_check); + if (new->source->auto_check) + new->source->auto_check_time = gtk_spin_button_get_value_as_int (gui->source_auto_check_min); + + /* transport */ + if (CAMEL_PROVIDER_IS_STORE_AND_TRANSPORT (gui->transport.provider)) { + /* The transport URI is the same as the source URI. */ + save_service (&gui->source, gui->extra_config, new->transport); + } else + save_service (&gui->transport, NULL, new->transport); + + /* Check to make sure that the Drafts folder uri is "valid" before assigning it */ + if (gui->drafts_folder_uri != NULL + && (mail_config_get_account_by_source_url (gui->drafts_folder_uri) || + !strncmp (gui->drafts_folder_uri, "mbox:", 5))) { + new->drafts_folder_uri = em_uri_from_camel (gui->drafts_folder_uri); + } else { + /* assign defaults - the uri is unknown to us (probably pointed to an old source url) */ + new->drafts_folder_uri = em_uri_from_camel(mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_DRAFTS)); + } + + /* Check to make sure that the Sent folder uri is "valid" before assigning it */ + if (gui->sent_folder_uri != NULL + && (mail_config_get_account_by_source_url (gui->sent_folder_uri) || + !strncmp (gui->sent_folder_uri, "mbox:", 5))) { + new->sent_folder_uri = em_uri_from_camel (gui->sent_folder_uri); + } else { + /* assign defaults - the uri is unknown to us (probably pointed to an old source url) */ + new->sent_folder_uri = em_uri_from_camel(mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_SENT)); + } + + new->always_cc = gtk_toggle_button_get_active (gui->always_cc); + new->cc_addrs = g_strdup (gtk_entry_get_text (gui->cc_addrs)); + new->always_bcc = gtk_toggle_button_get_active (gui->always_bcc); + new->bcc_addrs = g_strdup (gtk_entry_get_text (gui->bcc_addrs)); + + new->pgp_key = g_strdup (gtk_entry_get_text (gui->pgp_key)); + new->pgp_encrypt_to_self = gtk_toggle_button_get_active (gui->pgp_encrypt_to_self); + new->pgp_always_sign = gtk_toggle_button_get_active (gui->pgp_always_sign); + new->pgp_no_imip_sign = gtk_toggle_button_get_active (gui->pgp_no_imip_sign); + new->pgp_always_trust = gtk_toggle_button_get_active (gui->pgp_always_trust); + +#if defined (HAVE_NSS) + new->smime_sign_default = gtk_toggle_button_get_active (gui->smime_sign_default); + new->smime_sign_key = g_strdup (gtk_entry_get_text (gui->smime_sign_key)); + + new->smime_encrypt_default = gtk_toggle_button_get_active (gui->smime_encrypt_default); + new->smime_encrypt_key = g_strdup (gtk_entry_get_text (gui->smime_encrypt_key)); + new->smime_encrypt_to_self = gtk_toggle_button_get_active (gui->smime_encrypt_to_self); +#endif /* HAVE_NSS */ + + is_storage = provider && (provider->flags & CAMEL_PROVIDER_IS_STORAGE); + + if (!mail_config_find_account (account)) { + /* this is a new account so add it to our account-list */ + is_new = TRUE; + } + + /* update the old account with the new settings */ + e_account_import (account, new); + g_object_unref (new); + + if (is_new) { + mail_config_add_account (account); + + /* if the account provider is something we can stick + in the folder-tree and not added by some other + component, then get the CamelStore and add it to + the folder-tree */ + if (is_storage && account->enabled) + mail_get_store (account->source->url, NULL, add_new_store, account); + } else { + e_account_list_change (mail_config_get_accounts (), account); + } + + if (gtk_toggle_button_get_active (gui->default_account)) + mail_config_set_default_account (account); + + mail_config_save_accounts (); + + mail_autoreceive_setup (); + + return TRUE; +} + +void +mail_account_gui_destroy (MailAccountGui *gui) +{ + ESignatureList *signatures; + + g_object_unref (gui->xml); + g_object_unref (gui->account); + + signatures = mail_config_get_signatures (); + g_signal_handler_disconnect (signatures, gui->sig_added_id); + g_signal_handler_disconnect (signatures, gui->sig_removed_id); + g_signal_handler_disconnect (signatures, gui->sig_changed_id); + + if (gui->extra_config) + g_hash_table_destroy (gui->extra_config); + + g_free (gui->drafts_folder_uri); + g_free (gui->sent_folder_uri); + g_free (gui); +} diff --git a/mail/mail-account-gui.h b/mail/mail-account-gui.h new file mode 100644 index 0000000000..8044041b5e --- /dev/null +++ b/mail/mail-account-gui.h @@ -0,0 +1,146 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: + * Jeffrey Stedfast <fejj@ximian.com> + * Dan Winship <danw@ximian.com> + * + * Copyright 2001-2003 Ximian, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef MAIL_ACCOUNT_GUI_H +#define MAIL_ACCOUNT_GUI_H + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#include <camel/camel-provider.h> + +struct _EAccount; +struct _EMAccountPrefs; + +typedef struct _MailAccountGuiService { + struct _GtkWidget *container; + + struct _GtkOptionMenu *type; + struct _GtkLabel *description; + struct _GtkEntry *hostname; + struct _GtkEntry *username; + struct _GtkEntry *path; + struct _GtkWidget *ssl_frame; + struct _GtkOptionMenu *use_ssl; + struct _GtkWidget *ssl_selected; + struct _GtkWidget *ssl_hbox; + struct _GtkWidget *no_ssl; + struct _GtkOptionMenu *authtype; + struct _GtkWidget *authitem; + struct _GtkToggleButton *remember; + struct _GtkButton *check_supported; + + struct _GtkToggleButton *needs_auth; + + CamelProvider *provider; + CamelProviderType provider_type; +} MailAccountGuiService; + +typedef struct _MailAccountGui { + struct _EAccount *account; + struct _EMAccountPrefs *dialog; + struct _GladeXML *xml; + + /* identity */ + struct _GtkEntry *full_name; + struct _GtkEntry *email_address; + struct _GtkEntry *reply_to; + struct _GtkEntry *organization; + + /* signatures */ + struct _GtkOptionMenu *sig_menu; + guint sig_added_id; + guint sig_removed_id; + guint sig_changed_id; + const char *sig_uid; + + /* incoming mail */ + MailAccountGuiService source; + struct _GtkToggleButton *source_auto_check; + struct _GtkSpinButton *source_auto_check_min; + + /* extra incoming config */ + GHashTable *extra_config; + + /* outgoing mail */ + MailAccountGuiService transport; + + /* account management */ + struct _GtkEntry *account_name; + struct _GtkToggleButton *default_account; + + /* special folders */ + struct _GtkButton *drafts_folder_button; + char *drafts_folder_uri; + struct _GtkButton *sent_folder_button; + char *sent_folder_uri; + struct _GtkButton *restore_folders_button; + + /* always cc/bcc */ + struct _GtkToggleButton *always_cc; + struct _GtkEntry *cc_addrs; + struct _GtkToggleButton *always_bcc; + struct _GtkEntry *bcc_addrs; + + /* Security */ + struct _GtkEntry *pgp_key; + struct _GtkToggleButton *pgp_encrypt_to_self; + struct _GtkToggleButton *pgp_always_sign; + struct _GtkToggleButton *pgp_no_imip_sign; + struct _GtkToggleButton *pgp_always_trust; + + struct _GtkToggleButton *smime_sign_default; + struct _GtkEntry *smime_sign_key; + struct _GtkButton *smime_sign_key_select; + struct _GtkButton *smime_sign_key_clear; + struct _GtkButton *smime_sign_select; + struct _GtkToggleButton *smime_encrypt_default; + struct _GtkToggleButton *smime_encrypt_to_self; + struct _GtkEntry *smime_encrypt_key; + struct _GtkButton *smime_encrypt_key_select; + struct _GtkButton *smime_encrypt_key_clear; +} MailAccountGui; + + +MailAccountGui *mail_account_gui_new (struct _EAccount *account, struct _EMAccountPrefs *dialog); +void mail_account_gui_setup (MailAccountGui *gui, struct _GtkWidget *top); +gboolean mail_account_gui_save (MailAccountGui *gui); +void mail_account_gui_destroy (MailAccountGui *gui); + +gboolean mail_account_gui_identity_complete (MailAccountGui *gui, struct _GtkWidget **incomplete); +gboolean mail_account_gui_source_complete (MailAccountGui *gui, struct _GtkWidget **incomplete); +gboolean mail_account_gui_transport_complete (MailAccountGui *gui, struct _GtkWidget **incomplete); +gboolean mail_account_gui_management_complete (MailAccountGui *gui, struct _GtkWidget **incomplete); + +void mail_account_gui_build_extra_conf (MailAccountGui *gui, const char *url); + +void mail_account_gui_auto_detect_extra_conf (MailAccountGui *gui); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* MAIL_ACCOUNT_GUI_H */ diff --git a/mail/mail-component.c b/mail/mail-component.c index e51a30268c..8b71bf47e7 100644 --- a/mail/mail-component.c +++ b/mail/mail-component.c @@ -35,6 +35,7 @@ #include <fcntl.h> #include <errno.h> +#include "em-popup.h" #include "em-utils.h" #include "em-composer-utils.h" #include "em-format.h" @@ -74,7 +75,6 @@ #include <gal/e-table/e-tree.h> #include <gal/e-table/e-tree-memory.h> -#include <libgnome/gnome-i18n.h> #include <camel/camel-file-utils.h> #include <camel/camel-vtrash-folder.h> @@ -98,10 +98,6 @@ struct _store_info { /* 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; }; struct _MailComponentPrivate { @@ -176,21 +172,6 @@ store_info_free(struct _store_info *si) g_free(si); } -static void -mc_add_store_done(CamelStore *store, CamelFolderInfo *info, void *data) -{ - struct _store_info *si = data; - - if (si->done) - si->done(store, info, si); - - /* 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); -} - /* Utility functions. */ static void mc_add_store(MailComponent *component, CamelStore *store, const char *name, void (*done)(CamelStore *store, CamelFolderInfo *info, void *data)) @@ -200,10 +181,9 @@ mc_add_store(MailComponent *component, CamelStore *store, const char *name, void 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); - mail_note_store(store, NULL, mc_add_store_done, si); + mail_note_store(store, NULL, done, component); } static void @@ -654,8 +634,6 @@ impl_quit(PortableServer_Servant servant, CORBA_Environment *ev) int now = time(NULL)/60/60/24, days; GConfClient *gconf = mail_config_get_gconf_client(); - mail_vfolder_shutdown(); - mc->priv->quit_expunge = gconf_client_get_bool(gconf, "/apps/evolution/mail/trash/empty_on_exit", NULL) && ((days = gconf_client_get_int(gconf, "/apps/evolution/mail/trash/empty_on_exit_days", NULL)) == 0 || (days + gconf_client_get_int(gconf, "/apps/evolution/mail/trash/empty_date", NULL)) <= now); @@ -700,7 +678,7 @@ impl__get_userCreatableItems (PortableServer_Servant servant, CORBA_Environment list->_buffer[1].menuDescription = _("Mail _Folder"); list->_buffer[1].tooltip = _("Create a new mail folder"); list->_buffer[1].menuShortcut = 'f'; - list->_buffer[1].iconName = "stock_new-dir"; + list->_buffer[1].iconName = "stock_folder"; list->_buffer[1].type = GNOME_Evolution_CREATABLE_FOLDER; return list; @@ -775,28 +753,13 @@ handleuri_got_folder(char *uri, CamelFolder *folder, void *data) EMMessageBrowser *emmb; if (folder != NULL) { - const char *reply = camel_url_get_param(url, "reply"); - - if (reply) { - int mode; - - 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 { - 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); - } + 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); } @@ -900,7 +863,7 @@ mail_component_init (MailComponent *component) priv->async_event = mail_async_event_new(); priv->store_hash = g_hash_table_new (NULL, NULL); - mail_autoreceive_init(); + mail_autoreceive_setup(); offline = mail_offline_handler_new(); bonobo_object_add_interface((BonoboObject *)component, (BonoboObject *)offline); diff --git a/mail/mail-config-druid.c b/mail/mail-config-druid.c new file mode 100644 index 0000000000..9cc3283042 --- /dev/null +++ b/mail/mail-config-druid.c @@ -0,0 +1,767 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: + * Jeffrey Stedfast <fejj@ximian.com> + * Dan Winship <danw@ximian.com> + * Iain Holmes <iain@ximian.com> + * + * Copyright 2001 Ximian, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <sys/types.h> +#include <sys/utsname.h> +#include <string.h> +#include <unistd.h> + +#include <gal/util/e-util.h> +#include <glade/glade.h> +#include <gtkhtml/gtkhtml.h> +#include <libgnomeui/gnome-dialog.h> +#include <libgnomeui/gnome-dialog-util.h> +#include <libgnomeui/gnome-druid.h> +#include <libgnomeui/gnome-druid-page-standard.h> +#include <bonobo/bonobo-exception.h> + +#include "mail-config-druid.h" +#include "mail-config.h" +#include "mail-ops.h" +#include "mail-session.h" +#include "mail-account-gui.h" + +#include <evolution-wizard.h> +#include <e-util/e-account.h> +#include <e-util/e-icon-factory.h> + +typedef enum { + MAIL_CONFIG_WIZARD_PAGE_NONE = -1, + MAIL_CONFIG_WIZARD_PAGE_IDENTITY, + MAIL_CONFIG_WIZARD_PAGE_SOURCE, + MAIL_CONFIG_WIZARD_PAGE_EXTRA, + MAIL_CONFIG_WIZARD_PAGE_TRANSPORT, + MAIL_CONFIG_WIZARD_PAGE_MANAGEMENT, + + MAIL_CONFIG_WIZARD_NUM_PAGES +} MailConfigWizardPage; + +typedef struct { + /* Only one of these will be set */ + GnomeDruid *druid; + EvolutionWizard *corba_wizard; + + MailAccountGui *gui; + + GPtrArray *interior_pages; + GnomeDruidPage *last_page; + + gboolean identity_copied; + CamelProvider *last_source; + MailConfigWizardPage page; +} MailConfigWizard; + +static void +config_wizard_set_buttons_sensitive (MailConfigWizard *mcw, + gboolean prev_sensitive, + gboolean next_sensitive) +{ + if (mcw->corba_wizard) { + evolution_wizard_set_buttons_sensitive (mcw->corba_wizard, + prev_sensitive, + next_sensitive, + TRUE, NULL); + } else { + gnome_druid_set_buttons_sensitive (mcw->druid, + prev_sensitive, + next_sensitive, + TRUE, FALSE); + } +} + +static void +config_wizard_set_page (MailConfigWizard *mcw, MailConfigWizardPage page) +{ + if (mcw->corba_wizard) + evolution_wizard_set_page (mcw->corba_wizard, page, NULL); + else { + if (page < mcw->interior_pages->len) + gnome_druid_set_page (mcw->druid, mcw->interior_pages->pdata[page]); + else + gnome_druid_set_page (mcw->druid, mcw->last_page); + } +} + +/* Identity Page */ +static void +identity_changed (GtkWidget *widget, gpointer data) +{ + MailConfigWizard *mcw = data; + GtkWidget *incomplete; + gboolean next_sensitive; + + if (mcw->page != MAIL_CONFIG_WIZARD_PAGE_IDENTITY) + return; + + next_sensitive = mail_account_gui_identity_complete (mcw->gui, &incomplete); + + config_wizard_set_buttons_sensitive (mcw, TRUE, next_sensitive); +} + +static void +identity_prepare (MailConfigWizard *mcw) +{ + mcw->page = MAIL_CONFIG_WIZARD_PAGE_IDENTITY; + + if (!gtk_entry_get_text (mcw->gui->full_name)) { + char *uname; + + uname = g_locale_to_utf8 (g_get_real_name (), -1, NULL, NULL, NULL); + gtk_entry_set_text (mcw->gui->full_name, uname ? uname : ""); + g_free (uname); + } + identity_changed (NULL, mcw); +} + +static gboolean +identity_next (MailConfigWizard *mcw) +{ + if (!mcw->identity_copied) { + char *username; + const char *user; + + /* Copy the username part of the email address into + * the Username field of the source and transport pages. + */ + user = gtk_entry_get_text (mcw->gui->email_address); + username = g_strndup (user, strcspn (user, "@")); + gtk_entry_set_text (mcw->gui->source.username, username); + gtk_entry_set_text (mcw->gui->transport.username, username); + g_free (username); + + mcw->identity_copied = TRUE; + } + + return FALSE; +} + +static void +identity_activate_cb (GtkEntry *ent, gpointer user_data) +{ + MailConfigWizard *mcw = user_data; + + if (mail_account_gui_identity_complete (mcw->gui, NULL) && + !identity_next (mcw)) + config_wizard_set_page (mcw, MAIL_CONFIG_WIZARD_PAGE_SOURCE); +} + +/* Incoming mail Page */ +static void +source_changed (GtkWidget *widget, gpointer data) +{ + MailConfigWizard *mcw = data; + GtkWidget *incomplete; + gboolean next_sensitive; + + if (mcw->page != MAIL_CONFIG_WIZARD_PAGE_SOURCE) + return; + + next_sensitive = mail_account_gui_source_complete (mcw->gui, &incomplete); + + config_wizard_set_buttons_sensitive (mcw, TRUE, next_sensitive); +} + +static void +source_prepare (MailConfigWizard *mcw) +{ + mcw->page = MAIL_CONFIG_WIZARD_PAGE_SOURCE; + source_changed (NULL, mcw); +} + +static gboolean +source_next (MailConfigWizard *mcw) +{ + /* FIXME: if online, check that the data is good. */ + + if (mcw->gui->source.provider && mcw->gui->source.provider->extra_conf) + return FALSE; + + /* Otherwise, skip to transport page. */ + config_wizard_set_page (mcw, MAIL_CONFIG_WIZARD_PAGE_TRANSPORT); + return TRUE; +} + +static void +source_activate_cb (GtkEntry *ent, gpointer user_data) +{ + MailConfigWizard *mcw = user_data; + + if (mail_account_gui_source_complete (mcw->gui, NULL) && + !source_next (mcw)) + config_wizard_set_page (mcw, MAIL_CONFIG_WIZARD_PAGE_EXTRA); +} + +/* Extra Config Page */ +static void +extra_prepare (MailConfigWizard *mcw) +{ + mcw->page = MAIL_CONFIG_WIZARD_PAGE_EXTRA; + if (mcw->gui->source.provider != mcw->last_source) { + mcw->last_source = mcw->gui->source.provider; + mail_account_gui_auto_detect_extra_conf (mcw->gui); + } +} + +/* Transport Page */ +static gboolean +transport_next (MailConfigWizard *mcw) +{ + /* FIXME: if online, check that the data is good. */ + return FALSE; +} + +static gboolean +transport_back (MailConfigWizard *mcw) +{ + if (mcw->gui->source.provider && mcw->gui->source.provider->extra_conf) + return FALSE; + else { + config_wizard_set_page (mcw, MAIL_CONFIG_WIZARD_PAGE_SOURCE); + return TRUE; + } +} + +static void +transport_changed (GtkWidget *widget, gpointer data) +{ + MailConfigWizard *mcw = data; + GtkWidget *incomplete; + gboolean next_sensitive; + + if (mcw->page != MAIL_CONFIG_WIZARD_PAGE_TRANSPORT) + return; + + next_sensitive = mail_account_gui_transport_complete (mcw->gui, &incomplete); + + config_wizard_set_buttons_sensitive (mcw, TRUE, next_sensitive); +} + +static void +transport_prepare (MailConfigWizard *mcw) +{ + mcw->page = MAIL_CONFIG_WIZARD_PAGE_TRANSPORT; + transport_changed (NULL, mcw); +} + +static void +transport_activate_cb (GtkEntry *ent, gpointer user_data) +{ + MailConfigWizard *mcw = user_data; + + if (mail_account_gui_transport_complete (mcw->gui, NULL) && + !transport_next (mcw)) + config_wizard_set_page (mcw, MAIL_CONFIG_WIZARD_PAGE_MANAGEMENT); +} + +/* Management page */ +static gboolean +management_check (MailConfigWizard *mcw) +{ + gboolean next_sensitive; + const char *text; + + text = gtk_entry_get_text (mcw->gui->account_name); + next_sensitive = text && *text; + + /* no accounts with the same name */ + if (next_sensitive && mail_config_get_account_by_name (text)) + next_sensitive = FALSE; + + config_wizard_set_buttons_sensitive (mcw, TRUE, next_sensitive); + return next_sensitive; +} + +static void +management_prepare (MailConfigWizard *mcw) +{ + const char *name, *text; + + mcw->page = MAIL_CONFIG_WIZARD_PAGE_MANAGEMENT; + + text = gtk_entry_get_text (mcw->gui->account_name); + if (!text || *text == '\0') { + name = gtk_entry_get_text(mcw->gui->email_address); + if (name && *name) { + if (mail_config_get_account_by_name (name)) { + char *template; + unsigned int i = 1, len; + + /* length of name + 1 char for ' ' + 1 char + for '(' + 10 chars for %d + 1 char for ')' + + 1 char for nul */ + len = strlen (name); + template = alloca (len + 14); + strcpy (template, name); + name = template; + do { + sprintf (template + len, " (%d)", i++); + } while (mail_config_get_account_by_name (name) && i != 0); + } + + gtk_entry_set_text(mcw->gui->account_name, name); + } + } + + management_check (mcw); +} + +static void +management_changed (GtkWidget *widget, gpointer data) +{ + MailConfigWizard *mcw = data; + + if (mcw->page != MAIL_CONFIG_WIZARD_PAGE_MANAGEMENT) + return; + + management_check (mcw); +} + +static void +management_activate_cb (GtkEntry *ent, gpointer user_data) +{ + MailConfigWizard *mcw = user_data; + + if (management_check (mcw)) + config_wizard_set_page (mcw, mcw->page + 1); +} + +static struct { + const char *page_name, *title, *icon_name; + void (*prepare_func) (MailConfigWizard *mcw); + gboolean (*back_func) (MailConfigWizard *mcw); + gboolean (*next_func) (MailConfigWizard *mcw); + const char *help_text; +} wizard_pages[] = { + { "identity_page", N_("Identity"), "stock_contact", + identity_prepare, NULL, identity_next, + N_("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.") + }, + + { "source_page", N_("Receiving Mail"), "stock_mail-receive", + source_prepare, NULL, source_next, + N_("Please enter information about your incoming " + "mail server below. If you are not sure, ask your " + "system administrator or Internet Service Provider.") + }, + + { "extra_page", N_("Receiving Mail"), "stock_mail-receive", + extra_prepare, NULL, NULL, + N_("Please select among the following options") + }, + + { "transport_page", N_("Sending Mail"), "stock_mail-send", + transport_prepare, transport_back, transport_next, + N_("Please enter information about the way you will " + "send mail. If you are not sure, ask your system " + "administrator or Internet Service Provider.") + }, + + { "management_page", N_("Account Management"), "stock_person", + management_prepare, NULL, NULL, + N_("You are almost done with the mail configuration " + "process. The identity, incoming mail server and " + "outgoing mail transport method which you provided " + "will be grouped together to make an Evolution mail " + "account. Please enter a name for this account in " + "the space below. This name will be used for display " + "purposes only.") + } +}; +static const int num_wizard_pages = sizeof (wizard_pages) / sizeof (wizard_pages[0]); + +static GtkWidget * +get_page (GladeXML *xml, int page_num) +{ + GtkWidget *vbox, *widget; + + vbox = gtk_vbox_new (FALSE, 4); + + widget = gtk_label_new (_(wizard_pages[page_num].help_text)); + gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE); + gtk_label_set_justify (GTK_LABEL (widget), GTK_JUSTIFY_FILL); + gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0); + gtk_widget_show_all (vbox); + + switch (page_num) { + case MAIL_CONFIG_WIZARD_PAGE_IDENTITY: + widget = glade_xml_get_widget (xml, "identity_required_frame"); + gtk_container_set_border_width (GTK_CONTAINER (widget), 0); + gtk_widget_reparent (widget, vbox); + gtk_box_set_child_packing (GTK_BOX (vbox), widget, FALSE, FALSE, 0, GTK_PACK_START); + widget = glade_xml_get_widget (xml, "identity_optional_frame"); + gtk_container_set_border_width (GTK_CONTAINER (widget), 0); + gtk_widget_reparent (widget, vbox); + gtk_box_set_child_packing (GTK_BOX (vbox), widget, FALSE, FALSE, 0, GTK_PACK_START); + break; + + case MAIL_CONFIG_WIZARD_PAGE_SOURCE: + widget = glade_xml_get_widget (xml, "source_vbox"); + gtk_container_set_border_width (GTK_CONTAINER (widget), 0); + gtk_widget_reparent (widget, vbox); + break; + + case MAIL_CONFIG_WIZARD_PAGE_EXTRA: + widget = glade_xml_get_widget (xml, "extra_table"); + gtk_container_set_border_width (GTK_CONTAINER (widget), 0); + gtk_widget_reparent (widget, vbox); + break; + + case MAIL_CONFIG_WIZARD_PAGE_TRANSPORT: + widget = glade_xml_get_widget (xml, "transport_vbox"); + gtk_container_set_border_width (GTK_CONTAINER (widget), 0); + gtk_widget_reparent (widget, vbox); + break; + + case MAIL_CONFIG_WIZARD_PAGE_MANAGEMENT: + widget = glade_xml_get_widget (xml, "management_frame"); + gtk_container_set_border_width (GTK_CONTAINER (widget), 0); + gtk_widget_reparent (widget, vbox); + break; + + default: + g_return_val_if_reached (NULL); + } + + return vbox; +} + + +static MailConfigWizard * +config_wizard_new (void) +{ + MailConfigWizard *mcw; + const char *user; + EAccountService *xport; + struct utsname uts; + EAccount *account; + + /* Create a new account object with some defaults */ + account = e_account_new (); + account->enabled = TRUE; + + account->id->name = g_locale_to_utf8 (g_get_real_name (), -1, NULL, NULL, NULL); + user = g_get_user_name (); + if (user && !uname (&uts) && strchr (uts.nodename, '.')) + account->id->address = g_strdup_printf ("%s@%s", user, uts.nodename); + + if ((xport = mail_config_get_default_transport ())) { + account->transport->url = g_strdup (xport->url); + account->transport->save_passwd = xport->save_passwd; + } + + /* Create the config wizard object */ + mcw = g_new0 (MailConfigWizard, 1); + mcw->gui = mail_account_gui_new (account, NULL); + g_object_unref (account); + + /* Set up gui */ + g_signal_connect (mcw->gui->account_name, "changed", + G_CALLBACK (management_changed), mcw); + g_signal_connect (mcw->gui->full_name, "changed", + G_CALLBACK (identity_changed), mcw); + g_signal_connect (mcw->gui->email_address, "changed", + G_CALLBACK (identity_changed), mcw); + g_signal_connect (mcw->gui->reply_to,"changed", + G_CALLBACK (identity_changed), mcw); + g_signal_connect (mcw->gui->source.hostname, "changed", + G_CALLBACK (source_changed), mcw); + g_signal_connect (mcw->gui->source.username, "changed", + G_CALLBACK (source_changed), mcw); + g_signal_connect (mcw->gui->source.path, "changed", + G_CALLBACK (source_changed), mcw); + g_signal_connect (mcw->gui->transport.hostname, "changed", + G_CALLBACK (transport_changed), mcw); + g_signal_connect (mcw->gui->transport.username, "changed", + G_CALLBACK (transport_changed), mcw); + g_signal_connect (mcw->gui->transport.needs_auth, "toggled", + G_CALLBACK (transport_changed), mcw); + + g_signal_connect (mcw->gui->account_name, "activate", + G_CALLBACK (management_activate_cb), mcw); + + g_signal_connect (mcw->gui->full_name, "activate", + G_CALLBACK (identity_activate_cb), mcw); + g_signal_connect (mcw->gui->email_address, "activate", + G_CALLBACK (identity_activate_cb), mcw); + g_signal_connect (mcw->gui->reply_to,"activate", + G_CALLBACK (identity_activate_cb), mcw); + g_signal_connect (mcw->gui->organization, "activate", + G_CALLBACK (identity_activate_cb), mcw); + + g_signal_connect (mcw->gui->source.hostname, "activate", + G_CALLBACK (source_activate_cb), mcw); + g_signal_connect (mcw->gui->source.username, "activate", + G_CALLBACK (source_activate_cb), mcw); + g_signal_connect (mcw->gui->source.path, "activate", + G_CALLBACK (source_activate_cb), mcw); + + g_signal_connect (mcw->gui->transport.hostname, "activate", + G_CALLBACK (transport_activate_cb), mcw); + g_signal_connect (mcw->gui->transport.username, "activate", + G_CALLBACK (transport_activate_cb), mcw); + + return mcw; +} + +static void +free_config_wizard (MailConfigWizard *mcw) +{ + mail_account_gui_destroy (mcw->gui); + + if (mcw->interior_pages) + g_ptr_array_free (mcw->interior_pages, TRUE); + + g_free (mcw); +} + +/* In-proc config druid */ + +static void +druid_cancel (GnomeDruid *druid, gpointer user_data) +{ + MailConfigWizard *mcw = user_data; + GtkWidget *window; + + window = glade_xml_get_widget (mcw->gui->xml, "account_druid"); + gtk_widget_destroy (window); + + free_config_wizard (mcw); +} + +static void +druid_finish (GnomeDruidPage *page, GnomeDruid *druid, gpointer user_data) +{ + MailConfigWizard *mcw = user_data; + + mail_account_gui_save (mcw->gui); + druid_cancel (druid, user_data); +} + +static void +druid_prepare (GnomeDruidPage *page, GnomeDruid *druid, gpointer data) +{ + MailConfigWizard *mcw = g_object_get_data (G_OBJECT (druid), "MailConfigWizard"); + int page_num = GPOINTER_TO_INT (data); + + if (wizard_pages[page_num].prepare_func) + wizard_pages[page_num].prepare_func (mcw); +} + +static gboolean +druid_back (GnomeDruidPage *page, GnomeDruid *druid, gpointer data) +{ + MailConfigWizard *mcw = g_object_get_data (G_OBJECT (druid), "MailConfigWizard"); + int page_num = GPOINTER_TO_INT (data); + + if (wizard_pages[page_num].back_func) + return wizard_pages[page_num].back_func (mcw); + else + return FALSE; +} + +static gboolean +druid_next (GnomeDruidPage *page, GnomeDruid *druid, gpointer data) +{ + MailConfigWizard *mcw = g_object_get_data (G_OBJECT (druid), "MailConfigWizard"); + int page_num = GPOINTER_TO_INT (data); + + if (wizard_pages[page_num].next_func) + return wizard_pages[page_num].next_func (mcw); + else + return FALSE; +} + + +MailConfigDruid * +mail_config_druid_new (void) +{ + MailConfigWizard *mcw; + GtkWidget *new, *page; + GdkPixbuf *icon; + int i; + + mcw = config_wizard_new (); + mcw->druid = (GnomeDruid *)glade_xml_get_widget (mcw->gui->xml, "druid"); + g_object_set_data (G_OBJECT (mcw->druid), "MailConfigWizard", mcw); + gtk_widget_show_all (GTK_WIDGET (mcw->druid)); + + mcw->interior_pages = g_ptr_array_new (); + for (i = 0; i < num_wizard_pages; i++) { + page = glade_xml_get_widget (mcw->gui->xml, + wizard_pages[i].page_name); + icon = e_icon_factory_get_icon (wizard_pages[i].icon_name, E_ICON_SIZE_DIALOG); + gnome_druid_page_standard_set_logo (GNOME_DRUID_PAGE_STANDARD (page), icon); + g_object_unref (icon); + g_ptr_array_add (mcw->interior_pages, page); + gtk_box_pack_start (GTK_BOX (GNOME_DRUID_PAGE_STANDARD (page)->vbox), + get_page (mcw->gui->xml, i), + FALSE, FALSE, 0); + g_signal_connect (page, "back", G_CALLBACK (druid_back), + GINT_TO_POINTER (i)); + g_signal_connect (page, "next", G_CALLBACK (druid_next), + GINT_TO_POINTER (i)); + + /* At least in 2.0 (and probably 2.2 too), + * GnomeDruidPageStandard is broken and you need to + * connect_after to "prepare" or else its default + * method will run after your signal handler and + * undo its button sensitivity changes. + */ + g_signal_connect_after (page, "prepare", + G_CALLBACK (druid_prepare), + GINT_TO_POINTER (i)); + } + g_signal_connect (mcw->druid, "cancel", G_CALLBACK (druid_cancel), mcw); + + mcw->last_page = (GnomeDruidPage *)glade_xml_get_widget (mcw->gui->xml, "finish_page"); + g_signal_connect (mcw->last_page, "finish", G_CALLBACK (druid_finish), mcw); + + gnome_druid_set_buttons_sensitive (mcw->druid, FALSE, TRUE, TRUE, FALSE); + /*gtk_widget_show_all (GTK_WIDGET (mcw->druid));*/ + mail_account_gui_setup (mcw->gui, NULL); + + new = glade_xml_get_widget (mcw->gui->xml, "account_druid"); + gtk_window_set_type_hint ((GtkWindow *) new, GDK_WINDOW_TYPE_HINT_DIALOG); + + return (MailConfigDruid *) new; +} + + +/* CORBA wizard */ + +static void +wizard_next_cb (EvolutionWizard *wizard, + int page_num, + MailConfigWizard *mcw) +{ + if (page_num >= MAIL_CONFIG_WIZARD_PAGE_MANAGEMENT) + return; + + if (wizard_pages[page_num].next_func && + wizard_pages[page_num].next_func (mcw)) + return; + + evolution_wizard_set_page (wizard, page_num + 1, NULL); +} + +static void +wizard_prepare_cb (EvolutionWizard *wizard, + int page_num, + MailConfigWizard *mcw) +{ + if (wizard_pages[page_num].prepare_func) + wizard_pages[page_num].prepare_func (mcw); +} + +static void +wizard_back_cb (EvolutionWizard *wizard, + int page_num, + MailConfigWizard *mcw) +{ + if (page_num >= MAIL_CONFIG_WIZARD_NUM_PAGES) { + evolution_wizard_set_page (wizard, MAIL_CONFIG_WIZARD_PAGE_MANAGEMENT, NULL); + return; + } + + if (wizard_pages[page_num].back_func && + wizard_pages[page_num].back_func (mcw)) + return; + + if (page_num > 0) + evolution_wizard_set_page (wizard, page_num - 1, NULL); +} + +static void +wizard_finish_cb (EvolutionWizard *wizard, + MailConfigWizard *w) +{ + MailAccountGui *gui = w->gui; + + /* Save the settings for that account */ + if (mail_account_gui_save (gui) == FALSE) + /* problem. Um, how to keep the druid alive? */ + return; + + /* Write out the config info */ + mail_config_write (); + mail_account_gui_destroy (gui); + w->gui = NULL; +} + +static void +wizard_cancel_cb (EvolutionWizard *wizard, + MailConfigWizard *mcw) +{ + mail_account_gui_destroy (mcw->gui); + mcw->gui = NULL; +} + +static void +wizard_help_cb (EvolutionWizard *wizard, + int page_num, + MailConfigWizard *mcw) +{ +} + +BonoboObject * +evolution_mail_config_wizard_new (void) +{ + EvolutionWizard *wizard; + MailConfigWizard *mcw; + GdkPixbuf *icon; + int i; + + mcw = config_wizard_new (); + mail_account_gui_setup (mcw->gui, NULL); + + wizard = evolution_wizard_new (); + for (i = 0; i < MAIL_CONFIG_WIZARD_NUM_PAGES; i++) { + icon = e_icon_factory_get_icon (wizard_pages[i].icon_name, E_ICON_SIZE_DIALOG); + evolution_wizard_add_page (wizard, _(wizard_pages[i].title), + icon, get_page (mcw->gui->xml, i)); + g_object_unref (icon); + } + + g_object_set_data_full (G_OBJECT (wizard), "MailConfigWizard", + mcw, (GDestroyNotify)free_config_wizard); + mcw->corba_wizard = wizard; + + g_signal_connect (wizard, "next", G_CALLBACK (wizard_next_cb), mcw); + g_signal_connect (wizard, "prepare", G_CALLBACK (wizard_prepare_cb), mcw); + g_signal_connect (wizard, "back", G_CALLBACK (wizard_back_cb), mcw); + g_signal_connect (wizard, "finish", G_CALLBACK (wizard_finish_cb), mcw); + g_signal_connect (wizard, "cancel", G_CALLBACK (wizard_cancel_cb), mcw); + g_signal_connect (wizard, "help", G_CALLBACK (wizard_help_cb), mcw); + + return BONOBO_OBJECT (wizard); +} diff --git a/mail/mail-config.c b/mail/mail-config.c index 0d0943b254..c1c8adf02d 100644 --- a/mail/mail-config.c +++ b/mail/mail-config.c @@ -54,6 +54,7 @@ #include <gal/util/e-util.h> #include <gal/widgets/e-gui-utils.h> +#include <e-util/e-url.h> #include <e-util/e-passwords.h> #include <e-util/e-account-list.h> #include <e-util/e-signature-list.h> diff --git a/mail/mail-config.glade b/mail/mail-config.glade index 4df8207e26..2103e332e5 100644 --- a/mail/mail-config.glade +++ b/mail/mail-config.glade @@ -41,31 +41,10 @@ Click "Forward" to begin. </property> <child internal-child="vbox"> <widget class="GtkVBox" id="druid_identity_vbox"> - <property name="border_width">12</property> + <property name="border_width">16</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> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> + <property name="spacing">0</property> <child> <placeholder/> @@ -82,31 +61,30 @@ Click "Forward" to begin. </property> <child internal-child="vbox"> <widget class="GtkVBox" id="druid_source_vbox"> - <property name="border_width">12</property> + <property name="border_width">16</property> <property name="visible">True</property> <property name="homogeneous">False</property> - <property name="spacing">12</property> + <property name="spacing">0</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> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> + <placeholder/> </child> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GnomeDruidPageStandard" id="extra_page"> + <property name="visible">True</property> + <property name="title" translatable="yes">Receiving Email</property> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="druid_extra_vbox"> + <property name="border_width">16</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> <child> <placeholder/> @@ -123,31 +101,10 @@ Click "Forward" to begin. </property> <child internal-child="vbox"> <widget class="GtkVBox" id="druid_transport_vbox"> - <property name="border_width">12</property> + <property name="border_width">16</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> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> + <property name="spacing">0</property> <child> <placeholder/> @@ -164,32 +121,10 @@ Click "Forward" to begin. </property> <child internal-child="vbox"> <widget class="GtkVBox" id="druid_management_vbox"> - <property name="border_width">12</property> + <property name="border_width">16</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. -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> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> + <property name="spacing">0</property> <child> <placeholder/> @@ -376,7 +311,7 @@ For example: "Work" or "Personal"</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="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> <packing> @@ -503,7 +438,7 @@ For example: "Work" or "Personal"</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="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> <packing> @@ -574,7 +509,7 @@ For example: "Work" or "Personal"</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="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> <packing> @@ -691,7 +626,7 @@ For example: "Work" or "Personal"</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="mnemonic_widget">sigOption</property> </widget> <packing> <property name="left_attach">0</property> @@ -710,12 +645,24 @@ For example: "Work" or "Personal"</property> <property name="spacing">6</property> <child> - <widget class="Custom" id="signature_dropdown"> + <widget class="GtkOptionMenu" id="sigOption"> <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> + <property name="can_focus">True</property> + <property name="history">0</property> + + <child internal-child="menu"> + <widget class="GtkMenu" id="convertwidget1"> + <property name="visible">True</property> + + <child> + <widget class="GtkMenuItem" id="convertwidget2"> + <property name="visible">True</property> + <property name="label" translatable="yes">Default</property> + <property name="use_underline">True</property> + </widget> + </child> + </widget> + </child> </widget> <packing> <property name="padding">0</property> @@ -761,7 +708,7 @@ For example: "Work" or "Personal"</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="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> <packing> @@ -807,7 +754,7 @@ For example: "Work" or "Personal"</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="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> <packing> @@ -947,7 +894,7 @@ For example: "Work" or "Personal"</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="mnemonic_widget">source_type_omenu</property> </widget> <packing> <property name="left_attach">0</property> @@ -1008,12 +955,56 @@ For example: "Work" or "Personal"</property> </child> <child> - <widget class="Custom" id="source_type_dropdown"> + <widget class="GtkOptionMenu" id="source_type_omenu"> <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> + <property name="can_focus">True</property> + <property name="history">0</property> + + <child internal-child="menu"> + <widget class="GtkMenu" id="convertwidget3"> + <property name="visible">True</property> + + <child> + <widget class="GtkMenuItem" id="convertwidget4"> + <property name="visible">True</property> + <property name="label" translatable="yes">POP</property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="convertwidget5"> + <property name="visible">True</property> + <property name="label" translatable="yes">IMAPv4 </property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="convertwidget6"> + <property name="visible">True</property> + <property name="label" translatable="yes">Standard Unix mbox</property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="convertwidget7"> + <property name="visible">True</property> + <property name="label" translatable="yes">Qmail maildir </property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="convertwidget8"> + <property name="visible">True</property> + <property name="label" translatable="yes">None</property> + <property name="use_underline">True</property> + </widget> + </child> + </widget> + </child> </widget> <packing> <property name="left_attach">1</property> @@ -1174,7 +1165,7 @@ For example: "Work" or "Personal"</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="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> <packing> @@ -1195,7 +1186,7 @@ For example: "Work" or "Personal"</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="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> <packing> @@ -1240,7 +1231,6 @@ For example: "Work" or "Personal"</property> <property name="directory_entry">False</property> <property name="modal">False</property> <property name="use_filechooser">True</property> - <property name="filechooser_action">GTK_FILE_CHOOSER_ACTION_OPEN</property> <child internal-child="entry"> <widget class="GtkEntry" id="source_path"> @@ -1251,7 +1241,7 @@ For example: "Work" or "Personal"</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="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> </child> @@ -1363,7 +1353,7 @@ For example: "Work" or "Personal"</property> <child> <widget class="GtkLabel" id="lblSourceUseSSL"> <property name="visible">True</property> - <property name="label" translatable="yes">_Use Secure Connection:</property> + <property name="label" translatable="yes">_Use Secure Connection (SSL):</property> <property name="use_underline">True</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_CENTER</property> @@ -1383,12 +1373,40 @@ For example: "Work" or "Personal"</property> </child> <child> - <widget class="Custom" id="source_use_ssl"> + <widget class="GtkOptionMenu" 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> + <property name="can_focus">True</property> + <property name="history">0</property> + + <child internal-child="menu"> + <widget class="GtkMenu" id="convertwidget9"> + <property name="visible">True</property> + + <child> + <widget class="GtkMenuItem" id="convertwidget10"> + <property name="visible">True</property> + <property name="label" translatable="yes">Always</property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="convertwidget11"> + <property name="visible">True</property> + <property name="label" translatable="yes">Whenever Possible</property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="convertwidget12"> + <property name="visible">True</property> + <property name="label" translatable="yes">Never</property> + <property name="use_underline">True</property> + </widget> + </child> + </widget> + </child> </widget> <packing> <property name="padding">0</property> @@ -1430,7 +1448,7 @@ For example: "Work" or "Personal"</property> <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="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> @@ -1543,12 +1561,32 @@ For example: "Work" or "Personal"</property> <property name="spacing">6</property> <child> - <widget class="Custom" id="source_auth_dropdown"> + <widget class="GtkOptionMenu" id="source_auth_omenu"> <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> + <property name="can_focus">True</property> + <property name="history">0</property> + + <child internal-child="menu"> + <widget class="GtkMenu" id="convertwidget13"> + <property name="visible">True</property> + + <child> + <widget class="GtkMenuItem" id="convertwidget14"> + <property name="visible">True</property> + <property name="label" translatable="yes">Password</property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="convertwidget15"> + <property name="visible">True</property> + <property name="label" translatable="yes">Kerberos </property> + <property name="use_underline">True</property> + </widget> + </child> + </widget> + </child> </widget> <packing> <property name="padding">0</property> @@ -1635,9 +1673,229 @@ For example: "Work" or "Personal"</property> </child> <child> + <widget class="GtkLabel" id="label32"> + <property name="visible">True</property> + <property name="label" translatable="yes">Receiving 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> + </widget> + <packing> + <property name="type">tab</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vboxExtraTableBorder"> + <property name="border_width">12</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">12</property> + + <child> + <widget class="GtkTable" id="extra_table"> + <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">18</property> + <property name="column_spacing">6</property> + + <child> + <widget class="GtkVBox" id="extra_mailcheck_frame"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkTable" id="extra_mailcheck_table"> + <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">6</property> + + <child> + <widget class="GtkTable" id="extra_table"> + <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">0</property> + + <child> + <widget class="GtkVBox" id="extra_mailcheck_frame"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="lblMailCheck"> + <property name="visible">True</property> + <property name="label" translatable="yes"><span weight="bold">Checking for New 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> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkTable" id="extra_mailcheck_table"> + <property name="border_width">12</property> + <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">0</property> + <property name="column_spacing">0</property> + + <child> + <widget class="GtkHBox" id="extra_mailcheck_hbox"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">4</property> + + <child> + <widget class="GtkCheckButton" id="extra_auto_check"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Automatically check for _new mail every</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="extra_auto_check_min"> + <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">True</property> + <property name="update_policy">GTK_UPDATE_ALWAYS</property> + <property name="snap_to_ticks">False</property> + <property name="wrap">False</property> + <property name="adjustment">10 1 1440 1 10 10</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="lblMinutes"> + <property name="visible">True</property> + <property name="label" translatable="yes">minutes</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> + </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">2</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="left_attach">0</property> + <property name="right_attach">2</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">2</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="left_attach">0</property> + <property name="right_attach">2</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">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="label" translatable="yes">Receiving Options</property> <property name="use_underline">True</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_CENTER</property> @@ -1688,7 +1946,7 @@ For example: "Work" or "Personal"</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="mnemonic_widget">transport_type_omenu</property> </widget> <packing> <property name="left_attach">0</property> @@ -1724,12 +1982,32 @@ For example: "Work" or "Personal"</property> </child> <child> - <widget class="Custom" id="transport_type_dropdown"> + <widget class="GtkOptionMenu" id="transport_type_omenu"> <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> + <property name="can_focus">True</property> + <property name="history">0</property> + + <child internal-child="menu"> + <widget class="GtkMenu" id="convertwidget16"> + <property name="visible">True</property> + + <child> + <widget class="GtkMenuItem" id="convertwidget17"> + <property name="visible">True</property> + <property name="label" translatable="yes">SMTP</property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="convertwidget18"> + <property name="visible">True</property> + <property name="label" translatable="yes">Sendmail</property> + <property name="use_underline">True</property> + </widget> + </child> + </widget> + </child> </widget> <packing> <property name="left_attach">1</property> @@ -1901,7 +2179,7 @@ For example: "Work" or "Personal"</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="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> <packing> @@ -2037,7 +2315,7 @@ For example: "Work" or "Personal"</property> <child> <widget class="GtkLabel" id="lblTransportUseSSL"> <property name="visible">True</property> - <property name="label" translatable="yes">_Use Secure Connection:</property> + <property name="label" translatable="yes">_Use Secure Connection (SSL):</property> <property name="use_underline">True</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_CENTER</property> @@ -2057,12 +2335,40 @@ For example: "Work" or "Personal"</property> </child> <child> - <widget class="Custom" id="transport_use_ssl"> + <widget class="GtkOptionMenu" 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> + <property name="can_focus">True</property> + <property name="history">0</property> + + <child internal-child="menu"> + <widget class="GtkMenu" id="convertwidget19"> + <property name="visible">True</property> + + <child> + <widget class="GtkMenuItem" id="convertwidget20"> + <property name="visible">True</property> + <property name="label" translatable="yes">Always</property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="convertwidget21"> + <property name="visible">True</property> + <property name="label" translatable="yes">Whenever Possible</property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="convertwidget22"> + <property name="visible">True</property> + <property name="label" translatable="yes">Never</property> + <property name="use_underline">True</property> + </widget> + </child> + </widget> + </child> </widget> <packing> <property name="padding">0</property> @@ -2104,7 +2410,7 @@ For example: "Work" or "Personal"</property> <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="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> @@ -2241,7 +2547,7 @@ For example: "Work" or "Personal"</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="mnemonic_widget">transport_auth_omenu</property> </widget> <packing> <property name="left_attach">0</property> @@ -2287,7 +2593,7 @@ For example: "Work" or "Personal"</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="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> <packing> @@ -2306,12 +2612,32 @@ For example: "Work" or "Personal"</property> <property name="spacing">6</property> <child> - <widget class="Custom" id="transport_auth_dropdown"> + <widget class="GtkOptionMenu" id="transport_auth_omenu"> <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> + <property name="can_focus">True</property> + <property name="history">0</property> + + <child internal-child="menu"> + <widget class="GtkMenu" id="convertwidget23"> + <property name="visible">True</property> + + <child> + <widget class="GtkMenuItem" id="convertwidget24"> + <property name="visible">True</property> + <property name="label" translatable="yes">Password</property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="convertwidget25"> + <property name="visible">True</property> + <property name="label" translatable="yes">Kerberos </property> + <property name="use_underline">True</property> + </widget> + </child> + </widget> + </child> </widget> <packing> <property name="padding">0</property> @@ -2588,10 +2914,10 @@ For example: "Work" or "Personal"</property> <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="creation_function">mail_account_gui_folder_selector_button_new</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> + <property name="last_modification_time">Wed, 03 Apr 2002 23:03:59 GMT</property> </widget> <packing> <property name="left_attach">1</property> @@ -2606,10 +2932,10 @@ For example: "Work" or "Personal"</property> <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="creation_function">mail_account_gui_folder_selector_button_new</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> + <property name="last_modification_time">Wed, 03 Apr 2002 23:03:41 GMT</property> </widget> <packing> <property name="left_attach">1</property> @@ -2872,7 +3198,7 @@ For example: "Work" or "Personal"</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="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> <packing> @@ -2988,7 +3314,7 @@ For example: "Work" or "Personal"</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="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> <packing> @@ -3195,7 +3521,7 @@ For example: "Work" or "Personal"</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="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> <packing> @@ -3216,7 +3542,7 @@ For example: "Work" or "Personal"</property> <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="label" translatable="yes">Always _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> @@ -3235,7 +3561,7 @@ For example: "Work" or "Personal"</property> <widget class="GtkCheckButton" id="pgp_no_imip_sign"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="label" translatable="yes">_Don't sign meeting requests (for Outlook compatibility)</property> + <property name="label" translatable="yes">Don't 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> @@ -3254,7 +3580,7 @@ For example: "Work" or "Personal"</property> <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 mail</property> + <property name="label" translatable="yes">Al_ways encrypt to myself when sending encrypted mail</property> <property name="use_underline">True</property> <property name="relief">GTK_RELIEF_NORMAL</property> <property name="focus_on_click">True</property> @@ -3389,7 +3715,7 @@ For example: "Work" or "Personal"</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="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> <packing> @@ -3410,7 +3736,7 @@ For example: "Work" or "Personal"</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="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> <packing> @@ -3426,7 +3752,7 @@ For example: "Work" or "Personal"</property> <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 mail</property> + <property name="label" translatable="yes">A_lso encrypt to self when sending encrypted mail</property> <property name="use_underline">True</property> <property name="relief">GTK_RELIEF_NORMAL</property> <property name="focus_on_click">True</property> @@ -3448,7 +3774,7 @@ For example: "Work" or "Personal"</property> <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="label" translatable="yes">_Encrypt outgoing messages (by default)</property> <property name="use_underline">True</property> <property name="relief">GTK_RELIEF_NORMAL</property> <property name="focus_on_click">True</property> @@ -3470,7 +3796,7 @@ For example: "Work" or "Personal"</property> <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 outgoing messages (by default)</property> + <property name="label" translatable="yes">_Digitally sign outgoing messages (by default)</property> <property name="use_underline">True</property> <property name="relief">GTK_RELIEF_NORMAL</property> <property name="focus_on_click">True</property> @@ -3531,7 +3857,7 @@ For example: "Work" or "Personal"</property> <child> <widget class="GtkLabel" id="label469"> <property name="visible">True</property> - <property name="label" translatable="yes">Sig_ning certificate:</property> + <property name="label" translatable="yes">Si_gning certificate:</property> <property name="use_underline">True</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> @@ -3604,7 +3930,7 @@ For example: "Work" or "Personal"</property> <child> <widget class="GtkLabel" id="button98"> <property name="visible">True</property> - <property name="label" translatable="yes">Se_lect...</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> @@ -3637,68 +3963,10 @@ For example: "Work" or "Personal"</property> <widget class="GtkButton" id="smime_encrypt_key_clear"> <property name="visible">True</property> <property name="can_focus">True</property> + <property name="label">gtk-clear</property> + <property name="use_stock">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> - </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> @@ -3768,7 +4036,7 @@ For example: "Work" or "Personal"</property> <child> <widget class="GtkLabel" id="label472"> <property name="visible">True</property> - <property name="label" translatable="yes">S_elect...</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> @@ -3801,68 +4069,10 @@ For example: "Work" or "Personal"</property> <widget class="GtkButton" id="smime_sign_key_clear"> <property name="visible">True</property> <property name="can_focus">True</property> + <property name="label">gtk-clear</property> + <property name="use_stock">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> - </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> @@ -4142,7 +4352,7 @@ For example: "Work" or "Personal"</property> <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> <child> - <widget class="GtkNotebook" id="preferences_toplevel"> + <widget class="GtkNotebook" id="toplevel"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="show_tabs">True</property> @@ -5020,7 +5230,6 @@ For example: "Work" or "Personal"</property> <property name="directory_entry">False</property> <property name="modal">False</property> <property name="use_filechooser">True</property> - <property name="filechooser_action">GTK_FILE_CHOOSER_ACTION_OPEN</property> <child internal-child="entry"> <widget class="GtkEntry" id="txtNotifyPlaySound"> @@ -5031,7 +5240,7 @@ For example: "Work" or "Personal"</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="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> </child> @@ -5550,7 +5759,7 @@ For example: "Work" or "Personal"</property> <property name="max_length">0</property> <property name="text" translatable="yes">Important</property> <property name="has_frame">True</property> - <property name="invisible_char">*</property> + <property name="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> <packing> @@ -5572,7 +5781,7 @@ For example: "Work" or "Personal"</property> <property name="max_length">0</property> <property name="text" translatable="yes">Work</property> <property name="has_frame">True</property> - <property name="invisible_char">*</property> + <property name="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> <packing> @@ -5594,7 +5803,7 @@ For example: "Work" or "Personal"</property> <property name="max_length">0</property> <property name="text" translatable="yes">Personal</property> <property name="has_frame">True</property> - <property name="invisible_char">*</property> + <property name="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> <packing> @@ -5616,7 +5825,7 @@ For example: "Work" or "Personal"</property> <property name="max_length">0</property> <property name="text" translatable="yes">To Do</property> <property name="has_frame">True</property> - <property name="invisible_char">*</property> + <property name="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> <packing> @@ -5638,7 +5847,7 @@ For example: "Work" or "Personal"</property> <property name="max_length">0</property> <property name="text" translatable="yes">Later</property> <property name="has_frame">True</property> - <property name="invisible_char">*</property> + <property name="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> <packing> @@ -5793,7 +6002,7 @@ For example: "Work" or "Personal"</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="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> <packing> @@ -6241,7 +6450,7 @@ For example: "Work" or "Personal"</property> <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> <child> - <widget class="GtkNotebook" id="composer_toplevel"> + <widget class="GtkNotebook" id="toplevel"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="show_tabs">True</property> @@ -6400,7 +6609,7 @@ For example: "Work" or "Personal"</property> <child> <widget class="GtkAlignment" id="alignment25"> <property name="visible">True</property> - <property name="xalign">7.45058015283e-09</property> + <property name="xalign">7.45058e-09</property> <property name="yalign">0.5</property> <property name="xscale">0</property> <property name="yscale">1</property> @@ -7235,6 +7444,57 @@ For example: "Work" or "Personal"</property> <property name="spacing">12</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="pixmapSpellInfo"> + <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">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">This page allows you to configure spell checking behavior and language. 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> + </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="vbox196"> <property name="visible">True</property> <property name="homogeneous">False</property> @@ -7354,53 +7614,33 @@ For example: "Work" or "Personal"</property> </child> <child> - <widget class="GtkHBox" id="hboxImageAndHelp"> + <widget class="GtkHBox" id="hbox219"> <property name="visible">True</property> <property name="homogeneous">False</property> <property name="spacing">6</property> <child> - <widget class="GtkImage" id="pixmapSpellInfo"> + <widget class="GtkButton" id="buttonSpellCheckEnable"> <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> + <property name="sensitive">False</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Enable</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">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> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</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> + <property name="fill">False</property> </packing> </child> </widget> @@ -7579,7 +7819,7 @@ For example: "Work" or "Personal"</property> <packing> <property name="padding">0</property> <property name="expand">False</property> - <property name="fill">True</property> + <property name="fill">False</property> </packing> </child> </widget> @@ -8066,7 +8306,7 @@ for display purposes only. </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="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> <packing> @@ -8086,7 +8326,6 @@ for display purposes only. </property> <property name="directory_entry">False</property> <property name="modal">False</property> <property name="use_filechooser">True</property> - <property name="filechooser_action">GTK_FILE_CHOOSER_ACTION_OPEN</property> <child internal-child="entry"> <widget class="GtkEntry" id="combo-entry2"> @@ -8097,7 +8336,7 @@ for display purposes only. </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="invisible_char" translatable="yes">*</property> <property name="activates_default">False</property> </widget> </child> diff --git a/mail/mail-errors.xml b/mail/mail-errors.xml index 045cf9326a..9e32d5aba2 100644 --- a/mail/mail-errors.xml +++ b/mail/mail-errors.xml @@ -69,13 +69,6 @@ Many email systems add an Apparently-To header to messages that only have BCC re <button label="_Empty Trash" response="GTK_RESPONSE_YES"/> </error> - <error id="ask-open-many" type="warning" default="GTK_RESPONSE_CANCEL"> - <primary>Are you sure you want to open {0} messages at once?</primary> - <secondary>Opening too many messages at once may take a long time.</secondary> - <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/> - <button label="_Open Messages" response="GTK_RESPONSE_YES"/> - </error> - <error id="exit-unsaved" type="warning" default="GTK_RESPONSE_NO"> <primary>You have unsent messages, do you wish to quit anyway?</primary> <secondary>If you quit, these messages will not be sent until Evolution is started again.</secondary> @@ -263,7 +256,7 @@ The message is stored in the Outbox folder. Check the message for errors and re <error id="vfolder-notexist" type="error"> <primary>Cannot edit vFolder "{0}" as it does not exist.</primary> - <secondary>This folder may have been added implicitly, go to the vFolder editor to add it explicitly, if required.</secondary> + <secondary>This folder may have been added implictly, go to the virtual folder editor to add it explictly, if required.</secondary> </error> <error id="vfolder-notunique" type="error"> @@ -318,23 +311,9 @@ You can choose to ignore this folder, overwrite or append its contents, or quit. <button label="_Append" response="GTK_RESPONSE_OK"/> </error> - <error id="no-load-license" type="error"> - <primary>Unable to read license file.</primary> - <secondary>Cannot read the license file "{0}", due to an - installation problem. You will not be able to use this provider until - you can accept its license.</secondary> - </error> - - <error id="checking-service" type="info"> - <title>Querying server</title> - <primary>Please wait.</primary> - <secondary>Querying server for a list of supported authentication mechanisms.</secondary> - <button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/> - </error> - <error id="gw-accountsetup-error" type="error"> - <primary>Unable to connect to the GroupWise -server.</primary> + <primary><span weight="bold" size="larger">Unable to connect to the GroupWise +server.</span></primary> <secondary> Please check your account settings and try again. </secondary> diff --git a/mail/mail-errors.xml.h b/mail/mail-errors.xml.h index ba728c520d..74cdecfc92 100644 --- a/mail/mail-errors.xml.h +++ b/mail/mail-errors.xml.h @@ -49,11 +49,6 @@ char *s = N_("Are you sure you want to permanently remove all the deleted messag /* mail:ask-empty-trash secondary */ char *s = N_("If you continue, you will not be able to recover these messages."); char *s = N_("_Empty Trash"); -/* mail:ask-open-many primary */ -char *s = N_("Are you sure you want to open {0} messages at once?"); -/* mail:ask-open-many secondary */ -char *s = N_("Opening too many messages at once may take a long time."); -char *s = N_("_Open Messages"); /* mail:exit-unsaved primary */ char *s = N_("You have unsent messages, do you wish to quit anyway?"); /* mail:exit-unsaved secondary */ @@ -190,7 +185,7 @@ char *s = N_("_Discard changes"); /* mail:vfolder-notexist primary */ char *s = N_("Cannot edit vFolder \"{0}\" as it does not exist."); /* mail:vfolder-notexist secondary */ -char *s = N_("This folder may have been added implicitly, go to the vFolder editor to add it explicitly, if required."); +char *s = N_("This folder may have been added implictly, go to the virtual folder editor to add it explictly, if required."); /* mail:vfolder-notunique primary */ char *s = N_("Cannot add vFolder \"{0}\"."); /* mail:vfolder-notunique secondary */ @@ -235,18 +230,6 @@ char *s = N_("A non-empty folder at \"{1}\" already exists.\n" char *s = N_("Ignore"); char *s = N_("_Overwrite"); char *s = N_("_Append"); -/* mail:no-load-license primary */ -char *s = N_("Unable to read license file."); -/* mail:no-load-license secondary */ -char *s = N_("Cannot read the license file \"{0}\", due to an\n" - " installation problem. You will not be able to use this provider until\n" - " you can accept its license."); -/* mail:checking-service title */ -char *s = N_("Querying server"); -/* mail:checking-service primary */ -char *s = N_("Please wait."); -/* mail:checking-service secondary */ -char *s = N_("Querying server for a list of supported authentication mechanisms."); /* mail:gw-accountsetup-error primary */ char *s = N_("Unable to connect to the GroupWise\n" "server."); diff --git a/mail/mail-ops.c b/mail/mail-ops.c index 3c80c7c535..d0c5e272a1 100644 --- a/mail/mail-ops.c +++ b/mail/mail-ops.c @@ -36,14 +36,11 @@ #include <errno.h> #include <libgnome/gnome-exec.h> #include <gal/util/e-util.h> -#include <libgnome/gnome-i18n.h> #include <camel/camel-mime-filter-from.h> #include <camel/camel-stream-filter.h> #include <camel/camel-stream-fs.h> #include <camel/camel-mime-filter-charset.h> -#include <camel/camel-offline-folder.h> -#include <camel/camel-offline-store.h> #include <camel/camel-disco-folder.h> #include <camel/camel-disco-store.h> #include <camel/camel-operation.h> @@ -443,7 +440,8 @@ static char *resent_recipients[] = { /* send 1 message to a specific transport */ static void -mail_send_message(CamelFolder *queue, const char *uid, const char *destination, CamelFilterDriver *driver, CamelException *ex) +mail_send_message (CamelMimeMessage *message, const char *destination, + CamelFilterDriver *driver, CamelException *ex) { EAccount *account = NULL; const CamelInternetAddress *iaddr; @@ -456,14 +454,10 @@ mail_send_message(CamelFolder *queue, const char *uid, const char *destination, CamelFolder *folder = NULL; GString *err = NULL; XEvolution *xev; - CamelMimeMessage *message; int i; - - message = camel_folder_get_message(queue, uid, ex); - if (!message) - return; - camel_medium_set_header (CAMEL_MEDIUM (message), "X-Mailer", "Evolution " VERSION SUB_VERSION " " VERSION_COMMENT); + camel_medium_set_header (CAMEL_MEDIUM (message), "X-Mailer", + "Evolution " VERSION SUB_VERSION " " VERSION_COMMENT); xev = mail_tool_remove_xevolution_headers (message); @@ -532,18 +526,12 @@ mail_send_message(CamelFolder *queue, const char *uid, const char *destination, } /* post-process */ - err = g_string_new(""); - info = camel_message_info_new(NULL); - camel_message_info_set_flags(info, CAMEL_MESSAGE_SEEN, ~0); + info = camel_message_info_new (); + info->flags = CAMEL_MESSAGE_SEEN; if (sent_folder_uri) { folder = mail_tool_uri_to_folder (sent_folder_uri, 0, ex); - if (camel_exception_is_set(ex)) { - g_string_append_printf (err, _("Failed to append to %s: %s\n" - "Appending to local `Sent' folder instead."), - sent_folder_uri, camel_exception_get_description (ex)); - camel_exception_clear (ex); - } + camel_exception_clear (ex); g_free (sent_folder_uri); } @@ -560,12 +548,14 @@ mail_send_message(CamelFolder *queue, const char *uid, const char *destination, if (camel_exception_get_id (ex) == CAMEL_EXCEPTION_USER_CANCEL) goto exit; - /* sending mail, filtering failed */ + /* save this error */ + err = g_string_new (""); g_string_append_printf (err, _("Failed to apply outgoing filters: %s"), camel_exception_get_description (ex)); } } + retry_append: camel_exception_clear (ex); camel_folder_append_message (folder, message, info, NULL, ex); if (camel_exception_is_set (ex)) { @@ -576,48 +566,42 @@ mail_send_message(CamelFolder *queue, const char *uid, const char *destination, sent_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_SENT); + if (err == NULL) + err = g_string_new (""); + else + g_string_append (err, "\n\n"); + if (folder != sent_folder) { const char *name; camel_object_get (folder, NULL, CAMEL_OBJECT_DESCRIPTION, (char **) &name, 0); - if (err->len) - g_string_append(err, "\n\n"); g_string_append_printf (err, _("Failed to append to %s: %s\n" "Appending to local `Sent' folder instead."), name, camel_exception_get_description (ex)); camel_object_ref (sent_folder); camel_object_unref (folder); folder = sent_folder; - - camel_exception_clear (ex); - camel_folder_append_message (folder, message, info, NULL, ex); - } - - if (camel_exception_is_set (ex)) { - if (camel_exception_get_id (ex) == CAMEL_EXCEPTION_USER_CANCEL) - goto exit; - - if (err->len) - g_string_append(err, "\n\n"); + + goto retry_append; + } else { g_string_append_printf (err, _("Failed to append to local `Sent' folder: %s"), camel_exception_get_description (ex)); } } - - if (!camel_exception_is_set(ex)) - camel_folder_set_message_flags (queue, uid, CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_SEEN, ~0); - if (err->len) { + if (err != NULL) { /* set the culmulative exception report */ camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, err->str); } - exit: - g_string_free (err, TRUE); + exit: + camel_folder_sync (folder, FALSE, NULL); camel_message_info_free (info); camel_object_unref (folder); - camel_object_unref(message); + + if (err != NULL) + g_string_free (err, TRUE); } /* ** SEND MAIL QUEUE ***************************************************** */ @@ -673,11 +657,10 @@ send_queue_send(struct _mail_msg *mm) CamelMessageInfo *info; info = camel_folder_get_message_info (m->queue, uids->pdata[i]); - if (info) { - if ((camel_message_info_flags(info) & CAMEL_MESSAGE_DELETED) == 0) - send_uids->pdata[j++] = uids->pdata[i]; - camel_folder_free_message_info(m->queue, info); - } + if (info && info->flags & CAMEL_MESSAGE_DELETED) + continue; + + send_uids->pdata[j++] = uids->pdata[i]; } send_uids->len = j; @@ -692,32 +675,36 @@ send_queue_send(struct _mail_msg *mm) camel_operation_register (m->cancel); camel_exception_init (&ex); - - /* NB: This code somewhat abuses the 'exception' stuff. Apart from fatal problems, it is also - used as a mechanism to accumualte warning messages and present them back to the user. */ - + for (i = 0, j = 0; i < send_uids->len; i++) { int pc = (100 * i) / send_uids->len; + CamelMimeMessage *message; report_status (m, CAMEL_FILTER_STATUS_START, pc, _("Sending message %d of %d"), i+1, send_uids->len); - mail_send_message (m->queue, send_uids->pdata[i], m->destination, m->driver, &ex); - if (camel_exception_is_set (&ex)) { - if (ex.id != CAMEL_EXCEPTION_USER_CANCEL) { - /* merge exceptions into one */ - if (camel_exception_is_set (&mm->ex)) - camel_exception_setv (&mm->ex, CAMEL_EXCEPTION_SYSTEM, "%s\n\n%s", mm->ex.desc, ex.desc); - else - camel_exception_xfer (&mm->ex, &ex); - camel_exception_clear (&ex); - - /* keep track of the number of failures */ - j++; - } else { - /* transfer the USER_CANCEL exeption to the async op exception and then break */ + if (!(message = camel_folder_get_message (m->queue, send_uids->pdata[i], &ex))) { + /* I guess ignore errors where we can't get the message (should never happen anyway)? */ + camel_exception_clear (&ex); + continue; + } + + mail_send_message (message, m->destination, m->driver, &ex); + if (!camel_exception_is_set (&ex)) { + camel_folder_set_message_flags (m->queue, send_uids->pdata[i], CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_SEEN, ~0); + } else if (ex.id != CAMEL_EXCEPTION_USER_CANCEL) { + /* merge exceptions into one */ + if (camel_exception_is_set (&mm->ex)) + camel_exception_setv (&mm->ex, CAMEL_EXCEPTION_SYSTEM, "%s\n\n%s", mm->ex.desc, ex.desc); + else camel_exception_xfer (&mm->ex, &ex); - break; - } + camel_exception_clear (&ex); + + /* keep track of the number of failures */ + j++; + } else { + /* transfer the USER_CANCEL exeption to the async op exception and then break */ + camel_exception_xfer (&mm->ex, &ex); + break; } } @@ -2118,8 +2105,6 @@ static void prep_offline_do(struct _mail_msg *mm) camel_disco_folder_prepare_for_offline((CamelDiscoFolder *)folder, "(match-all)", &mm->ex); - } else if (CAMEL_IS_OFFLINE_FOLDER (folder)) { - camel_offline_folder_downsync ((CamelOfflineFolder *) folder, "(match-all)", &mm->ex); } /* prepare_for_offline should do this? */ /* of course it should all be atomic, but ... */ @@ -2213,18 +2198,6 @@ static void set_offline_do(struct _mail_msg *mm) &mm->ex); return; } - } else if (CAMEL_IS_OFFLINE_STORE (m->store)) { - if (!m->offline) { - camel_offline_store_set_network_state (CAMEL_OFFLINE_STORE (m->store), - CAMEL_OFFLINE_STORE_NETWORK_AVAIL, - &mm->ex); - return; - } else { - camel_offline_store_set_network_state (CAMEL_OFFLINE_STORE (m->store), - CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL, - &mm->ex); - return; - } } if (m->offline) diff --git a/mail/mail-ops.h b/mail/mail-ops.h index 21c0685165..8527994eaa 100644 --- a/mail/mail-ops.h +++ b/mail/mail-ops.h @@ -36,7 +36,7 @@ extern "C" { #include "camel/camel-mime-message.h" #include "camel/camel-operation.h" -#include "libedataserver/e-msgport.h" +#include "e-util/e-msgport.h" #include "e-util/e-account.h" void mail_append_mail (CamelFolder *folder, CamelMimeMessage *message, CamelMessageInfo *info, diff --git a/mail/mail-tools.c b/mail/mail-tools.c index b49fb38a43..20f6ae0fe9 100644 --- a/mail/mail-tools.c +++ b/mail/mail-tools.c @@ -36,7 +36,6 @@ #include <gconf/gconf.h> #include <gconf/gconf-client.h> -#include <libgnome/gnome-i18n.h> #include <camel/camel-vee-folder.h> #include <camel/camel-file-utils.h> diff --git a/mail/mail-vfolder.c b/mail/mail-vfolder.c index 8798ccba33..01cdd1ace2 100644 --- a/mail/mail-vfolder.c +++ b/mail/mail-vfolder.c @@ -59,9 +59,6 @@ static pthread_mutex_t vfolder_lock = PTHREAD_MUTEX_INITIALIZER; static GList *source_folders_remote; /* list of source folder uri's - remote ones */ static GList *source_folders_local; /* list of source folder uri's - local ones */ static GHashTable *vfolder_hash; -/* This is a slightly hacky solution to shutting down, we poll this variable in various - loops, and just quit processing if it is set. */ -static volatile int shutdown; /* are we shutting down? */ /* more globals ... */ extern CamelSession *session; @@ -87,7 +84,7 @@ vfolder_setup_desc(struct _mail_msg *mm, int done) { struct _setup_msg *m = (struct _setup_msg *)mm; - return g_strdup_printf(_("Setting up vFolder: %s"), m->folder->full_name); + return g_strdup_printf(_("Setting up vfolder: %s"), m->folder->full_name); } static void @@ -97,12 +94,12 @@ vfolder_setup_do(struct _mail_msg *mm) GList *l, *list = NULL; CamelFolder *folder; - d(printf("Setting up vFolder: %s\n", m->folder->full_name)); + d(printf("Setting up vfolder: %s\n", m->folder->full_name)); camel_vee_folder_set_expression((CamelVeeFolder *)m->folder, m->query); l = m->sources_uri; - while (l && !shutdown) { + while (l) { d(printf(" Adding uri: %s\n", (char *)l->data)); folder = mail_tool_uri_to_folder (l->data, 0, &mm->ex); if (folder) { @@ -115,15 +112,14 @@ vfolder_setup_do(struct _mail_msg *mm) } l = m->sources_folder; - while (l && !shutdown) { + while (l) { d(printf(" Adding folder: %s\n", ((CamelFolder *)l->data)->full_name)); camel_object_ref(l->data); list = g_list_append(list, l->data); l = l->next; } - if (!shutdown) - camel_vee_folder_set_folders((CamelVeeFolder *)m->folder, list); + camel_vee_folder_set_folders((CamelVeeFolder *)m->folder, list); l = list; while (l) { @@ -255,13 +251,9 @@ vfolder_adduri_do(struct _mail_msg *mm) GList *l; CamelFolder *folder = NULL; - if (shutdown) - return; - d(printf("%s uri to vfolder: %s\n", m->remove?"Removing":"Adding", m->uri)); /* we dont try lookup the cache if we are removing it, its no longer there */ - if (!m->remove && !mail_note_get_folder_from_uri(m->uri, &folder)) { g_warning("Folder '%s' disappeared while I was adding/remove it to/from my vfolder", m->uri); return; @@ -272,7 +264,7 @@ vfolder_adduri_do(struct _mail_msg *mm) if (folder != NULL) { l = m->folders; - while (l && !shutdown) { + while (l) { if (m->remove) camel_vee_folder_remove_folder((CamelVeeFolder *)l->data, folder); else @@ -410,19 +402,11 @@ uri_is_spethal(CamelStore *store, const char *uri) return TRUE; /* don't use strcasecmp here */ - if (url->fragment) { - res = (((store->flags & CAMEL_STORE_VTRASH) - && strcmp(url->fragment, CAMEL_VTRASH_NAME) == 0) - || ((store->flags & CAMEL_STORE_VJUNK) - && strcmp(url->fragment, CAMEL_VJUNK_NAME) == 0)); - } else { - res = url->path - && (((store->flags & CAMEL_STORE_VTRASH) - && strcmp(url->path, "/" CAMEL_VTRASH_NAME) == 0) - || ((store->flags & CAMEL_STORE_VJUNK) - && strcmp(url->path, "/" CAMEL_VJUNK_NAME) == 0)); - } - + res = url->path + && (((store->flags & CAMEL_STORE_VTRASH) + && strcmp(url->path, "/" CAMEL_VTRASH_NAME) == 0) + || ((store->flags & CAMEL_STORE_VJUNK) + && strcmp(url->path, "/" CAMEL_VJUNK_NAME) == 0)); camel_url_free(url); return res; @@ -896,7 +880,7 @@ vfolder_load_storage(void) (CamelObjectEventHookFunc)store_folder_renamed, NULL); d(printf("got store '%s' = %p\n", storeuri, vfolder_store)); - mail_component_load_store_by_uri (mail_component_peek (), storeuri, _("vFolders")); + mail_component_load_store_by_uri (mail_component_peek (), storeuri, _("VFolders")); /* load our rules */ user = g_strdup_printf ("%s/mail/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ())); @@ -1005,7 +989,7 @@ vfolder_edit_rule(const char *uri) w = filter_rule_get_widget((FilterRule *)newrule, (RuleContext *)context); - gd = (GtkDialog *)gtk_dialog_new_with_buttons(_("Edit vFolder"), NULL, + gd = (GtkDialog *)gtk_dialog_new_with_buttons(_("Edit VFolder"), NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, @@ -1089,7 +1073,7 @@ vfolder_gui_add_rule(EMVFolderRule *rule) w = filter_rule_get_widget((FilterRule *)rule, (RuleContext *)context); - gd = (GtkDialog *)gtk_dialog_new_with_buttons(_("New vFolder"), + gd = (GtkDialog *)gtk_dialog_new_with_buttons(_("New VFolder"), NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, @@ -1134,8 +1118,6 @@ vfolder_foreach_cb (gpointer key, gpointer data, gpointer user_data) void mail_vfolder_shutdown (void) { - shutdown = 1; - g_hash_table_foreach (vfolder_hash, vfolder_foreach_cb, NULL); g_hash_table_destroy (vfolder_hash); vfolder_hash = NULL; diff --git a/mail/message-list.c b/mail/message-list.c index 59c08cc3ce..c8b39ba462 100644 --- a/mail/message-list.c +++ b/mail/message-list.c @@ -39,7 +39,6 @@ #include <gtk/gtkmain.h> #include <gtk/gtkinvisible.h> -#include <libgnome/gnome-i18n.h> #include <gal/util/e-util.h> #include <gal/widgets/e-gui-utils.h> @@ -57,7 +56,7 @@ #include <camel/camel-folder.h> #include <camel/camel-folder-thread.h> #include <camel/camel-vee-folder.h> -#include <libedataserver/e-memory.h> +#include <e-util/e-memory.h> #include "filter/filter-label.h" @@ -153,6 +152,8 @@ enum { NORMALISED_LAST, }; +#define PARENT_TYPE (e_tree_scrolled_get_type ()) + /* #define SMART_ADDRESS_COMPARE */ #ifdef SMART_ADDRESS_COMPARE @@ -164,7 +165,7 @@ struct _EMailAddress { typedef struct _EMailAddress EMailAddress; #endif /* SMART_ADDRESS_COMPARE */ -G_DEFINE_TYPE (MessageList, message_list, E_TREE_SCROLLED_TYPE); +static ETreeScrolledClass *message_list_parent_class; static void on_cursor_activated_cmd (ETree *tree, int row, ETreePath path, gpointer user_data); static void on_selection_changed_cmd(ETree *tree, MessageList *ml); @@ -487,7 +488,7 @@ ml_search_forward(MessageList *ml, int start, int end, guint32 flags, guint32 ma path = e_tree_table_adapter_node_at_row(etta, row); if (path && (info = get_message_info(ml, path)) - && (camel_message_info_flags(info) & mask) == flags) + && (info->flags & mask) == flags) return path; } @@ -506,7 +507,7 @@ ml_search_backward(MessageList *ml, int start, int end, guint32 flags, guint32 m path = e_tree_table_adapter_node_at_row(etta, row); if (path && (info = get_message_info(ml, path)) - && (camel_message_info_flags(info) & mask) == flags) + && (info->flags & mask) == flags) return path; } @@ -1077,7 +1078,7 @@ subtree_unread(MessageList *ml, ETreePath node) info = e_tree_memory_node_get_data((ETreeMemory *)ml->model, node); g_assert(info); - if (!(camel_message_info_flags(info) & CAMEL_MESSAGE_SEEN)) + if (!(info->flags & CAMEL_MESSAGE_SEEN)) return TRUE; if ((child = e_tree_model_node_get_first_child (E_TREE_MODEL (ml->model), node))) @@ -1099,7 +1100,7 @@ subtree_size(MessageList *ml, ETreePath node) info = e_tree_memory_node_get_data((ETreeMemory *)ml->model, node); g_assert(info); - size += camel_message_info_size(info); + size += info->size; if ((child = e_tree_model_node_get_first_child (E_TREE_MODEL (ml->model), node))) size += subtree_size(ml, child); @@ -1120,9 +1121,9 @@ subtree_earliest(MessageList *ml, ETreePath node, int sent) g_assert(info); if (sent) - date = camel_message_info_date_sent(info); + date = info->date_sent; else - date = camel_message_info_date_received(info); + date = info->date_received; if (earliest == 0 || date < earliest) earliest = date; @@ -1145,7 +1146,6 @@ ml_tree_value_at (ETreeModel *etm, ETreePath path, int col, void *model_data) MessageList *message_list = model_data; CamelMessageInfo *msg_info; const char *str; - guint32 flags; if (e_tree_model_node_is_root (etm, path)) return NULL; @@ -1156,21 +1156,20 @@ ml_tree_value_at (ETreeModel *etm, ETreePath path, int col, void *model_data) switch (col){ case COL_MESSAGE_STATUS: - flags = camel_message_info_flags(msg_info); - if (flags & CAMEL_MESSAGE_ANSWERED) + if (msg_info->flags & CAMEL_MESSAGE_ANSWERED) return GINT_TO_POINTER (2); - else if (flags & CAMEL_MESSAGE_SEEN) + else if (msg_info->flags & CAMEL_MESSAGE_SEEN) return GINT_TO_POINTER (1); else return GINT_TO_POINTER (0); break; case COL_FLAGGED: - return GINT_TO_POINTER ((camel_message_info_flags(msg_info) & CAMEL_MESSAGE_FLAGGED) != 0); + return GINT_TO_POINTER ((msg_info->flags & CAMEL_MESSAGE_FLAGGED) != 0); case COL_SCORE: { const char *tag; int score = 0; - tag = camel_message_info_user_tag(msg_info, "score"); + tag = camel_tag_get ((CamelTag **) &msg_info->user_tags, "score"); if (tag) score = atoi (tag); @@ -1181,8 +1180,8 @@ ml_tree_value_at (ETreeModel *etm, ETreePath path, int col, void *model_data) /* FIXME: this all should be methods off of message-tag-followup class, FIXME: the tag names should be namespaced :( */ - tag = camel_message_info_user_tag(msg_info, "follow-up"); - cmp = camel_message_info_user_tag(msg_info, "completed-on"); + tag = camel_tag_get ((CamelTag **) &msg_info->user_tags, "follow-up"); + cmp = camel_tag_get ((CamelTag **) &msg_info->user_tags, "completed-on"); if (tag && tag[0]) { if (cmp && cmp[0]) return GINT_TO_POINTER(2); @@ -1195,7 +1194,7 @@ ml_tree_value_at (ETreeModel *etm, ETreePath path, int col, void *model_data) const char *tag; time_t due_by; - tag = camel_message_info_user_tag(msg_info, "due-by"); + tag = camel_tag_get ((CamelTag **) &msg_info->user_tags, "due-by"); if (tag && *tag) { due_by = camel_header_decode_date (tag, NULL); return GINT_TO_POINTER (due_by); @@ -1204,10 +1203,10 @@ ml_tree_value_at (ETreeModel *etm, ETreePath path, int col, void *model_data) } } case COL_FOLLOWUP_FLAG: - str = camel_message_info_user_tag(msg_info, "follow-up"); + str = camel_tag_get ((CamelTag **) &msg_info->user_tags, "follow-up"); return (void *)(str ? str : ""); case COL_ATTACHMENT: - return GINT_TO_POINTER ((camel_message_info_flags(msg_info) & CAMEL_MESSAGE_ATTACHMENTS) != 0); + return GINT_TO_POINTER ((msg_info->flags & CAMEL_MESSAGE_ATTACHMENTS) != 0); case COL_FROM: str = camel_message_info_from (msg_info); return (void *)(str ? str : ""); @@ -1219,41 +1218,38 @@ ml_tree_value_at (ETreeModel *etm, ETreePath path, int col, void *model_data) case COL_SUBJECT_NORM: return (void *) get_normalised_string (message_list, msg_info, col); case COL_SENT: - return GINT_TO_POINTER (camel_message_info_date_sent(msg_info)); + return GINT_TO_POINTER (msg_info->date_sent); case COL_RECEIVED: - return GINT_TO_POINTER (camel_message_info_date_received(msg_info)); + return GINT_TO_POINTER (msg_info->date_received); case COL_TO: str = camel_message_info_to (msg_info); return (void *)(str ? str : ""); case COL_TO_NORM: return (void *) get_normalised_string (message_list, msg_info, col); case COL_SIZE: - return GINT_TO_POINTER (camel_message_info_size(msg_info)); + return GINT_TO_POINTER (msg_info->size); case COL_DELETED: - return GINT_TO_POINTER ((camel_message_info_flags(msg_info) & CAMEL_MESSAGE_DELETED) != 0); + return GINT_TO_POINTER ((msg_info->flags & CAMEL_MESSAGE_DELETED) != 0); case COL_UNREAD: { ETreePath child; - flags = camel_message_info_flags(msg_info); - + child = e_tree_model_node_get_first_child(etm, path); if (child && !e_tree_node_is_expanded(message_list->tree, path) - && (flags & CAMEL_MESSAGE_SEEN)) { + && (msg_info->flags & CAMEL_MESSAGE_SEEN)) { return GINT_TO_POINTER (subtree_unread (message_list, child)); } - return GINT_TO_POINTER (!(flags & CAMEL_MESSAGE_SEEN)); + return GINT_TO_POINTER (!(msg_info->flags & CAMEL_MESSAGE_SEEN)); } case COL_COLOUR: { const char *colour, *due_by, *completed, *label; /* Priority: colour tag; label tag; important flag; due-by tag */ - - /* This is astonisngly poorly written code */ - - colour = camel_message_info_user_tag(msg_info, "colour"); - due_by = camel_message_info_user_tag(msg_info, "due-by"); - completed = camel_message_info_user_tag(msg_info, "completed-on"); - label = camel_message_info_user_tag(msg_info, "label"); + + colour = camel_tag_get ((CamelTag **) &msg_info->user_tags, "colour"); + due_by = camel_tag_get ((CamelTag **) &msg_info->user_tags, "due-by"); + completed = camel_tag_get ((CamelTag **) &msg_info->user_tags, "completed-on"); + label = camel_tag_get ((CamelTag **) &msg_info->user_tags, "label"); if (colour == NULL) { find_colour: if (label != NULL) { @@ -1263,7 +1259,7 @@ ml_tree_value_at (ETreeModel *etm, ETreePath path, int col, void *model_data) label = NULL; goto find_colour; } - } else if (camel_message_info_flags(msg_info) & CAMEL_MESSAGE_FLAGGED) { + } else if (msg_info->flags & CAMEL_MESSAGE_FLAGGED) { /* FIXME: extract from the important.xpm somehow. */ colour = "#A7453E"; } else if ((due_by && *due_by) && !(completed && *completed)) { @@ -1682,48 +1678,34 @@ ml_drop_action(struct _drop_msg *m) } static void -ml_drop_popup_copy(EPopup *ep, EPopupItem *item, void *data) +ml_drop_popup_copy(GtkWidget *item, struct _drop_msg *m) { - struct _drop_msg *m = data; - m->action = GDK_ACTION_COPY; ml_drop_action(m); } static void -ml_drop_popup_move(EPopup *ep, EPopupItem *item, void *data) +ml_drop_popup_move(GtkWidget *item, struct _drop_msg *m) { - struct _drop_msg *m = data; - m->action = GDK_ACTION_MOVE; ml_drop_action(m); } static void -ml_drop_popup_cancel(EPopup *ep, EPopupItem *item, void *data) +ml_drop_popup_cancel(GtkWidget *item, struct _drop_msg *m) { - struct _drop_msg *m = data; - m->aborted = TRUE; mail_msg_free(&m->msg); } -static EPopupItem ml_drop_popup_menu[] = { - { E_POPUP_ITEM, "00.emc.02", N_("_Copy"), ml_drop_popup_copy, NULL, "stock_folder-copy", 0 }, - { E_POPUP_ITEM, "00.emc.03", N_("_Move"), ml_drop_popup_move, NULL, "stock_folder-move", 0 }, - { E_POPUP_BAR, "10.emc" }, - { E_POPUP_ITEM, "99.emc.00", N_("Cancel _Drag"), ml_drop_popup_cancel, NULL, NULL, 0 }, +static EMPopupItem ml_drop_popup_menu[] = { + { EM_POPUP_ITEM, "00.emc.02", N_("_Copy"), G_CALLBACK(ml_drop_popup_copy), NULL, "stock_folder-copy", 0 }, + { EM_POPUP_ITEM, "00.emc.03", N_("_Move"), G_CALLBACK(ml_drop_popup_move), NULL, "stock_folder-move", 0 }, + { EM_POPUP_BAR, "10.emc" }, + { EM_POPUP_ITEM, "99.emc.00", N_("Cancel _Drag"), G_CALLBACK(ml_drop_popup_cancel), NULL, NULL, 0 }, }; static void -ml_drop_popup_free(EPopup *ep, GSList *items, void *data) -{ - g_slist_free(items); - - /* FIXME: free data if no item was selected? */ -} - -static void ml_tree_drag_data_received (ETree *tree, int row, ETreePath path, int col, GdkDragContext *context, gint x, gint y, GtkSelectionData *data, guint info, @@ -1755,12 +1737,15 @@ ml_tree_drag_data_received (ETree *tree, int row, ETreePath path, int col, GtkMenu *menu; int i; - emp = em_popup_new("org.gnome.mail.messagelist.popup.drop"); - for (i=0;i<sizeof(ml_drop_popup_menu)/sizeof(ml_drop_popup_menu[0]);i++) - menus = g_slist_append(menus, &ml_drop_popup_menu[i]); + emp = em_popup_new("com.ximian.mail.messagelist.popup.drop"); + for (i=0;i<sizeof(ml_drop_popup_menu)/sizeof(ml_drop_popup_menu[0]);i++) { + EMPopupItem *item = &ml_drop_popup_menu[i]; - e_popup_add_items((EPopup *)emp, menus, NULL, ml_drop_popup_free, m); - menu = e_popup_create_menu_once((EPopup *)emp, NULL, 0); + item->activate_data = m; + menus = g_slist_append(menus, item); + } + em_popup_add_items(emp, menus, (GDestroyNotify)g_slist_free); + menu = em_popup_create_menu_once(emp, NULL, 0, 0); gtk_menu_popup(menu, NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time()); } else { ml_drop_action(m); @@ -1802,11 +1787,12 @@ ml_scrolled (GtkAdjustment *adj, MessageList *ml) } /* - * GObject::init + * GtkObject::init */ static void -message_list_init (MessageList *message_list) +message_list_init (GtkObject *object) { + MessageList *message_list = MESSAGE_LIST (object); struct _MessageListPrivate *p; GtkAdjustment *adjustment; GdkAtom matom; @@ -1864,7 +1850,7 @@ message_list_destroy(GtkObject *object) mail_async_event_destroy(message_list->async_event); message_list->async_event = NULL; } - + if (message_list->folder) { /* need to do this before removing folder, folderinfo's might not exist after */ save_tree_state(message_list); @@ -1948,20 +1934,20 @@ message_list_finalise (GObject *object) } /* - * GObjectClass::init + * GtkObjectClass::init */ static void -message_list_class_init (MessageListClass *message_list_class) +message_list_class_init (GObjectClass *object_class) { - GObjectClass *object_class = (GObjectClass *) message_list_class; - GtkObjectClass *gtkobject_class = (GtkObjectClass *) message_list_class; int i; + message_list_parent_class = g_type_class_ref(PARENT_TYPE); + 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; + ((GtkObjectClass *)object_class)->destroy = message_list_destroy; message_list_signals[MESSAGE_SELECTED] = g_signal_new ("message_selected", @@ -1999,7 +1985,6 @@ message_list_class_init (MessageListClass *message_list_class) static void message_list_construct (MessageList *message_list) { - AtkObject *a11y; gboolean construct_failed; message_list->model = e_tree_memory_callbacks_new (ml_tree_icon_at, @@ -2041,11 +2026,6 @@ message_list_construct (MessageList *message_list) if (!construct_failed) e_tree_root_node_set_visible (message_list->tree, FALSE); - if (atk_get_root () != NULL) { - a11y = gtk_widget_get_accessible (message_list->tree); - atk_object_set_name (a11y, _("Message List")); - } - g_signal_connect((message_list->tree), "cursor_activated", G_CALLBACK (on_cursor_activated_cmd), message_list); @@ -2161,7 +2141,7 @@ find_next_undeleted (MessageList *ml) check |= CAMEL_MESSAGE_DELETED; info = get_message_info (ml, node); - if (info && (camel_message_info_flags(info) & check) == 0) { + if (info && (info->flags & check) == 0) { return NULL; } @@ -2178,7 +2158,7 @@ find_next_undeleted (MessageList *ml) node = e_tree_node_at_row (et, vrow); info = get_message_info (ml, node); - if (info && (camel_message_info_flags(info) & check) == 0) { + if (info && (info->flags & check) == 0) { return g_strdup (camel_message_info_uid (info)); } vrow ++; @@ -2681,21 +2661,17 @@ mail_folder_hide_by_flag (CamelFolder *folder, MessageList *ml, CamelFolderChang for (i = 0; i < oldchanges->uid_changed->len; i++) { ETreePath node = g_hash_table_lookup (ml->uid_nodemap, oldchanges->uid_changed->pdata[i]); - guint32 flags; - + info = camel_folder_get_message_info (folder, oldchanges->uid_changed->pdata[i]); - if (info) - flags = camel_message_info_flags(info); - - if (node != NULL && info != NULL && (flags & flag) != 0) + if (node != NULL && info != NULL && (info->flags & flag) != 0) camel_folder_change_info_remove_uid (newchanges, oldchanges->uid_changed->pdata[i]); - else if (node == NULL && info != NULL && (flags & flag) == 0) + else if (node == NULL && info != NULL && (info->flags & flag) == 0) camel_folder_change_info_add_uid (newchanges, oldchanges->uid_changed->pdata[i]); else camel_folder_change_info_change_uid (newchanges, oldchanges->uid_changed->pdata[i]); camel_folder_free_message_info (folder, info); } - + if (newchanges->uid_added->len > 0 || newchanges->uid_removed->len > 0) { for (i = 0; i < oldchanges->uid_added->len; i++) camel_folder_change_info_add_uid (newchanges, oldchanges->uid_added->pdata[i]); @@ -2764,7 +2740,7 @@ folder_changed (CamelObject *o, gpointer event_data, gpointer user_data) { CamelFolderChangeInfo *changes; MessageList *ml = MESSAGE_LIST (user_data); - + if (event_data) { changes = camel_folder_change_info_new(); camel_folder_change_info_cat(changes, (CamelFolderChangeInfo *)event_data); @@ -2806,7 +2782,6 @@ message_list_set_folder (MessageList *message_list, CamelFolder *folder, const c message_list->idle_id = 0; } - /* reset the normalised sort performance hack */ g_hash_table_foreach_remove (message_list->normalised_hash, normalised_free, NULL); mail_regen_cancel(message_list); @@ -2878,6 +2853,8 @@ message_list_set_folder (MessageList *message_list, CamelFolder *folder, const c } } +E_MAKE_TYPE (message_list, "MessageList", MessageList, message_list_class_init, message_list_init, PARENT_TYPE); + static gboolean on_cursor_activated_idle (gpointer data) { @@ -2957,8 +2934,7 @@ on_click (ETree *tree, gint row, ETreePath path, gint col, GdkEvent *event, Mess { CamelMessageInfo *info; int flag; - guint32 flags; - + if (col == COL_MESSAGE_STATUS) flag = CAMEL_MESSAGE_SEEN; else if (col == COL_FLAGGED) @@ -2968,21 +2944,19 @@ on_click (ETree *tree, gint row, ETreePath path, gint col, GdkEvent *event, Mess if (!(info = get_message_info (list, path))) return FALSE; - - flags = camel_message_info_flags(info); - + /* If a message was marked as deleted and the user flags it as important, marks it as needing a reply, marks it as unread, then undelete the message. */ - if (flags & CAMEL_MESSAGE_DELETED) { - if (col == COL_FLAGGED && !(flags & CAMEL_MESSAGE_FLAGGED)) + if (info->flags & CAMEL_MESSAGE_DELETED) { + if (col == COL_FLAGGED && !(info->flags & CAMEL_MESSAGE_FLAGGED)) flag |= CAMEL_MESSAGE_DELETED; - if (col == COL_MESSAGE_STATUS && (flags & CAMEL_MESSAGE_SEEN)) + if (col == COL_MESSAGE_STATUS && (info->flags & CAMEL_MESSAGE_SEEN)) flag |= CAMEL_MESSAGE_DELETED; } - camel_folder_set_message_flags (list->folder, camel_message_info_uid (info), flag, ~flags); + camel_folder_set_message_flags (list->folder, camel_message_info_uid (info), flag, ~info->flags); if (flag == CAMEL_MESSAGE_SEEN && list->seen_id) { g_source_remove (list->seen_id); @@ -3673,8 +3647,13 @@ mail_regen_list (MessageList *ml, const char *search, const char *hideexpr, Came struct _regen_list_msg *m; GConfClient *gconf; - if (ml->folder == NULL) + if (ml->folder == NULL) { + if (ml->search != search) { + g_free(ml->search); + ml->search = g_strdup(search); + } return; + } mail_regen_cancel(ml); |