aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mail/ChangeLog21
-rw-r--r--mail/em-composer-utils.c120
-rw-r--r--mail/em-folder-browser.c6
-rw-r--r--mail/em-folder-selection-button.c117
-rw-r--r--mail/em-folder-selection-button.h6
-rw-r--r--mail/em-folder-selector.c16
-rw-r--r--mail/em-folder-selector.h4
-rw-r--r--mail/em-folder-tree.c140
-rw-r--r--mail/em-folder-tree.h6
-rw-r--r--mail/em-subscribe-editor.c27
-rw-r--r--mail/em-utils.c169
-rw-r--r--mail/em-utils.h5
-rw-r--r--mail/mail-ops.c4
13 files changed, 534 insertions, 107 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog
index 18628947d1..bb6b4e56d2 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,3 +1,24 @@
+2004-01-12 Meilof Veeningen <meilof@wanadoo.nl>
+
+ * em-composer-utils.c: support for posting both to mail and to
+ (multiple) folders
+
+ * em-folder-browser.c: use em_utils_post_to_folder (works with NNTP)
+
+ * em-folder-selection-button.[ch]: added multiple selection mode
+
+ * em-folder-selector.[ch]: idem
+
+ * em-folder-tree.[ch]: added multiple selection mode, no longer show
+ disabled accounts
+
+ * em-utils.c: various changes to allow posting to (multiple) folders
+
+ * em-subscribe-editor.c: double-clicking a node in the editor updates
+ it directly
+
+ * mail-ops.c: for appending messages, set the "X-Mailer" header
+
2004-01-12 Radek Doulik <rodo@ximian.com>
* em-junk-filter.c (em_junk_sa_check_junk): use
diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c
index bc076a7f77..09ca8a8b4f 100644
--- a/mail/em-composer-utils.c
+++ b/mail/em-composer-utils.c
@@ -231,7 +231,7 @@ composer_send_queued_cb (CamelFolder *folder, CamelMimeMessage *msg, CamelMessag
}
static CamelMimeMessage *
-composer_get_message (EMsgComposer *composer, gboolean post, gboolean save_html_object_data)
+composer_get_message (EMsgComposer *composer, gboolean post, gboolean save_html_object_data, gboolean *no_recipients)
{
CamelMimeMessage *message = NULL;
EABDestination **recipients, **recipients_bcc;
@@ -296,10 +296,15 @@ composer_get_message (EMsgComposer *composer, gboolean post, gboolean save_html_
camel_object_unref (cia);
/* I'm sensing a lack of love, er, I mean recipients. */
- if (num == 0 && !post) {
- e_notice ((GtkWindow *) composer, GTK_MESSAGE_WARNING,
- _("You must specify recipients in order to send this message."));
- goto finished;
+ if (num == 0) {
+ if (post) {
+ if (no_recipients)
+ *no_recipients = TRUE;
+ } else {
+ e_notice ((GtkWindow *) composer, GTK_MESSAGE_WARNING,
+ _("You must specify recipients in order to send this message."));
+ goto finished;
+ }
}
if (num > 0 && (num == num_bcc || shown == 0)) {
@@ -389,55 +394,85 @@ em_utils_composer_send_cb (EMsgComposer *composer, gpointer user_data)
CamelMimeMessage *message;
CamelMessageInfo *info;
struct _send_data *send;
- gboolean post = FALSE;
- CamelFolder *folder;
+ gboolean no_recipients = FALSE;
+ CamelFolder *mail_folder = NULL, *tmpfldr;
+ GList *post_folders = NULL, *post_ptr;
XEvolution *xev;
- char *url;
-
- url = e_msg_composer_hdrs_get_post_to ((EMsgComposerHdrs *) composer->hdrs);
- if (url && *url) {
- post = TRUE;
-
- mail_msg_wait (mail_get_folder (url, 0, got_post_folder, &folder, mail_thread_new));
-
- if (!folder) {
- g_free (url);
- return;
- }
- } else {
- folder = outbox_folder;
- camel_object_ref (folder);
+ GList *postlist;
+
+ postlist = e_msg_composer_hdrs_get_post_to ((EMsgComposerHdrs *) composer->hdrs);
+ while (postlist) {
+ mail_msg_wait (mail_get_folder (postlist->data, 0, got_post_folder, &tmpfldr, mail_thread_new));
+ if (tmpfldr)
+ post_folders = g_list_append (post_folders, tmpfldr);
+ postlist = g_list_next (postlist);
}
- g_free (url);
+ mail_folder = outbox_folder;
+ camel_object_ref (mail_folder);
+
+ if (!post_folders && !mail_folder)
+ return;
- message = composer_get_message (composer, post, FALSE);
- if (!message)
+ if (!(message = composer_get_message (composer, post_folders != NULL, FALSE, &no_recipients)))
return;
- if (post) {
+ if (no_recipients) {
+ /* we're doing a post with no recipients */
+ camel_object_unref (mail_folder);
+ mail_folder = NULL;
+ }
+
+ if (mail_folder) {
+ /* mail the message */
+ info = camel_message_info_new ();
+ info->flags = CAMEL_MESSAGE_SEEN;
+
+ send = g_malloc (sizeof (*send));
+ send->emcs = user_data;
+ if (send->emcs)
+ emcs_ref (send->emcs);
+ send->send = TRUE;
+ send->composer = composer;
+ g_object_ref (composer);
+ gtk_widget_hide (GTK_WIDGET (composer));
+
+ e_msg_composer_set_enable_autosave (composer, FALSE);
+
+ mail_append_mail (mail_folder, message, info, composer_send_queued_cb, send);
+ camel_object_unref (mail_folder);
+ }
+
+ if (post_folders) {
/* Remove the X-Evolution* headers if we are in Post-To mode */
xev = mail_tool_remove_xevolution_headers (message);
mail_tool_destroy_xevolution (xev);
+
+ /* mail the message */
+ info = camel_message_info_new ();
+ info->flags = CAMEL_MESSAGE_SEEN;
+
+ post_ptr = post_folders;
+ while (post_ptr) {
+ send = g_malloc (sizeof (*send));
+ send->emcs = user_data;
+ if (send->emcs)
+ emcs_ref (send->emcs);
+ send->send = FALSE;
+ send->composer = composer;
+ g_object_ref (composer);
+ gtk_widget_hide (GTK_WIDGET (composer));
+
+ e_msg_composer_set_enable_autosave (composer, FALSE);
+
+ mail_append_mail ((CamelFolder *) post_ptr->data, message, info, composer_send_queued_cb, send);
+ camel_object_unref ((CamelFolder *) post_ptr->data);
+
+ post_ptr = g_list_next (post_ptr);
+ }
}
- info = camel_message_info_new ();
- info->flags = CAMEL_MESSAGE_SEEN;
-
- send = g_malloc (sizeof (*send));
- send->emcs = user_data;
- if (send->emcs)
- emcs_ref (send->emcs);
- send->send = !post;
- send->composer = composer;
- g_object_ref (composer);
- gtk_widget_hide (GTK_WIDGET (composer));
-
- e_msg_composer_set_enable_autosave (composer, FALSE);
-
- mail_append_mail (folder, message, info, composer_send_queued_cb, send);
camel_object_unref (message);
- camel_object_unref (folder);
}
struct _save_draft_info {
@@ -456,6 +491,7 @@ save_draft_done (CamelFolder *folder, CamelMimeMessage *msg, CamelMessageInfo *i
if (!ok)
goto done;
+
CORBA_exception_init (&ev);
GNOME_GtkHTML_Editor_Engine_runCommand (sdi->composer->editor_engine, "saved", &ev);
CORBA_exception_free (&ev);
diff --git a/mail/em-folder-browser.c b/mail/em-folder-browser.c
index ea89bd15a7..27cca529ad 100644
--- a/mail/em-folder-browser.c
+++ b/mail/em-folder-browser.c
@@ -618,11 +618,7 @@ static void
emfb_mail_post(BonoboUIComponent *uid, void *data, const char *path)
{
EMFolderView *emfv = data;
- char *url;
-
- url = mail_tools_folder_to_url (emfv->folder);
- em_utils_post_to_url (url);
- g_free (url);
+ em_utils_post_to_folder (emfv->folder);
}
static void
diff --git a/mail/em-folder-selection-button.c b/mail/em-folder-selection-button.c
index ce5f38680c..c6dc309d6b 100644
--- a/mail/em-folder-selection-button.c
+++ b/mail/em-folder-selection-button.c
@@ -35,6 +35,7 @@
#include "mail-component.h"
#include "em-folder-tree.h"
#include "em-folder-selector.h"
+#include "em-utils.h"
#include "em-folder-selection-button.h"
@@ -50,10 +51,13 @@ struct _EMFolderSelectionButtonPrivate {
GtkWidget *icon;
GtkWidget *label;
- char *uri;
+ char *uri; /* for single-select mode */
+ GList *uris; /* for multi-select mode */
char *title;
char *caption;
+
+ gboolean multiple_select;
};
enum {
@@ -120,25 +124,14 @@ static void
set_contents (EMFolderSelectionButton *button)
{
struct _EMFolderSelectionButtonPrivate *priv = button->priv;
- const char *folder_name;
- CamelURL *url;
-
- if (priv->uri == NULL
- || (url = camel_url_new (priv->uri, NULL)) == NULL) {
- set_contents_unselected (button);
- return;
- }
-
- folder_name = url->fragment ? url->fragment : url->path + 1;
+ char *folder_name = em_utils_folder_name_from_uri (priv->uri);
- if (folder_name == NULL) {
- camel_url_free (url);
+ if (folder_name) {
+ gtk_label_set_text (GTK_LABEL (priv->label), folder_name);
+ g_free (folder_name);
+ } else {
set_contents_unselected (button);
- return;
}
-
- gtk_label_set_text (GTK_LABEL (priv->label), folder_name);
- camel_url_free (url);
}
static void
@@ -150,6 +143,8 @@ em_folder_selection_button_init (EMFolderSelectionButton *emfsb)
priv = g_new0 (struct _EMFolderSelectionButtonPrivate, 1);
emfsb->priv = priv;
+ priv->multiple_select = FALSE;
+
box = gtk_hbox_new (FALSE, 4);
priv->icon = gtk_image_new ();
@@ -178,6 +173,10 @@ static void
em_folder_selection_button_finalize (GObject *obj)
{
struct _EMFolderSelectionButtonPrivate *priv = ((EMFolderSelectionButton *) obj)->priv;
+
+ GList *lst = ((EMFolderSelectionButton*) obj)->priv->uris;
+ g_list_foreach (lst, (GFunc) g_free, NULL);
+ g_list_free (lst);
g_free (priv->title);
g_free (priv->caption);
@@ -191,10 +190,17 @@ static void
emfsb_selector_response (EMFolderSelector *emfs, int response, EMFolderSelectionButton *button)
{
if (response == GTK_RESPONSE_OK) {
- const char *uri = em_folder_selector_get_selected_uri (emfs);
-
- em_folder_selection_button_set_selection (button, uri);
- g_signal_emit (button, signals[SELECTED], 0);
+ if (button->priv->multiple_select) {
+ GList *uris = em_folder_selector_get_selected_uris (emfs);
+
+ em_folder_selection_button_set_selection_mult (button, uris);
+ g_signal_emit (button, signals[SELECTED], 0);
+ } else {
+ const char *uri = em_folder_selector_get_selected_uri (emfs);
+
+ em_folder_selection_button_set_selection (button, uri);
+ g_signal_emit (button, signals[SELECTED], 0);
+ }
}
gtk_widget_destroy ((GtkWidget *) emfs);
@@ -213,9 +219,13 @@ em_folder_selection_button_clicked (GtkButton *button)
model = mail_component_peek_tree_model (mail_component_peek ());
emft = (EMFolderTree *) em_folder_tree_new_with_model (model);
+ em_folder_tree_set_multiselect (emft, priv->multiple_select);
dialog = em_folder_selector_new (emft, EM_FOLDER_SELECTOR_CAN_CREATE, priv->title, priv->caption);
- em_folder_selector_set_selected ((EMFolderSelector *) dialog, priv->uri);
+ if (priv->multiple_select)
+ em_folder_selector_set_selected_list ((EMFolderSelector *) dialog, priv->uris);
+ else
+ em_folder_selector_set_selected ((EMFolderSelector *) dialog, priv->uri);
g_signal_connect (dialog, "response", G_CALLBACK (emfsb_selector_response), button);
gtk_widget_show (dialog);
}
@@ -253,3 +263,66 @@ em_folder_selection_button_get_selection (EMFolderSelectionButton *button)
return button->priv->uri;
}
+
+void
+em_folder_selection_button_set_selection_mult (EMFolderSelectionButton *button, GList *uris)
+{
+ struct _EMFolderSelectionButtonPrivate *priv = button->priv;
+ char *caption, *tmp, *tmp2;
+
+ g_return_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button));
+
+ if (priv->uris) {
+ g_list_foreach (priv->uris, (GFunc) g_free, NULL);
+ g_list_free (priv->uris);
+ priv->uris = NULL;
+ }
+
+ priv->uris = uris;
+
+ /* compile the name */
+ caption = g_strdup ("");
+
+ while (uris) {
+ tmp = em_utils_folder_name_from_uri (uris->data);
+ if (tmp) {
+ tmp2 = g_strconcat (caption, ", ", tmp, NULL);
+ g_free (caption);
+ caption = tmp2;
+ g_free (tmp);
+ uris = uris->next;
+ } else {
+ /* apparently, we do not know this folder, so we'll just skip it */
+ g_free (uris->data);
+ uris = g_list_next (uris);
+ priv->uris = g_list_remove (priv->uris, uris->data);
+ }
+ }
+
+ if (caption[0])
+ gtk_label_set_text (GTK_LABEL (priv->label), caption + 2);
+ else
+ set_contents_unselected (button);
+
+ g_free (caption);
+}
+
+GList *
+em_folder_selection_button_get_selection_mult (EMFolderSelectionButton *button)
+{
+ g_return_val_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button), NULL);
+
+ return button->priv->uris;
+}
+
+void
+em_folder_selection_button_set_multiselect (EMFolderSelectionButton *button, gboolean value)
+{
+ button->priv->multiple_select = value;
+}
+
+gboolean
+em_folder_selection_button_get_multiselect (EMFolderSelectionButton *button)
+{
+ return button->priv->multiple_select;
+}
diff --git a/mail/em-folder-selection-button.h b/mail/em-folder-selection-button.h
index b8f64a4383..194a453efa 100644
--- a/mail/em-folder-selection-button.h
+++ b/mail/em-folder-selection-button.h
@@ -62,6 +62,12 @@ GtkWidget *em_folder_selection_button_new (const char *title, const char *captio
void em_folder_selection_button_set_selection (EMFolderSelectionButton *button, const char *uri);
const char *em_folder_selection_button_get_selection (EMFolderSelectionButton *button);
+void em_folder_selection_button_set_selection_mult (EMFolderSelectionButton *button, GList *uris);
+GList *em_folder_selection_button_get_selection_mult (EMFolderSelectionButton *button);
+
+void em_folder_selection_button_set_multiselect (EMFolderSelectionButton *button, gboolean value);
+gboolean em_folder_selection_button_get_multiselect (EMFolderSelectionButton *button);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/mail/em-folder-selector.c b/mail/em-folder-selector.c
index 5e2697ddf8..14169c94cc 100644
--- a/mail/em-folder-selector.c
+++ b/mail/em-folder-selector.c
@@ -280,6 +280,11 @@ em_folder_selector_set_selected (EMFolderSelector *emfs, const char *uri)
em_folder_tree_set_selected (emfs->emft, uri);
}
+void
+em_folder_selector_set_selected_list (EMFolderSelector *emfs, GList *list)
+{
+ em_folder_tree_set_selected_list (emfs->emft, list);
+}
const char *
em_folder_selector_get_selected_uri (EMFolderSelector *emfs)
@@ -329,6 +334,17 @@ em_folder_selector_get_selected_uri (EMFolderSelector *emfs)
return uri;
}
+GList *
+em_folder_selector_get_selected_uris (EMFolderSelector *emfs)
+{
+ return em_folder_tree_get_selected_uris (emfs->emft);
+}
+
+GList *
+em_folder_selector_get_selected_paths (EMFolderSelector *emfs)
+{
+ return em_folder_tree_get_selected_paths (emfs->emft);
+}
const char *
em_folder_selector_get_selected_path (EMFolderSelector *emfs)
diff --git a/mail/em-folder-selector.h b/mail/em-folder-selector.h
index 9d6a53ed30..0dbad9c7df 100644
--- a/mail/em-folder-selector.h
+++ b/mail/em-folder-selector.h
@@ -75,10 +75,14 @@ GtkWidget *em_folder_selector_new (struct _EMFolderTree *emft, guint32 flags, co
GtkWidget *em_folder_selector_create_new (struct _EMFolderTree *emft, guint32 flags, const char *title, const char *text);
void em_folder_selector_set_selected (EMFolderSelector *emfs, const char *uri);
+void em_folder_selector_set_selected_list (EMFolderSelector *emfs, GList *list);
const char *em_folder_selector_get_selected_uri (EMFolderSelector *emfs);
const char *em_folder_selector_get_selected_path (EMFolderSelector *emfs);
+GList *em_folder_selector_get_selected_uris (EMFolderSelector *emfs);
+GList *em_folder_selector_get_selected_paths (EMFolderSelector *emfs);
+
#ifdef cplusplus
}
#endif /* cplusplus */
diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c
index 45e8b3f48f..bc04551593 100644
--- a/mail/em-folder-tree.c
+++ b/mail/em-folder-tree.c
@@ -71,6 +71,10 @@ struct _EMFolderTreePrivate {
char *selected_uri;
char *selected_path;
+
+ gboolean do_multiselect;
+ /* when doing a multiselect, folders that we didn't find */
+ GList *lost_folders;
guint save_state_id;
@@ -130,6 +134,12 @@ static void emft_tree_row_expanded (GtkTreeView *treeview, GtkTreeIter *root, Gt
static gboolean emft_tree_button_press (GtkWidget *treeview, GdkEventButton *event, EMFolderTree *emft);
static void emft_tree_selection_changed (GtkTreeSelection *selection, EMFolderTree *emft);
+struct _emft_selection_data {
+ GtkTreeModel *model;
+ GtkTreeIter *iter;
+ gboolean set;
+};
+
static GtkVBoxClass *parent_class = NULL;
@@ -289,6 +299,7 @@ em_folder_tree_init (EMFolderTree *emft)
struct _EMFolderTreePrivate *priv;
priv = g_new0 (struct _EMFolderTreePrivate, 1);
+ priv->lost_folders = NULL;
priv->selected_uri = NULL;
priv->selected_path = NULL;
priv->treeview = NULL;
@@ -300,6 +311,13 @@ static void
em_folder_tree_finalize (GObject *obj)
{
EMFolderTree *emft = (EMFolderTree *) obj;
+
+ /* clear list of lost uris */
+ if (emft->priv->lost_folders) {
+ g_list_foreach (emft->priv->lost_folders, (GFunc) g_free, NULL);
+ g_list_free (emft->priv->lost_folders);
+ emft->priv->lost_folders = NULL;
+ }
g_free (emft->priv->selected_uri);
g_free (emft->priv->selected_path);
@@ -431,7 +449,7 @@ emft_expand_node (const char *key, gpointer value, EMFolderTree *emft)
return;
id = g_strndup (key, p - key);
- if ((account = mail_config_get_account_by_uid (id))) {
+ if ((account = mail_config_get_account_by_uid (id)) && account->enabled) {
CamelException ex;
CamelStore *store;
@@ -531,6 +549,83 @@ em_folder_tree_enable_drag_and_drop (EMFolderTree *emft)
GDK_ACTION_COPY | GDK_ACTION_MOVE);
}
+void
+em_folder_tree_set_multiselect (EMFolderTree *tree, gboolean mode)
+{
+ GtkTreeSelection *sel = gtk_tree_view_get_selection ((GtkTreeView *) tree->priv->treeview);
+
+ tree->priv->do_multiselect = mode;
+ gtk_tree_selection_set_mode (sel, mode ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE);
+}
+
+static void
+get_selected_uris_iterate (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
+{
+ GList **list = (GList **) data;
+ char *uri;
+
+ gtk_tree_model_get (model, iter, /*COL_STRING_FOLDER_PATH, &path,*/
+ COL_STRING_URI, &uri, -1);
+ *list = g_list_append (*list, g_strdup (uri));
+}
+
+GList *
+em_folder_tree_get_selected_uris (EMFolderTree *emft)
+{
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (emft->priv->treeview);
+ GList *lost = emft->priv->lost_folders;
+ GList *list = NULL;
+
+ /* at first, add lost uris */
+ while (lost) {
+ list = g_list_append (list, g_strdup (lost->data));
+ lost = g_list_next (lost);
+ }
+
+ gtk_tree_selection_selected_foreach (selection, get_selected_uris_iterate, &list);
+
+ return list;
+}
+
+static void
+get_selected_uris_path_iterate (GtkTreeModel *model, GtkTreePath *treepath, GtkTreeIter *iter, gpointer data)
+{
+ GList **list = (GList **) data;
+ char *path;
+
+ gtk_tree_model_get (model, iter, COL_STRING_FOLDER_PATH, &path, -1);
+ *list = g_list_append (*list, g_strdup (path));
+}
+
+GList *
+em_folder_tree_get_selected_paths (EMFolderTree *emft)
+{
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (emft->priv->treeview);
+ GList *list = NULL;
+
+ gtk_tree_selection_selected_foreach (selection, get_selected_uris_path_iterate, &list);
+
+ return list;
+}
+
+void
+em_folder_tree_set_selected_list (EMFolderTree *emft, GList *list)
+{
+ struct _EMFolderTreePrivate *priv = emft->priv;
+
+ /* clear list of lost uris */
+ if (priv->lost_folders) {
+ g_list_foreach (priv->lost_folders, (GFunc)g_free, NULL);
+ g_list_free (priv->lost_folders);
+ priv->lost_folders = NULL;
+ }
+
+ while (list) {
+ em_folder_tree_set_selected (emft, list->data);
+ list = g_list_next (list);
+ }
+}
+
#if 0
static void
@@ -616,8 +711,11 @@ emft_get_folder_info__got (struct _mail_msg *mm)
gtk_tree_model_get ((GtkTreeModel *) model, &root,
COL_BOOL_LOAD_SUBDIRS, &load,
-1);
- if (!load)
+ if (!load) {
+ if (priv->do_multiselect && m->select_uri)
+ priv->lost_folders = g_list_append (priv->lost_folders, g_strdup (m->select_uri));
return;
+ }
/* get the first child (which will be a dummy node) */
gtk_tree_model_iter_children ((GtkTreeModel *) model, &iter, &root);
@@ -1157,6 +1255,32 @@ emft_popup_delete_folders (CamelStore *store, const char *path, CamelException *
}
static void
+selfunc (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
+{
+ struct _emft_selection_data *dat = (struct _emft_selection_data *) data;
+
+ dat->model = model;
+ if (!dat->set)
+ *(dat->iter) = *iter;
+ dat->set = TRUE;
+}
+
+static gboolean
+emft_selection_get_selected (GtkTreeSelection *selection, GtkTreeModel **model, GtkTreeIter *iter)
+{
+ struct _emft_selection_data dat = { NULL, iter, FALSE };
+
+ if (gtk_tree_selection_get_mode (selection) == GTK_SELECTION_MULTIPLE) {
+ gtk_tree_selection_selected_foreach (selection, selfunc, &dat);
+ if (model)
+ *model = dat.model;
+ return dat.set;
+ } else {
+ return gtk_tree_selection_get_selected (selection, model, iter);
+ }
+}
+
+static void
emft_popup_delete_response (GtkWidget *dialog, guint response, EMFolderTree *emft)
{
struct _EMFolderTreePrivate *priv = emft->priv;
@@ -1172,7 +1296,7 @@ emft_popup_delete_response (GtkWidget *dialog, guint response, EMFolderTree *emf
return;
selection = gtk_tree_view_get_selection (priv->treeview);
- gtk_tree_selection_get_selected (selection, &model, &iter);
+ emft_selection_get_selected (selection, &model, &iter);
gtk_tree_model_get (model, &iter, COL_STRING_FOLDER_PATH, &path,
COL_POINTER_CAMEL_STORE, &store, -1);
@@ -1195,7 +1319,7 @@ emft_popup_delete_folder (GtkWidget *item, EMFolderTree *emft)
char *title, *path;
selection = gtk_tree_view_get_selection (priv->treeview);
- gtk_tree_selection_get_selected (selection, &model, &iter);
+ emft_selection_get_selected (selection, &model, &iter);
gtk_tree_model_get (model, &iter, COL_STRING_FOLDER_PATH, &path, -1);
dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
@@ -1232,7 +1356,7 @@ emft_popup_rename_folder (GtkWidget *item, EMFolderTree *emft)
size_t base_len;
selection = gtk_tree_view_get_selection (priv->treeview);
- gtk_tree_selection_get_selected (selection, &model, &iter);
+ emft_selection_get_selected (selection, &model, &iter);
gtk_tree_model_get (model, &iter, COL_STRING_FOLDER_PATH, &folder_path,
COL_STRING_DISPLAY_NAME, &name,
COL_POINTER_CAMEL_STORE, &store,
@@ -1509,7 +1633,7 @@ emft_popup_properties (GtkWidget *item, EMFolderTree *emft)
char *uri;
selection = gtk_tree_view_get_selection (priv->treeview);
- gtk_tree_selection_get_selected (selection, &model, &iter);
+ emft_selection_get_selected (selection, &model, &iter);
gtk_tree_model_get (model, &iter, COL_STRING_URI, &uri, -1);
mail_get_folder (uri, 0, emft_popup_properties_got_folder, emft, mail_thread_new);
@@ -1578,7 +1702,7 @@ emft_tree_selection_changed (GtkTreeSelection *selection, EMFolderTree *emft)
GtkTreeIter iter;
char *path, *uri;
- if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+ if (!emft_selection_get_selected (selection, &model, &iter))
return;
gtk_tree_model_get (model, &iter, COL_STRING_FOLDER_PATH, &path,
@@ -1670,7 +1794,7 @@ em_folder_tree_set_selected (EMFolderTree *emft, const char *uri)
row = si->row;
top = NULL;
}
-
+
/* FIXME: this gets all the subfolders of our first loaded
* parent folder - ideally we'd only get what we needed, but
* it's probably not worth the effort */
diff --git a/mail/em-folder-tree.h b/mail/em-folder-tree.h
index ec4e9301d9..2742b9fe15 100644
--- a/mail/em-folder-tree.h
+++ b/mail/em-folder-tree.h
@@ -65,6 +65,12 @@ GtkWidget *em_folder_tree_new_with_model (EMFolderTreeModel *model);
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_selected_list (EMFolderTree *emft, GList *list);
+GList *em_folder_tree_get_selected_uris (EMFolderTree *emft);
+GList *em_folder_tree_get_selected_paths (EMFolderTree *emft);
+
void em_folder_tree_set_selected (EMFolderTree *emft, const char *uri);
const char *em_folder_tree_get_selected_uri (EMFolderTree *emft);
const char *em_folder_tree_get_selected_path (EMFolderTree *emft);
diff --git a/mail/em-subscribe-editor.c b/mail/em-subscribe-editor.c
index 1fb9066362..a23af0a333 100644
--- a/mail/em-subscribe-editor.c
+++ b/mail/em-subscribe-editor.c
@@ -127,7 +127,6 @@ struct _EMSubscribeNode {
static void sub_editor_busy(EMSubscribeEditor *se, int dir);
static int sub_queue_fill_level(EMSubscribe *sub, EMSubscribeNode *node);
-static void sub_selection_changed(GtkTreeSelection *selection, EMSubscribe *sub);
static void
sub_node_free(char *key, EMSubscribeNode *node, EMSubscribe *sub)
@@ -195,7 +194,7 @@ sub_folder_subscribe (struct _mail_msg *mm)
camel_store_unsubscribe_folder (m->sub->store, m->node->info->full_name, &mm->ex);
}
-static void
+static void
sub_folder_subscribed (struct _mail_msg *mm)
{
struct _zsubscribe_msg *m = (struct _zsubscribe_msg *)mm, *next;
@@ -503,6 +502,29 @@ sub_selection_changed(GtkTreeSelection *selection, EMSubscribe *sub)
gtk_widget_set_sensitive(sub->editor->unsubscribe_button, dounsub);
}
+/* double-clicking causes a node item to be evaluated directly */
+static void sub_row_activated(GtkTreeView *tree, GtkTreePath *path, GtkTreeViewColumn *col, EMSubscribe *sub) {
+ EMSubscribeNode *node;
+ GtkTreeIter iter;
+ GtkTreeModel *model = gtk_tree_view_get_model(tree);
+
+ if (gtk_tree_model_get_iter(model, &iter, path) != TRUE) return;
+
+ gtk_tree_model_get(model, &iter, 2, &node, -1);
+
+ /* check whether the item is already processed */
+ if (node->path == NULL)
+ return;
+
+ /* remove it from wherever in the list it is, and place it in front instead */
+ e_dlist_remove((EDListNode *)node);
+ e_dlist_addhead(&sub->pending, (EDListNode *)node);
+
+ if (sub->pending_id == -1
+ && (node = (EMSubscribeNode *)e_dlist_remtail(&sub->pending)))
+ sub_queue_fill_level(sub, node);
+}
+
static void
sub_row_expanded(GtkTreeView *tree, GtkTreeIter *iter, GtkTreePath *path, EMSubscribe *sub)
{
@@ -621,6 +643,7 @@ subscribe_set_store(EMSubscribe *sub, CamelStore *store)
gtk_tree_view_set_headers_visible (sub->tree, FALSE);
g_signal_connect(sub->tree, "row-expanded", G_CALLBACK(sub_row_expanded), sub);
+ g_signal_connect(sub->tree, "row-activated", G_CALLBACK(sub_row_activated), sub);
g_signal_connect(sub->tree, "destroy", G_CALLBACK(sub_destroy), sub);
sub_selection_changed(selection, sub);
diff --git a/mail/em-utils.c b/mail/em-utils.c
index c942af0036..7a4c94b3b4 100644
--- a/mail/em-utils.c
+++ b/mail/em-utils.c
@@ -52,7 +52,7 @@
#include "em-composer-utils.h"
#include "em-format-quote.h"
-static EAccount *guess_account (CamelMimeMessage *message);
+static EAccount *guess_account (CamelMimeMessage *message, CamelFolder *folder);
static void emu_save_part_done (CamelMimePart *part, char *name, int done, void *data);
/**
@@ -343,6 +343,44 @@ em_utils_compose_new_message_with_mailto (const char *url)
}
/**
+ * em_utils_post_to_folder:
+ * @folder: folder
+ *
+ * Opens a new composer window as a child window of @parent's toplevel
+ * window. If @folder is non-NULL, the composer will default to posting
+ * mail to the folder specified by @folder.
+ **/
+void
+em_utils_post_to_folder (CamelFolder *folder)
+{
+ EMsgComposer *composer;
+ EAccount *account;
+
+ composer = e_msg_composer_new_with_type (E_MSG_COMPOSER_POST);
+
+ if (folder != NULL) {
+ char *url = mail_tools_folder_to_url (folder);
+
+ e_msg_composer_hdrs_set_post_to ((EMsgComposerHdrs *) ((EMsgComposer *) composer)->hdrs, url);
+ g_free (url);
+
+ url = camel_url_to_string (CAMEL_SERVICE (folder->parent_store)->url, CAMEL_URL_HIDE_ALL);
+ account = mail_config_get_account_by_source_url (url);
+ g_free (url);
+
+ if (account)
+ e_msg_composer_set_headers (composer, account->name, NULL, NULL, NULL, "");
+ }
+
+ em_composer_utils_setup_default_callbacks (composer);
+
+ e_msg_composer_unset_changed (composer);
+ e_msg_composer_drop_editor_undo (composer);
+
+ gtk_widget_show ((GtkWidget *) composer);
+}
+
+/**
* em_utils_post_to_url:
* @url: mailto url
*
@@ -355,7 +393,7 @@ em_utils_post_to_url (const char *url)
{
EMsgComposer *composer;
- composer = e_msg_composer_new_post ();
+ composer = e_msg_composer_new_with_type (E_MSG_COMPOSER_POST);
if (url != NULL)
e_msg_composer_hdrs_set_post_to ((EMsgComposerHdrs *) ((EMsgComposer *) composer)->hdrs, url);
@@ -647,7 +685,7 @@ redirect_get_composer (CamelMimeMessage *message)
while (camel_medium_get_header (CAMEL_MEDIUM (message), "Delivered-To"))
camel_medium_remove_header (CAMEL_MEDIUM (message), "Delivered-To");
- account = guess_account (message);
+ account = guess_account (message, NULL);
composer = e_msg_composer_new_redirect (message, account ? account->name : NULL);
@@ -795,7 +833,8 @@ em_utils_camel_address_to_destination (CamelInternetAddress *iaddr)
static EMsgComposer *
reply_get_composer (CamelMimeMessage *message, EAccount *account,
- CamelInternetAddress *to, CamelInternetAddress *cc)
+ CamelInternetAddress *to, CamelInternetAddress *cc,
+ CamelFolder *folder, const char *postto)
{
const char *message_id, *references;
EABDestination **tov, **ccv;
@@ -805,13 +844,19 @@ reply_get_composer (CamelMimeMessage *message, EAccount *account,
g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
g_return_val_if_fail (to == NULL || CAMEL_IS_INTERNET_ADDRESS (to), NULL);
g_return_val_if_fail (cc == NULL || CAMEL_IS_INTERNET_ADDRESS (cc), NULL);
-
- composer = e_msg_composer_new ();
-
+
/* construct the tov/ccv */
tov = em_utils_camel_address_to_destination (to);
ccv = em_utils_camel_address_to_destination (cc);
-
+
+ if (tov || ccv) {
+ if (postto)
+ composer = e_msg_composer_new_with_type (E_MSG_COMPOSER_MAIL_POST);
+ else
+ composer = e_msg_composer_new_with_type (E_MSG_COMPOSER_MAIL);
+ } else
+ composer = e_msg_composer_new_with_type (E_MSG_COMPOSER_POST);
+
/* Set the subject of the new message. */
if ((subject = (char *) camel_mime_message_get_subject (message))) {
if (strncasecmp (subject, "Re: ", 4) != 0)
@@ -821,11 +866,25 @@ reply_get_composer (CamelMimeMessage *message, EAccount *account,
} else {
subject = g_strdup ("");
}
-
+
e_msg_composer_set_headers (composer, account ? account->name : NULL, tov, ccv, NULL, subject);
g_free (subject);
+ /* add post-to, if nessecary */
+ if (postto) {
+ char *store_url = NULL;
+
+ if (folder) {
+ store_url = camel_url_to_string (CAMEL_SERVICE (folder->parent_store)->url, CAMEL_URL_HIDE_ALL);
+ if (store_url[strlen (store_url) - 1] == '/')
+ store_url[strlen (store_url)-1] = '\0';
+ }
+
+ e_msg_composer_hdrs_set_post_to_base (E_MSG_COMPOSER_HDRS (composer->hdrs), store_url ? store_url : "", postto);
+ g_free (store_url);
+ }
+
/* Add In-Reply-To and References. */
message_id = camel_medium_get_header (CAMEL_MEDIUM (message), "Message-Id");
references = camel_medium_get_header (CAMEL_MEDIUM (message), "References");
@@ -851,13 +910,26 @@ reply_get_composer (CamelMimeMessage *message, EAccount *account,
}
static EAccount *
-guess_account (CamelMimeMessage *message)
+guess_account (CamelMimeMessage *message, CamelFolder *folder)
{
const CamelInternetAddress *to, *cc;
- GHashTable *account_hash;
+ GHashTable *account_hash = NULL;
EAccount *account = NULL;
const char *addr;
int i;
+ const char *posthdr, *tmp;
+
+ /* check for newsgroup header */
+ posthdr = camel_medium_get_header (CAMEL_MEDIUM (message), "Newsgroups");
+
+ if (posthdr && folder) {
+ /* this was posted at a newsgroup! */
+ tmp = camel_url_to_string (CAMEL_SERVICE (folder->parent_store)->url, CAMEL_URL_HIDE_ALL);
+ account = mail_config_get_account_by_source_url (tmp);
+ g_free (tmp);
+ if (account)
+ goto found;
+ }
to = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_TO);
cc = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_CC);
@@ -885,18 +957,28 @@ guess_account (CamelMimeMessage *message)
found:
- g_hash_table_destroy (account_hash);
+ if (account_hash)
+ g_hash_table_destroy (account_hash);
return account;
}
static void
-get_reply_sender (CamelMimeMessage *message, CamelInternetAddress **to)
+get_reply_sender (CamelMimeMessage *message, CamelInternetAddress **to, const char **postto)
{
const CamelInternetAddress *reply_to;
- const char *name, *addr;
+ const char *name, *addr, *posthdr;
int i;
+ /* check whether there is a 'Newsgroups: ' header in there */
+ posthdr = camel_medium_get_header (CAMEL_MEDIUM (message), "Newsgroups");
+ if (posthdr && postto) {
+ *postto = posthdr;
+ while (**postto == ' ')
+ (*postto)++;
+ return;
+ }
+
reply_to = camel_mime_message_get_reply_to (message);
if (!reply_to)
reply_to = camel_mime_message_get_from (message);
@@ -967,13 +1049,21 @@ concat_unique_addrs (CamelInternetAddress *dest, const CamelInternetAddress *src
}
static void
-get_reply_all (CamelMimeMessage *message, CamelInternetAddress **to, CamelInternetAddress **cc)
+get_reply_all (CamelMimeMessage *message, CamelInternetAddress **to, CamelInternetAddress **cc, const char **postto)
{
const CamelInternetAddress *reply_to, *to_addrs, *cc_addrs;
- const char *name, *addr;
+ const char *name, *addr, *posthdr;
GHashTable *rcpt_hash;
int i;
+ /* check whether there is a 'Newsgroups: ' header in there */
+ posthdr = camel_medium_get_header (CAMEL_MEDIUM(message), "Newsgroups");
+ if (posthdr && postto) {
+ *postto = posthdr;
+ while (**postto == ' ')
+ (*postto)++;
+ }
+
rcpt_hash = generate_account_hash ();
reply_to = camel_mime_message_get_reply_to (message);
@@ -1079,21 +1169,21 @@ em_utils_reply_to_message (CamelMimeMessage *message, int mode)
EMsgComposer *composer;
EAccount *account;
- account = guess_account (message);
+ account = guess_account (message, NULL);
switch (mode) {
case REPLY_MODE_SENDER:
- get_reply_sender (message, &to);
+ get_reply_sender (message, &to, NULL);
break;
case REPLY_MODE_LIST:
if (get_reply_list (message, &to))
break;
case REPLY_MODE_ALL:
- get_reply_all (message, &to, &cc);
+ get_reply_all (message, &to, &cc, NULL);
break;
}
- composer = reply_get_composer (message, account, to, cc);
+ composer = reply_get_composer (message, account, to, cc, NULL, NULL);
e_msg_composer_add_message_attachments (composer, message, TRUE);
if (to != NULL)
@@ -1114,19 +1204,20 @@ static void
reply_to_message (CamelFolder *folder, const char *uid, CamelMimeMessage *message, void *user_data)
{
CamelInternetAddress *to = NULL, *cc = NULL;
+ const char *postto = NULL;
EMsgComposer *composer;
EAccount *account;
guint32 flags;
int mode;
mode = GPOINTER_TO_INT (user_data);
-
- account = guess_account (message);
+
+ account = guess_account (message, folder);
flags = CAMEL_MESSAGE_ANSWERED | CAMEL_MESSAGE_SEEN;
switch (mode) {
case REPLY_MODE_SENDER:
- get_reply_sender (message, &to);
+ get_reply_sender (message, &to, &postto);
break;
case REPLY_MODE_LIST:
flags |= CAMEL_MESSAGE_ANSWERED_ALL;
@@ -1134,11 +1225,11 @@ reply_to_message (CamelFolder *folder, const char *uid, CamelMimeMessage *messag
break;
case REPLY_MODE_ALL:
flags |= CAMEL_MESSAGE_ANSWERED_ALL;
- get_reply_all (message, &to, &cc);
+ get_reply_all (message, &to, &cc, &postto);
break;
}
- composer = reply_get_composer (message, account, to, cc);
+ composer = reply_get_composer (message, account, to, cc, folder, postto);
e_msg_composer_add_message_attachments (composer, message, TRUE);
if (to != NULL)
@@ -1187,12 +1278,12 @@ post_reply_to_message (CamelFolder *folder, const char *uid, CamelMimeMessage *m
EAccount *account;
guint32 flags;
- account = guess_account (message);
+ account = guess_account (message, folder);
flags = CAMEL_MESSAGE_ANSWERED | CAMEL_MESSAGE_SEEN;
- get_reply_sender (message, &to);
+ get_reply_sender (message, &to, NULL);
- composer = e_msg_composer_new_post ();
+ composer = e_msg_composer_new_with_type (E_MSG_COMPOSER_MAIL_POST);
/* construct the tov/ccv */
tov = em_utils_camel_address_to_destination (to);
@@ -2374,3 +2465,25 @@ em_utils_empty_trash (GtkWidget *parent)
/* Now empty the local trash folder */
mail_empty_trash (NULL, NULL, NULL);
}
+
+char *
+em_utils_folder_name_from_uri (const char *uri)
+{
+ CamelURL *url;
+ char *folder_name;
+
+ if (uri == NULL || (url = camel_url_new (uri, NULL)) == NULL)
+ return NULL;
+
+ folder_name = url->fragment ? url->fragment : url->path + 1;
+
+ if (folder_name == NULL) {
+ camel_url_free (url);
+ return NULL;
+ }
+
+ folder_name = g_strdup (folder_name);
+ camel_url_free (url);
+
+ return folder_name;
+}
diff --git a/mail/em-utils.h b/mail/em-utils.h
index f0d8e4249a..6b54e48de2 100644
--- a/mail/em-utils.h
+++ b/mail/em-utils.h
@@ -59,6 +59,7 @@ void em_utils_compose_new_message (void);
/* FIXME: mailto? url? should make up its mind what its called. imho use 'uri' */
void em_utils_compose_new_message_with_mailto (const char *url);
+void em_utils_post_to_folder (struct _CamelFolder *folder);
void em_utils_post_to_url (const char *url);
void em_utils_edit_message (struct _CamelMimeMessage *message);
@@ -121,6 +122,10 @@ char *em_utils_message_to_html(struct _CamelMimeMessage *msg, const char *credit
void em_utils_expunge_folder (struct _GtkWidget *parent, struct _CamelFolder *folder);
void em_utils_empty_trash (struct _GtkWidget *parent);
+/* returns the folder name portion of an URI */
+char *em_utils_folder_name_from_uri (const char *uri);
+
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/mail/mail-ops.c b/mail/mail-ops.c
index 32eb68b4f1..380ba24d30 100644
--- a/mail/mail-ops.c
+++ b/mail/mail-ops.c
@@ -887,6 +887,10 @@ mail_append_mail (CamelFolder *folder, CamelMimeMessage *message, CamelMessageIn
g_assert(CAMEL_IS_FOLDER (folder));
g_assert(CAMEL_IS_MIME_MESSAGE (message));
+ if (!camel_medium_get_header (CAMEL_MEDIUM (message), "X-Mailer"))
+ camel_medium_set_header (CAMEL_MEDIUM (message), "X-Mailer",
+ "Ximian Evolution " VERSION SUB_VERSION " " VERSION_COMMENT);
+
m = mail_msg_new (&append_mail_op, NULL, sizeof (*m));
m->folder = folder;
camel_object_ref(folder);