aboutsummaryrefslogtreecommitdiffstats
path: root/mail
diff options
context:
space:
mode:
authorJeffrey Stedfast <fejj@ximian.com>2003-11-14 03:02:07 +0800
committerJeffrey Stedfast <fejj@src.gnome.org>2003-11-14 03:02:07 +0800
commitfd244132adb4225b6982422632bd69bc57b4e589 (patch)
treee6f706c7bb025b7bd90498aa3a6517924955a6a7 /mail
parent4e093efda9886a3c51cdefd3fc236807a34e11f9 (diff)
downloadgsoc2013-evolution-fd244132adb4225b6982422632bd69bc57b4e589.tar
gsoc2013-evolution-fd244132adb4225b6982422632bd69bc57b4e589.tar.gz
gsoc2013-evolution-fd244132adb4225b6982422632bd69bc57b4e589.tar.bz2
gsoc2013-evolution-fd244132adb4225b6982422632bd69bc57b4e589.tar.lz
gsoc2013-evolution-fd244132adb4225b6982422632bd69bc57b4e589.tar.xz
gsoc2013-evolution-fd244132adb4225b6982422632bd69bc57b4e589.tar.zst
gsoc2013-evolution-fd244132adb4225b6982422632bd69bc57b4e589.zip
New folder-tree widget that replaces the shell's folder-tree widget.
2003-11-13 Jeffrey Stedfast <fejj@ximian.com> * em-folder-tree.[c,h]: New folder-tree widget that replaces the shell's folder-tree widget. * em-folder-tree-model.[c,h]: New source files subclassing GtkTreeStore for handling the mess that is drag&drop. * em-folder-selection-button.c: Ported to use EMFolderTree. * em-folder-selection.c: Ported to use EMFolderTree. * em-folder-selector.c: Ported to use EMFolderTree. * mail-component.c: Ported to use EMFolderTree. * mail-offline-handler.c (storage_go_online): Updated to not pass a storage argument. * mail-folder-cache.c: Removed storage stuff. * mail-send-recv.c (receive_update_got_store): Don't do EStorage* stuff anymore. svn path=/trunk/; revision=23331
Diffstat (limited to 'mail')
-rw-r--r--mail/ChangeLog62
-rw-r--r--mail/Makefile.am4
-rw-r--r--mail/em-folder-selection-button.c322
-rw-r--r--mail/em-folder-selection-button.h72
-rw-r--r--mail/em-folder-selection.c31
-rw-r--r--mail/em-folder-selection.h55
-rw-r--r--mail/em-folder-selector.c434
-rw-r--r--mail/em-folder-selector.h70
-rw-r--r--mail/em-folder-tree-model.c284
-rw-r--r--mail/em-folder-tree-model.h81
-rw-r--r--mail/em-folder-tree.c1516
-rw-r--r--mail/em-folder-tree.h13
-rw-r--r--mail/em-marshal.list5
-rw-r--r--mail/mail-component-factory.c2
-rw-r--r--mail/mail-component.c1515
-rw-r--r--mail/mail-component.h11
-rw-r--r--mail/mail-folder-cache.c83
-rw-r--r--mail/mail-folder-cache.h14
-rw-r--r--mail/mail-offline-handler.c2
-rw-r--r--mail/mail-send-recv.c16
20 files changed, 2277 insertions, 2315 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog
index 0413bf7094..ae41feb26a 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,3 +1,27 @@
+2003-11-13 Jeffrey Stedfast <fejj@ximian.com>
+
+ * em-folder-tree.[c,h]: New folder-tree widget that replaces the
+ shell's folder-tree widget.
+
+ * em-folder-tree-model.[c,h]: New source files subclassing
+ GtkTreeStore for handling the mess that is drag&drop.
+
+ * em-folder-selection-button.c: Ported to use EMFolderTree.
+
+ * em-folder-selection.c: Ported to use EMFolderTree.
+
+ * em-folder-selector.c: Ported to use EMFolderTree.
+
+ * mail-component.c: Ported to use EMFolderTree.
+
+ * mail-offline-handler.c (storage_go_online): Updated to not pass
+ a storage argument.
+
+ * mail-folder-cache.c: Removed storage stuff.
+
+ * mail-send-recv.c (receive_update_got_store): Don't do EStorage*
+ stuff anymore.
+
2003-11-13 Ettore Perazzoli <ettore@ximian.com>
* mail-component.c (impl__get_userCreatableItems): New,
@@ -31,7 +55,8 @@
2003-11-11 Not Zed <NotZed@Ximian.com>
- * em-format-html.c (efh_application_xpkcs7mime): output icons of the status.
+ * em-format-html.c (efh_application_xpkcs7mime): output icons of
+ the status.
(em_format_html_add_pobject): Changed to take a size specificier,
return the pobject, and re-ordered args to be more consistent with
puri stuff.
@@ -77,6 +102,41 @@
* Makefile.am: build the marshall files right at the beginning
+2003-11-11 Not Zed <NotZed@Ximian.com>
+
+ * mail-security.glade: new glade file for security related stuff.
+
+ * mail-config.glade: removed the message security dialogue, it
+ gets opened automatically by the config code :(
+
+2003-11-10 Ettore Perazzoli <ettore@ximian.com>
+
+ * GNOME_Evolution_Mail.server.in.in: Set an
+ "evolution:component_alias" property with a value of "mail".
+
+2003-11-10 Not Zed <NotZed@Ximian.com>
+
+ * em-format-html.c (em_format_html_multipart_signed_sign): changed
+ for cipher context api changes.
+ * em-format.c (emf_multipart_signed): ditto.
+
+2003-11-07 Not Zed <NotZed@Ximian.com>
+
+ * mail-config.glade: added security_information_dialog (probably
+ temporarily in this file).
+
+ * em-format.c (em_format_is_attachment): also treat pkcs7-mime as
+ non-attachment.
+ (emf_application_xpkcs7mime): no longer need to worry about
+ scanning the part.
+
+2003-11-07 Dan Winship <danw@ximian.com>
+
+ * message-list.c: Don't #include e-name-western.h, since the code
+ that uses it is commented out, and we want to remove the local
+ copy, but we don't want to make the mailer depend on the e-d-s
+ copy if it's not even going to be using it.
+
2003-11-07 JP Rosevear <jpr@ximian.com>
* Makefile.am: Make sure the marshal files are listed above other
diff --git a/mail/Makefile.am b/mail/Makefile.am
index 417ee0be24..858f25c3de 100644
--- a/mail/Makefile.am
+++ b/mail/Makefile.am
@@ -77,6 +77,10 @@ libevolution_mail_la_SOURCES = \
em-folder-selection-button.h \
em-folder-selector.c \
em-folder-selector.h \
+ em-folder-tree.c \
+ em-folder-tree.h \
+ em-folder-tree-model.c \
+ em-folder-tree-model.h \
em-folder-view.c \
em-folder-view.h \
em-folder-browser.c \
diff --git a/mail/em-folder-selection-button.c b/mail/em-folder-selection-button.c
index ac5a6e1d06..42964a10b2 100644
--- a/mail/em-folder-selection-button.c
+++ b/mail/em-folder-selection-button.c
@@ -1,51 +1,60 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* em-folder-selection-button.c
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
*
- * Copyright (C) 2003 Ximian, Inc.
+ * Copyright 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 free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * 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.
+ * 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.
+ * 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 Street #330, Boston, MA 02111-1307, USA.
*
- * Author: Ettore Perazzoli <ettore@ximian.com>
*/
+
+#ifdef HAVE_CONFIG_H
#include <config.h>
+#endif
#include <string.h>
-#include "em-folder-selection-button.h"
+#include <gtk/gtkimage.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkhbox.h>
+
+#include <gal/util/e-util.h>
#include "mail-component.h"
+#include "em-folder-tree.h"
#include "em-folder-selector.h"
-#include <gal/util/e-util.h>
+#include "em-folder-selection-button.h"
-#include <gtk/gtkimage.h>
-#include <gtk/gtklabel.h>
-#include <gtk/gtkhbox.h>
+static void em_folder_selection_button_class_init (EMFolderSelectionButtonClass *klass);
+static void em_folder_selection_button_init (EMFolderSelectionButton *emfsb);
+static void em_folder_selection_button_destroy (GtkObject *obj);
+static void em_folder_selection_button_finalize (GObject *obj);
+static void em_folder_selection_button_clicked (GtkButton *button);
-#define PARENT_TYPE gtk_button_get_type ()
static GtkButtonClass *parent_class = NULL;
struct _EMFolderSelectionButtonPrivate {
GtkWidget *icon;
GtkWidget *label;
-
+
char *uri;
-
+
char *title;
char *caption;
};
@@ -54,10 +63,55 @@ enum {
SELECTED,
LAST_SIGNAL
};
+
static guint signals[LAST_SIGNAL] = { 0 };
-/* Utility functions. */
+GType
+em_folder_selection_button_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (EMFolderSelectionButtonClass),
+ NULL, /* base_class_init */
+ NULL, /* base_class_finalize */
+ (GClassInitFunc) em_folder_selection_button_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (EMFolderSelectionButton),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) em_folder_selection_button_init,
+ };
+
+ type = g_type_register_static (GTK_TYPE_BUTTON, "EMFolderSelectionButton", &info, 0);
+ }
+
+ return type;
+}
+
+static void
+em_folder_selection_button_class_init (EMFolderSelectionButtonClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass);
+ GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass);
+
+ parent_class = g_type_class_ref (GTK_TYPE_BUTTON);
+
+ object_class->finalize = em_folder_selection_button_finalize;
+ gtk_object_class->destroy = em_folder_selection_button_destroy;
+ button_class->clicked = em_folder_selection_button_clicked;
+
+ signals[SELECTED] = g_signal_new ("selected",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (EMFolderSelectionButtonClass, selected),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
static void
set_contents_unselected (EMFolderSelectionButton *button)
@@ -69,174 +123,140 @@ set_contents_unselected (EMFolderSelectionButton *button)
static void
set_contents (EMFolderSelectionButton *button)
{
- EMFolderSelectionButtonPrivate *priv = button->priv;
- char *path, *tmp, *label;
-
- if (priv->uri == NULL)
- goto unset;
-
- /* We set the button name directly from the storage set path, which is /accountname/path/foldername */
- path = e_storage_set_get_path_for_physical_uri(mail_component_peek_storage_set(mail_component_peek()), priv->uri);
-
- if (path == NULL)
- goto unknown;
-
- tmp = strchr(path+1, '/');
- if (tmp == NULL)
- goto unknown;
- *tmp++ = 0;
-
- label = g_strdup_printf(_("\"%s\" in \"%s\""), tmp, path+1);
- gtk_label_set_text (GTK_LABEL (priv->label), label);
- g_free (label);
-
- g_free(path);
- return;
+ struct _EMFolderSelectionButtonPrivate *priv = button->priv;
+ const char *path;
+ CamelURL *url;
+
+ if (priv->uri == NULL) {
+ set_contents_unselected (button);
+ return;
+ }
+
+ url = camel_url_new (priv->uri, NULL);
+ path = url->fragment ? url->fragment : url->path;
+
+ if (path == NULL) {
+ camel_url_free (url);
+ set_contents_unselected (button);
+ return;
+ }
+
+ gtk_label_set_text (GTK_LABEL (priv->label), path);
+ camel_url_free (url);
+}
-unknown:
- g_free(path);
-unset:
- set_contents_unselected(button);
+static void
+em_folder_selection_button_init (EMFolderSelectionButton *emfsb)
+{
+ struct _EMFolderSelectionButtonPrivate *priv;
+ GtkWidget *box;
+
+ priv = g_new0 (struct _EMFolderSelectionButtonPrivate, 1);
+ emfsb->priv = priv;
+
+ box = gtk_hbox_new (FALSE, 4);
+
+ priv->icon = gtk_image_new ();
+ gtk_widget_show (priv->icon);
+ gtk_box_pack_start (GTK_BOX (box), priv->icon, FALSE, TRUE, 0);
+
+ priv->label = gtk_label_new ("");
+ gtk_widget_show (priv->label);
+ gtk_label_set_justify (GTK_LABEL (priv->label), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment (GTK_MISC (priv->label), 0.0, 0.0);
+ gtk_box_pack_start (GTK_BOX (box), priv->label, TRUE, TRUE, 0);
+
+ gtk_widget_show (box);
+ gtk_container_add (GTK_CONTAINER (emfsb), box);
+
+ set_contents (emfsb);
}
static void
-impl_finalize (GObject *object)
+em_folder_selection_button_destroy (GtkObject *obj)
{
- EMFolderSelectionButtonPrivate *priv = EM_FOLDER_SELECTION_BUTTON (object)->priv;
+ GTK_OBJECT_CLASS (parent_class)->destroy (obj);
+}
+static void
+em_folder_selection_button_finalize (GObject *obj)
+{
+ struct _EMFolderSelectionButtonPrivate *priv = ((EMFolderSelectionButton *) obj)->priv;
+
g_free (priv->title);
g_free (priv->caption);
- g_free(priv->uri);
+ g_free (priv->uri);
g_free (priv);
-
- (* G_OBJECT_CLASS (parent_class)->finalize) (object);
+
+ G_OBJECT_CLASS (parent_class)->finalize (obj);
}
static void
-emfsb_selector_response(EMFolderSelector *emfs, int response, EMFolderSelectionButton *button)
+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);
+ 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);
+
+ gtk_widget_destroy ((GtkWidget *) emfs);
}
static void
-impl_clicked (GtkButton *button)
+em_folder_selection_button_clicked (GtkButton *button)
{
- EMFolderSelectionButtonPrivate *priv = EM_FOLDER_SELECTION_BUTTON (button)->priv;
- EStorageSet *ess;
- GtkWidget *w;
- GtkWidget *toplevel;
-
+ struct _EMFolderSelectionButtonPrivate *priv = EM_FOLDER_SELECTION_BUTTON (button)->priv;
+ EMFolderTreeModel *model;
+ EMFolderTree *emft;
+ GtkWidget *dialog;
+
if (GTK_BUTTON_CLASS (parent_class)->clicked != NULL)
(* GTK_BUTTON_CLASS (parent_class)->clicked) (button);
-
- toplevel = gtk_widget_get_toplevel (GTK_WIDGET (button));
- ess = mail_component_peek_storage_set(mail_component_peek());
- w = em_folder_selector_new(ess, EM_FOLDER_SELECTOR_CAN_CREATE, priv->title, priv->caption);
- em_folder_selector_set_selected_uri((EMFolderSelector *)w, priv->uri);
- g_signal_connect(w, "response", G_CALLBACK(emfsb_selector_response), button);
- gtk_widget_show(w);
-}
-#if 0
-{
- uri = em_folder_selection_run_dialog_uri((GtkWindow *)toplevel,
- priv->title,
- priv->caption,
- priv->uri);
-
- em_folder_selection_button_set_selection (EM_FOLDER_SELECTION_BUTTON (button), uri);
- g_free(uri);
-
- g_signal_emit (button, signals[SELECTED], 0);
-}
-#endif
-
-static void
-class_init (EMFolderSelectionButtonClass *class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (class);
- GtkButtonClass *button_class = GTK_BUTTON_CLASS (class);
-
- object_class->finalize = impl_finalize;
-
- button_class->clicked = impl_clicked;
-
- parent_class = g_type_class_peek_parent (class);
-
- signals[SELECTED] = g_signal_new ("selected",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (EMFolderSelectionButtonClass, selected),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
+
+ model = mail_component_get_tree_model (mail_component_peek ());
+ emft = em_folder_tree_new_with_model (model);
+
+ dialog = em_folder_selector_new (emft, EM_FOLDER_SELECTOR_CAN_CREATE, priv->title, priv->caption);
+ em_folder_selector_set_selected ((EMFolderSelector *) dialog, priv->uri);
+ g_signal_connect (dialog, "response", G_CALLBACK (emfsb_selector_response), button);
+ gtk_widget_show (dialog);
}
-static void
-init (EMFolderSelectionButton *folder_selection_button)
-{
- EMFolderSelectionButtonPrivate *priv;
- GtkWidget *box;
-
- priv = g_new0 (EMFolderSelectionButtonPrivate, 1);
- folder_selection_button->priv = priv;
-
- box = gtk_hbox_new (FALSE, 4);
-
- priv->icon = gtk_image_new ();
- gtk_box_pack_start (GTK_BOX (box), priv->icon, FALSE, TRUE, 0);
-
- priv->label = gtk_label_new ("");
- gtk_label_set_justify (GTK_LABEL (priv->label), GTK_JUSTIFY_LEFT);
- gtk_misc_set_alignment (GTK_MISC (priv->label), 0.0, 0.0);
- gtk_box_pack_start (GTK_BOX (box), priv->label, TRUE, TRUE, 0);
-
- gtk_widget_show_all (box);
- gtk_container_add (GTK_CONTAINER (folder_selection_button), box);
-
- set_contents (folder_selection_button);
-}
GtkWidget *
-em_folder_selection_button_new(const char *title, const char *caption)
+em_folder_selection_button_new (const char *title, const char *caption)
{
EMFolderSelectionButton *button = g_object_new (EM_TYPE_FOLDER_SELECTION_BUTTON, NULL);
-
+
button->priv->title = g_strdup (title);
button->priv->caption = g_strdup (caption);
-
+
return GTK_WIDGET (button);
}
void
-em_folder_selection_button_set_selection(EMFolderSelectionButton *button, const char *uri)
+em_folder_selection_button_set_selection (EMFolderSelectionButton *button, const char *uri)
{
- EMFolderSelectionButtonPrivate *p = button->priv;
-
- g_return_if_fail(EM_IS_FOLDER_SELECTION_BUTTON(button));
-
- if (p->uri != uri) {
- g_free(p->uri);
- p->uri = g_strdup(uri);
+ struct _EMFolderSelectionButtonPrivate *priv = button->priv;
+
+ g_return_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button));
+
+ if (priv->uri != uri) {
+ g_free (priv->uri);
+ priv->uri = g_strdup (uri);
}
-
- set_contents(button);
+
+ set_contents (button);
}
const char *
-em_folder_selection_button_get_selection(EMFolderSelectionButton *button)
+em_folder_selection_button_get_selection (EMFolderSelectionButton *button)
{
g_return_val_if_fail (EM_IS_FOLDER_SELECTION_BUTTON (button), NULL);
-
+
return button->priv->uri;
}
-
-E_MAKE_TYPE (em_folder_selection_button, "EMFolderSelectionButton", EMFolderSelectionButton, class_init, init, PARENT_TYPE)
diff --git a/mail/em-folder-selection-button.h b/mail/em-folder-selection-button.h
index 1ab4eb461c..b8f64a4383 100644
--- a/mail/em-folder-selection-button.h
+++ b/mail/em-folder-selection-button.h
@@ -1,59 +1,69 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* em-folder-selection-button.h
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
*
- * Copyright (C) 2003 Ximian, Inc.
+ * Copyright 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 free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * 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.
+ * 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.
+ * 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 Street #330, Boston, MA 02111-1307, USA.
*
- * Author: Ettore Perazzoli <ettore@ximian.com>
*/
-#ifndef _EM_FOLDER_SELECTION_BUTTON_H_
-#define _EM_FOLDER_SELECTION_BUTTON_H_
+
+#ifndef __EM_FOLDER_SELECTION_BUTTON_H__
+#define __EM_FOLDER_SELECTION_BUTTON_H__
#include <gtk/gtkbutton.h>
-#define EM_TYPE_FOLDER_SELECTION_BUTTON (em_folder_selection_button_get_type ())
-#define EM_FOLDER_SELECTION_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON, EMFolderSelectionButton))
-#define EM_FOLDER_SELECTION_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EM_TYPE_FOLDER_SELECTION_BUTTON, EMFolderSelectionButtonClass))
-#define EM_IS_FOLDER_SELECTION_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON))
-#define EM_IS_FOLDER_SELECTION_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON))
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+#define EM_TYPE_FOLDER_SELECTION_BUTTON (em_folder_selection_button_get_type ())
+#define EM_FOLDER_SELECTION_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON, EMFolderSelectionButton))
+#define EM_FOLDER_SELECTION_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EM_TYPE_FOLDER_SELECTION_BUTTON, EMFolderSelectionButtonClass))
+#define EM_IS_FOLDER_SELECTION_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON))
+#define EM_IS_FOLDER_SELECTION_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EM_TYPE_FOLDER_SELECTION_BUTTON))
typedef struct _EMFolderSelectionButton EMFolderSelectionButton;
-typedef struct _EMFolderSelectionButtonPrivate EMFolderSelectionButtonPrivate;
typedef struct _EMFolderSelectionButtonClass EMFolderSelectionButtonClass;
struct _EMFolderSelectionButton {
GtkButton parent;
-
- EMFolderSelectionButtonPrivate *priv;
+
+ struct _EMFolderSelectionButtonPrivate *priv;
};
struct _EMFolderSelectionButtonClass {
GtkButtonClass parent_class;
-
+
/* Signals. */
-
+
void (* selected) (EMFolderSelectionButton *button);
};
+
GType em_folder_selection_button_get_type (void);
-GtkWidget *em_folder_selection_button_new(const char *title, const char *caption);
+GtkWidget *em_folder_selection_button_new (const char *title, const char *caption);
+
+void em_folder_selection_button_set_selection (EMFolderSelectionButton *button, const char *uri);
+const char *em_folder_selection_button_get_selection (EMFolderSelectionButton *button);
-void em_folder_selection_button_set_selection(EMFolderSelectionButton *button, const char *uri);
-const char *em_folder_selection_button_get_selection(EMFolderSelectionButton *button);
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
-#endif /* _EM_FOLDER_SELECTION_BUTTON_H_ */
+#endif /* __EM_FOLDER_SELECTION_BUTTON_H__ */
diff --git a/mail/em-folder-selection.c b/mail/em-folder-selection.c
index c65ad80fc7..5178facd2d 100644
--- a/mail/em-folder-selection.c
+++ b/mail/em-folder-selection.c
@@ -1,25 +1,26 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* em-folder-selection.c - UI for selecting folders.
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
*
- * Copyright (C) 2002 Ximian, Inc.
+ * Copyright 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 free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * 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.
+ * 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.
+ * 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 Street #330, Boston, MA 02111-1307, USA.
*
- * Author: Ettore Perazzoli <ettore@ximian.com>
*/
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
diff --git a/mail/em-folder-selection.h b/mail/em-folder-selection.h
index 374e1eec3f..8237e546f7 100644
--- a/mail/em-folder-selection.h
+++ b/mail/em-folder-selection.h
@@ -1,41 +1,54 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* em-folder-selection.h - UI for selecting folders.
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
*
- * Copyright (C) 2002 Ximian, Inc.
+ * Copyright 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 free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * 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.
+ * 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.
+ * 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 Street #330, Boston, MA 02111-1307, USA.
*
- * Author: Ettore Perazzoli <ettore@ximian.com>
*/
+
#ifndef EM_FOLDER_SELECTION_H
#define EM_FOLDER_SELECTION_H
-#include <camel/camel-folder.h>
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
#include <gtk/gtkwindow.h>
+#include <camel/camel-folder.h>
CamelFolder *em_folder_selection_run_dialog (GtkWindow *parent_window,
const char *title,
const char *caption,
CamelFolder *default_folder);
-char *em_folder_selection_run_dialog_uri(GtkWindow *parent_window,
- const char *title,
- const char *caption,
- const char *default_folder_uri);
-void em_select_folder(GtkWindow *parent_window, const char *title, const char *text, const char *default_folder_uri, void (*done)(const char *uri, void *data), void *data);
+char *em_folder_selection_run_dialog_uri (GtkWindow *parent_window,
+ const char *title,
+ const char *caption,
+ const char *default_folder_uri);
+
+void em_select_folder (GtkWindow *parent_window, const char *title, const char *text,
+ const char *default_folder_uri,
+ void (*done)(const char *uri, void *data),
+ void *data);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
#endif /* EM_FOLDER_SELECTION_H */
diff --git a/mail/em-folder-selector.c b/mail/em-folder-selector.c
index 3ccf00e497..a670222c5e 100644
--- a/mail/em-folder-selector.c
+++ b/mail/em-folder-selector.c
@@ -1,33 +1,31 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
*
- * Copyright(C) 2000, 2001, 2002, 2003 Ximian, Inc.
+ * Copyright 2003 Ximian, Inc. (www.ximian.com)
*
- * Authors: Ettore Perazzoli
- * Michael Zucchi
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * 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.
*
- * 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 Street #330, Boston, MA 02111-1307, USA.
*
- * 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 "em-folder-selector.h"
-
-#include "shell/e-storage-set-view.h"
-#include "shell/e-storage-set.h"
+#include <string.h>
#include <libgnome/gnome-i18n.h>
@@ -44,306 +42,272 @@
#include <camel/camel-url.h>
-#include <string.h>
-
-#define PARENT_TYPE (gtk_dialog_get_type())
-static GtkDialogClass *parent_class = NULL;
-
-static gboolean
-check_folder_type_valid(EMFolderSelector *emfs)
-{
- const char *selected;
- EFolder *folder;
+#include "em-folder-tree.h"
+#include "em-folder-selector.h"
- selected = e_storage_set_view_get_current_folder(emfs->essv);
- if (selected == NULL)
- return FALSE;
+#define d(x) x
- folder = e_storage_set_get_folder(emfs->ess, selected);
- if (folder == NULL)
- return FALSE;
- return TRUE;
-}
+static void em_folder_selector_class_init (EMFolderSelectorClass *klass);
+static void em_folder_selector_init (EMFolderSelector *emfs);
+static void em_folder_selector_destroy (GtkObject *obj);
+static void em_folder_selector_finalize (GObject *obj);
+static void em_folder_selector_response (GtkDialog *dialog, int response);
-#if 0 /* EPFIXME */
-static void
-folder_creation_dialog_result_cb(EShell *shell,
- EShellFolderCreationDialogResult result,
- const char *path,
- void *data)
-{
- EMFolderSelector *dialog;
- dialog = EM_FOLDER_SELECTOR(data);
+static GtkDialogClass *parent_class = NULL;
- if (result == E_SHELL_FOLDER_CREATION_DIALOG_RESULT_SUCCESS)
- e_storage_set_view_set_current_folder(E_STORAGE_SET_VIEW(priv->storage_set_view),
- path);
-}
-#endif
-static void
-emfs_dispose(GObject *object)
+GType
+em_folder_selector_get_type (void)
{
- EMFolderSelector *emfs = (EMFolderSelector *)object;
-
- if (emfs->ess != NULL) {
- g_object_unref(emfs->ess);
- emfs->ess = NULL;
- emfs->essv = NULL;
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (EMFolderSelectorClass),
+ NULL, /* base_class_init */
+ NULL, /* base_class_finalize */
+ (GClassInitFunc) em_folder_selector_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (EMFolderSelector),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) em_folder_selector_init,
+ };
+
+ type = g_type_register_static (GTK_TYPE_DIALOG, "EMFolderSelector", &info, 0);
}
-
- (* G_OBJECT_CLASS(parent_class)->dispose)(object);
+
+ return type;
}
static void
-emfs_finalize(GObject *object)
+em_folder_selector_class_init (EMFolderSelectorClass *klass)
{
- /*EMFolderSelector *emfs = (EMFolderSelector *)object;*/
-
- (* G_OBJECT_CLASS(parent_class)->finalize)(object);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass);
+ GtkDialogClass *dialog_class = GTK_DIALOG_CLASS (klass);
+
+ parent_class = g_type_class_ref (GTK_TYPE_DIALOG);
+
+ object_class->finalize = em_folder_selector_finalize;
+ gtk_object_class->destroy = em_folder_selector_destroy;
+
+ dialog_class->response = em_folder_selector_response;
}
static void
-emfs_response(GtkDialog *dialog, int response)
+em_folder_selector_init (EMFolderSelector *emfs)
{
- EMFolderSelector *emfs = (EMFolderSelector *)dialog;
- const char *path;
-
- switch (response) {
- case EM_FOLDER_SELECTOR_RESPONSE_NEW:
- path = e_storage_set_view_get_current_folder(emfs->essv);
-
- printf("create new folder, default parent '%s'\n", path);
- break;
- }
+ emfs->selected_path = NULL;
+ emfs->selected_uri = NULL;
}
static void
-emfs_class_init(EMFolderSelectorClass *klass)
+em_folder_selector_destroy (GtkObject *obj)
{
- GObjectClass *object_class;
- GtkDialogClass *dialog_class;
-
- parent_class = g_type_class_ref(PARENT_TYPE);
- object_class = G_OBJECT_CLASS(klass);
- dialog_class = GTK_DIALOG_CLASS(klass);
-
- object_class->dispose = emfs_dispose;
- object_class->finalize = emfs_finalize;
-
- dialog_class->response = emfs_response;
+ GTK_OBJECT_CLASS (parent_class)->destroy (obj);
}
static void
-emfs_init(EMFolderSelector *emfs)
+em_folder_selector_finalize (GObject *obj)
{
- emfs->flags = 0;
+ EMFolderSelector *emfs = (EMFolderSelector *) obj;
+
+ g_free (emfs->selected_path);
+ g_free (emfs->selected_uri);
+
+ G_OBJECT_CLASS (parent_class)->finalize (obj);
}
static void
-folder_selected_cb(EStorageSetView *essv, const char *path, EMFolderSelector *emfs)
+em_folder_selector_response (GtkDialog *dialog, int response)
{
- if (check_folder_type_valid(emfs))
- gtk_dialog_set_response_sensitive(GTK_DIALOG(emfs), GTK_RESPONSE_OK, TRUE);
- else
- gtk_dialog_set_response_sensitive(GTK_DIALOG(emfs), GTK_RESPONSE_OK, FALSE);
+ EMFolderSelector *emfs = (EMFolderSelector *) dialog;
+
+ switch (response) {
+ case EM_FOLDER_SELECTOR_RESPONSE_NEW:
+ /* FIXME: implement me */
+ break;
+ }
}
+
+
static void
-double_click_cb(EStorageSetView *essv, int row, ETreePath path, int col, GdkEvent *event, EMFolderSelector *emfs)
+folder_selected_cb (EMFolderTree *emft, const char *path, const char *uri, EMFolderSelector *emfs)
{
- if (check_folder_type_valid(emfs)) {
- /*g_signal_emit(emfs, signals[FOLDER_SELECTED], 0,
- em_folder_selector_get_selected(emfs));*/
- printf("double clicked!\n");
- }
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (emfs), GTK_RESPONSE_OK, TRUE);
}
void
-em_folder_selector_construct(EMFolderSelector *emfs, EStorageSet *ess, guint32 flags, const char *title, const char *text)
+em_folder_selector_construct (EMFolderSelector *emfs, EMFolderTree *emft, guint32 flags, const char *title, const char *text)
{
GtkWidget *scrolled_window;
- GtkWidget *text_label;
-
- gtk_window_set_default_size(GTK_WINDOW(emfs), 350, 300);
- gtk_window_set_modal(GTK_WINDOW(emfs), TRUE);
- gtk_window_set_title(GTK_WINDOW(emfs), title);
- gtk_container_set_border_width(GTK_CONTAINER(emfs), 6);
-
+ GtkWidget *label;
+
+ gtk_window_set_default_size (GTK_WINDOW (emfs), 350, 300);
+ gtk_window_set_modal (GTK_WINDOW (emfs), TRUE);
+ gtk_window_set_title (GTK_WINDOW (emfs), title);
+ gtk_container_set_border_width (GTK_CONTAINER (emfs), 6);
+
+ gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (emfs)->vbox), 6);
+ gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (emfs)->vbox), 6);
+
emfs->flags = flags;
if (flags & EM_FOLDER_SELECTOR_CAN_CREATE)
- gtk_dialog_add_buttons(GTK_DIALOG(emfs), GTK_STOCK_NEW, EM_FOLDER_SELECTOR_RESPONSE_NEW, NULL);
-
- gtk_dialog_add_buttons(GTK_DIALOG(emfs),
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OK, GTK_RESPONSE_OK,
- NULL);
-
- gtk_dialog_set_response_sensitive(GTK_DIALOG(emfs), GTK_RESPONSE_OK, FALSE);
- gtk_dialog_set_default_response(GTK_DIALOG(emfs), GTK_RESPONSE_OK);
-
- emfs->ess = ess;
- g_object_ref(ess);
-
- emfs->essv = (EStorageSetView *)e_storage_set_create_new_view(ess, NULL);
- e_storage_set_view_set_allow_dnd(emfs->essv, FALSE);
- e_storage_set_view_enable_search(emfs->essv, TRUE);
-
- g_signal_connect(emfs->essv, "double_click", G_CALLBACK(double_click_cb), emfs);
- g_signal_connect(emfs->essv, "folder_selected", G_CALLBACK(folder_selected_cb), emfs);
-
- scrolled_window = gtk_scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), GTK_SHADOW_IN);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
+ gtk_dialog_add_buttons (GTK_DIALOG (emfs), GTK_STOCK_NEW, EM_FOLDER_SELECTOR_RESPONSE_NEW, NULL);
+
+ gtk_dialog_add_buttons (GTK_DIALOG (emfs), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
+
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (emfs), GTK_RESPONSE_OK, FALSE);
+ gtk_dialog_set_default_response (GTK_DIALOG (emfs), GTK_RESPONSE_OK);
+
+ emfs->emft = emft;
+ gtk_widget_show ((GtkWidget *) emfs->emft);
+
+ g_signal_connect (emfs->emft, "folder-selected", G_CALLBACK (folder_selected_cb), emfs);
+
+ scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-
- gtk_container_add(GTK_CONTAINER(scrolled_window), (GtkWidget *)emfs->essv);
-
- gtk_box_pack_end(GTK_BOX(GTK_DIALOG(emfs)->vbox), scrolled_window, TRUE, TRUE, 6);
- gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(emfs)->vbox), 6);
+ gtk_widget_show (scrolled_window);
- gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(emfs)->vbox), 6);
+ gtk_container_add (GTK_CONTAINER (scrolled_window), (GtkWidget *) emft);
+
+ gtk_box_pack_end (GTK_BOX (GTK_DIALOG (emfs)->vbox), scrolled_window, TRUE, TRUE, 6);
- gtk_widget_show((GtkWidget *)emfs->essv);
- gtk_widget_show(scrolled_window);
-
if (text != NULL) {
- text_label = gtk_label_new(text);
- gtk_label_set_justify(GTK_LABEL(text_label), GTK_JUSTIFY_LEFT);
- gtk_widget_show(text_label);
-
- gtk_box_pack_end(GTK_BOX(GTK_DIALOG(emfs)->vbox), text_label, FALSE, TRUE, 6);
- gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(emfs)->vbox), 6);
+ label = gtk_label_new (text);
+ gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
+ gtk_widget_show (label);
+
+ gtk_box_pack_end (GTK_BOX (GTK_DIALOG (emfs)->vbox), label, FALSE, TRUE, 6);
}
-
- GTK_WIDGET_SET_FLAGS((GtkWidget *)emfs->essv, GTK_CAN_FOCUS);
- gtk_widget_grab_focus((GtkWidget *)emfs->essv);
+
+ GTK_WIDGET_SET_FLAGS ((GtkWidget *) emfs->emft, GTK_CAN_FOCUS);
+ gtk_widget_grab_focus ((GtkWidget *) emfs->emft);
}
GtkWidget *
-em_folder_selector_new(EStorageSet *ess, guint32 flags, const char *title, const char *text)
+em_folder_selector_new (EMFolderTree *emft, guint32 flags, const char *title, const char *text)
{
EMFolderSelector *emfs;
-
- g_return_val_if_fail(E_IS_STORAGE_SET(ess), NULL);
-
- emfs = g_object_new(em_folder_selector_get_type(), NULL);
- em_folder_selector_construct(emfs, ess, flags, title, text);
-
- return GTK_WIDGET(emfs);
+
+ emfs = g_object_new (em_folder_selector_get_type (), NULL);
+ em_folder_selector_construct (emfs, emft, flags, title, text);
+
+ return (GtkWidget *) emfs;
}
static void
-emfs_create_name_changed(GtkEntry *entry, EMFolderSelector *emfs)
+emfs_create_name_changed (GtkEntry *entry, EMFolderSelector *emfs)
{
- int active;
-
- active = e_storage_set_view_get_current_folder(emfs->essv) != NULL
- && emfs->name_entry->text_length > 0;
-
- gtk_dialog_set_response_sensitive((GtkDialog *)emfs, GTK_RESPONSE_OK, active);
+ gboolean active;
+
+ /* FIXME: need to port this... */
+ active = /* folder does not exist && */ emfs->name_entry->text_length > 0;
+
+ gtk_dialog_set_response_sensitive ((GtkDialog *) emfs, GTK_RESPONSE_OK, active);
}
static void
-emfs_create_name_activate(GtkEntry *entry, EMFolderSelector *emfs)
+emfs_create_name_activate (GtkEntry *entry, EMFolderSelector *emfs)
{
- printf("entry activated, woop\n");
+ /* FIXME: create the folder... */
+ printf ("entry activated, woop\n");
}
GtkWidget *
-em_folder_selector_create_new(EStorageSet *ess, guint32 flags, const char *title, const char *text)
+em_folder_selector_create_new (EMFolderTree *emft, guint32 flags, const char *title, const char *text)
{
EMFolderSelector *emfs;
GtkWidget *hbox, *w;
-
- g_return_val_if_fail(E_IS_STORAGE_SET(ess), NULL);
-
- emfs = g_object_new(em_folder_selector_get_type(), NULL);
- em_folder_selector_construct(emfs, ess, flags, title, text);
-
- hbox = gtk_hbox_new(FALSE, 0);
- w = gtk_label_new_with_mnemonic(_("Folder _name"));
- gtk_box_pack_start((GtkBox *)hbox, w, FALSE, FALSE, 6);
- emfs->name_entry = (GtkEntry *)gtk_entry_new();
- g_signal_connect(emfs->name_entry, "changed", G_CALLBACK(emfs_create_name_changed), emfs);
- g_signal_connect(emfs->name_entry, "activate", G_CALLBACK(emfs_create_name_activate), emfs);
- gtk_box_pack_start((GtkBox *)hbox, (GtkWidget *)emfs->name_entry, TRUE, FALSE, 6);
- gtk_widget_show_all(hbox);
-
- gtk_box_pack_start((GtkBox *)((GtkDialog *)emfs)->vbox, hbox, FALSE, TRUE, 0);
-
- return GTK_WIDGET(emfs);
+
+ emfs = g_object_new (em_folder_selector_get_type (), NULL);
+ em_folder_selector_construct (emfs, emft, flags, title, text);
+
+ hbox = gtk_hbox_new (FALSE, 0);
+ w = gtk_label_new_with_mnemonic (_("Folder _name"));
+ gtk_box_pack_start ((GtkBox *) hbox, w, FALSE, FALSE, 6);
+ emfs->name_entry = (GtkEntry *) gtk_entry_new ();
+ g_signal_connect (emfs->name_entry, "changed", G_CALLBACK (emfs_create_name_changed), emfs);
+ g_signal_connect (emfs->name_entry, "activate", G_CALLBACK (emfs_create_name_activate), emfs);
+ gtk_box_pack_start ((GtkBox *) hbox, (GtkWidget *) emfs->name_entry, TRUE, FALSE, 6);
+ gtk_widget_show_all (hbox);
+
+ gtk_box_pack_start ((GtkBox *) ((GtkDialog *) emfs)->vbox, hbox, FALSE, TRUE, 0);
+
+ return (GtkWidget *) emfs;
}
-void
-em_folder_selector_set_selected(EMFolderSelector *emfs, const char *path)
-{
- e_storage_set_view_set_current_folder(emfs->essv, path);
-}
void
-em_folder_selector_set_selected_uri(EMFolderSelector *emfs, const char *uri)
+em_folder_selector_set_selected (EMFolderSelector *emfs, const char *uri)
{
- const char *path;
-
- path = e_storage_set_get_path_for_physical_uri(emfs->ess, uri);
- if (path)
- e_storage_set_view_set_current_folder(emfs->essv, path);
+ em_folder_tree_set_selected (emfs->emft, uri);
}
+
const char *
-em_folder_selector_get_selected(EMFolderSelector *emfs)
+em_folder_selector_get_selected_uri (EMFolderSelector *emfs)
{
- const char *path;
-
- path = e_storage_set_view_get_current_folder(emfs->essv);
- if (emfs->name_entry) {
- g_free(emfs->selected);
- emfs->selected = g_strdup_printf("%s/%s", path, gtk_entry_get_text(emfs->name_entry));
- path = emfs->selected;
+ const char *uri;
+
+ if (!(uri = em_folder_tree_get_selected_uri (emfs->emft))) {
+ d(printf ("no selected folder?\n"));
+ return NULL;
}
-
- return path;
+
+ if (uri && emfs->name_entry) {
+ CamelURL *url;
+ char *newpath;
+
+ url = camel_url_new (uri, NULL);
+ newpath = g_strdup_printf ("%s/%s", url->fragment ? url->fragment : url->path, gtk_entry_get_text (emfs->name_entry));
+ if (url->fragment)
+ camel_url_set_fragment (url, newpath);
+ else
+ camel_url_set_path (url, newpath);
+
+ g_free (emfs->selected_path);
+ emfs->selected_path = newpath;
+
+ g_free (emfs->selected_uri);
+ emfs->selected_uri = camel_url_to_string (url, 0);
+
+ camel_url_free (url);
+ uri = emfs->selected_uri;
+ }
+
+ return uri;
}
+
const char *
-em_folder_selector_get_selected_uri(EMFolderSelector *emfs)
+em_folder_selector_get_selected_path (EMFolderSelector *emfs)
{
const char *path;
- EFolder *folder;
-
- path = e_storage_set_view_get_current_folder(emfs->essv);
- if (path == NULL) {
- printf("current folder is null?\n");
- return NULL;
+
+ if (emfs->selected_path) {
+ /* already did the work in a previous call */
+ return emfs->selected_path;
}
-
- folder = e_storage_set_get_folder(emfs->ess, path);
- if (folder == NULL) {
- printf("path ok, but can't get folder?\n");
+
+ if (!(path = em_folder_tree_get_selected_path (emfs->emft))) {
+ d(printf ("no selected folder?\n"));
return NULL;
}
-
- path = e_folder_get_physical_uri(folder);
+
if (path && emfs->name_entry) {
- CamelURL *url;
char *newpath;
-
- url = camel_url_new(path, NULL);
- newpath = g_strdup_printf("%s/%s", url->fragment?url->fragment:url->path, gtk_entry_get_text(emfs->name_entry));
- if (url->fragment)
- camel_url_set_fragment(url, newpath);
- else
- camel_url_set_path(url, newpath);
- g_free(emfs->selected_uri);
- emfs->selected_uri = camel_url_to_string(url, 0);
- camel_url_free(url);
- path = emfs->selected_uri;
+
+ path = newpath = g_strdup_printf ("%s/%s", path, gtk_entry_get_text (emfs->name_entry));
+ emfs->selected_path = newpath;
}
-
+
return path;
}
-
-E_MAKE_TYPE(em_folder_selector, "EMFolderSelector", EMFolderSelector, emfs_class_init, emfs_init, PARENT_TYPE)
diff --git a/mail/em-folder-selector.h b/mail/em-folder-selector.h
index 48fc6758b5..76fb5888ff 100644
--- a/mail/em-folder-selector.h
+++ b/mail/em-folder-selector.h
@@ -1,27 +1,26 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-folder-selection-dialog.h
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
*
- * Copyright (C) 2000, 2001, 2002, 2003 Ximian, Inc.
+ * Copyright 2003 Ximian, Inc. (www.ximian.com)
*
- * Authors: Ettore Perazzoli
- * Michael Zucchi
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * 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.
*
- * 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.
+ * 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 Street #330, Boston, MA 02111-1307, USA.
*
*/
+
#ifndef EM_FOLDER_SELECTOR_H
#define EM_FOLDER_SELECTOR_H
@@ -42,29 +41,20 @@ typedef struct _EMFolderSelector EMFolderSelector;
typedef struct _EMFolderSelectorPrivate EMFolderSelectorPrivate;
typedef struct _EMFolderSelectorClass EMFolderSelectorClass;
-struct _EStorageSet;
-struct _EStorageSetView;
-
struct _EMFolderSelector {
GtkDialog parent;
-
+
guint32 flags;
- struct _EStorageSet *ess;
- struct _EStorageSetView *essv;
-
+ struct _EMFolderTree *emft;
+
struct _GtkEntry *name_entry;
- char *selected;
+ char *selected_path;
char *selected_uri;
};
struct _EMFolderSelectorClass {
GtkDialogClass parent_class;
-
-#if 0
- void (* folder_selected) (EMFolderSelector *folder_selection_dialog,
- const char *path);
- void (* cancelled) (EMFolderSelector *folder_selection_dialog);
-#endif
+
};
enum {
@@ -75,19 +65,21 @@ enum {
EM_FOLDER_SELECTOR_RESPONSE_NEW = 1,
};
-GtkType em_folder_selector_get_type (void);
-void em_folder_selector_construct(EMFolderSelector *, struct _EStorageSet *, guint32, const char *, const char *);
+
+GType em_folder_selector_get_type (void);
+
+void em_folder_selector_construct (EMFolderSelector *emfs, struct _EMFolderTree *emft, guint32 flags, const char *title, const char *text);
+
/* for selecting folders */
-GtkWidget *em_folder_selector_new (struct _EStorageSet *, guint32, const char *, const char *);
+GtkWidget *em_folder_selector_new (struct _EMFolderTree *emft, guint32 flags, const char *title, const char *text);
/* for creating folders */
-GtkWidget *em_folder_selector_create_new(struct _EStorageSet *ess, guint32 flags, const char *title, const char *text);
+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 *path);
-void em_folder_selector_set_selected_uri(EMFolderSelector *emfs, const char *uri);
+void em_folder_selector_set_selected (EMFolderSelector *emfs, const char *uri);
-const char *em_folder_selector_get_selected (EMFolderSelector *emfs);
-const char *em_folder_selector_get_selected_uri(EMFolderSelector *emfs);
+const char *em_folder_selector_get_selected_uri (EMFolderSelector *emfs);
+const char *em_folder_selector_get_selected_path (EMFolderSelector *emfs);
#ifdef cplusplus
}
diff --git a/mail/em-folder-tree-model.c b/mail/em-folder-tree-model.c
new file mode 100644
index 0000000000..786ac94d68
--- /dev/null
+++ b/mail/em-folder-tree-model.c
@@ -0,0 +1,284 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2003 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "em-marshal.h"
+#include "em-folder-tree-model.h"
+
+
+/* GObject virtual method overrides */
+static void em_folder_tree_model_class_init (EMFolderTreeModelClass *klass);
+static void em_folder_tree_model_init (EMFolderTreeModel *model);
+static void em_folder_tree_model_finalize (GObject *obj);
+
+/* interface init methods */
+static void tree_model_iface_init (GtkTreeModelIface *iface);
+static void tree_drag_dest_iface_init (GtkTreeDragDestIface *iface);
+static void tree_drag_source_iface_init (GtkTreeDragSourceIface *iface);
+
+/* drag & drop iface methods */
+static gboolean model_drag_data_received (GtkTreeDragDest *drag_dest,
+ GtkTreePath *dest_path,
+ GtkSelectionData *selection_data);
+static gboolean model_row_drop_possible (GtkTreeDragDest *drag_dest,
+ GtkTreePath *dest_path,
+ GtkSelectionData *selection_data);
+static gboolean model_row_draggable (GtkTreeDragSource *drag_source,
+ GtkTreePath *src_path);
+static gboolean model_drag_data_get (GtkTreeDragSource *drag_source,
+ GtkTreePath *src_path,
+ GtkSelectionData *selection_data);
+static gboolean model_drag_data_delete (GtkTreeDragSource *drag_source,
+ GtkTreePath *src_path);
+
+
+enum {
+ DRAG_DATA_RECEIVED,
+ ROW_DROP_POSSIBLE,
+ ROW_DRAGGABLE,
+ DRAG_DATA_GET,
+ DRAG_DATA_DELETE,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+
+static GtkTreeStore *parent_class = NULL;
+
+
+GType
+em_folder_tree_model_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (EMFolderTreeModelClass),
+ NULL, /* base_class_init */
+ NULL, /* base_class_finalize */
+ (GClassInitFunc) em_folder_tree_model_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (EMFolderTreeModel),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) em_folder_tree_model_init,
+ };
+ static const GInterfaceInfo tree_model_info = {
+ (GInterfaceInitFunc) tree_model_iface_init,
+ NULL,
+ NULL
+ };
+ static const GInterfaceInfo drag_dest_info = {
+ (GInterfaceInitFunc) tree_drag_dest_iface_init,
+ NULL,
+ NULL
+ };
+ static const GInterfaceInfo drag_source_info = {
+ (GInterfaceInitFunc) tree_drag_source_iface_init,
+ NULL,
+ NULL
+ };
+
+ type = g_type_register_static (GTK_TYPE_TREE_STORE, "EMFolderTreeModel", &info, 0);
+
+ g_type_add_interface_static (type, GTK_TYPE_TREE_MODEL,
+ &tree_model_info);
+ g_type_add_interface_static (type, GTK_TYPE_TREE_DRAG_DEST,
+ &drag_dest_info);
+ g_type_add_interface_static (type, GTK_TYPE_TREE_DRAG_SOURCE,
+ &drag_source_info);
+ }
+
+ return type;
+}
+
+
+static void
+em_folder_tree_model_class_init (EMFolderTreeModelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_ref (GTK_TYPE_TREE_STORE);
+
+ object_class->finalize = em_folder_tree_model_finalize;
+
+ /* signals */
+ signals[DRAG_DATA_RECEIVED] =
+ g_signal_new ("drag-data-received",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_NO_HOOKS,
+ G_STRUCT_OFFSET (EMFolderTreeModelClass, drag_data_received),
+ NULL, NULL,
+ em_marshal_BOOLEAN__POINTER_POINTER,
+ G_TYPE_BOOLEAN, 2,
+ G_TYPE_POINTER,
+ G_TYPE_POINTER);
+
+ signals[ROW_DROP_POSSIBLE] =
+ g_signal_new ("row-drop-possible",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_NO_HOOKS,
+ G_STRUCT_OFFSET (EMFolderTreeModelClass, row_drop_possible),
+ NULL, NULL,
+ em_marshal_BOOLEAN__POINTER_POINTER,
+ G_TYPE_BOOLEAN, 2,
+ G_TYPE_POINTER,
+ G_TYPE_POINTER);
+
+ signals[ROW_DRAGGABLE] =
+ g_signal_new ("row-draggable",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_NO_HOOKS,
+ G_STRUCT_OFFSET (EMFolderTreeModelClass, row_draggable),
+ NULL, NULL,
+ em_marshal_BOOLEAN__POINTER,
+ G_TYPE_BOOLEAN, 1,
+ G_TYPE_POINTER);
+
+ signals[DRAG_DATA_GET] =
+ g_signal_new ("drag-data-get",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_NO_HOOKS,
+ G_STRUCT_OFFSET (EMFolderTreeModelClass, drag_data_get),
+ NULL, NULL,
+ em_marshal_BOOLEAN__POINTER_POINTER,
+ G_TYPE_BOOLEAN, 2,
+ G_TYPE_POINTER,
+ G_TYPE_POINTER);
+
+ signals[DRAG_DATA_DELETE] =
+ g_signal_new ("drag-data-delete",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_NO_HOOKS,
+ G_STRUCT_OFFSET (EMFolderTreeModelClass, drag_data_delete),
+ NULL, NULL,
+ em_marshal_BOOLEAN__POINTER,
+ G_TYPE_BOOLEAN, 1,
+ G_TYPE_POINTER);
+}
+
+static void
+em_folder_tree_model_init (EMFolderTreeModel *model)
+{
+ ;
+}
+
+static void
+em_folder_tree_model_finalize (GObject *obj)
+{
+ G_OBJECT_CLASS (parent_class)->finalize (obj);
+}
+
+
+static void
+tree_model_iface_init (GtkTreeModelIface *iface)
+{
+ ;
+}
+
+static void
+tree_drag_dest_iface_init (GtkTreeDragDestIface *iface)
+{
+ iface->drag_data_received = model_drag_data_received;
+ iface->row_drop_possible = model_row_drop_possible;
+}
+
+static void
+tree_drag_source_iface_init (GtkTreeDragSourceIface *iface)
+{
+ iface->row_draggable = model_row_draggable;
+ iface->drag_data_get = model_drag_data_get;
+ iface->drag_data_delete = model_drag_data_delete;
+}
+
+
+static gboolean
+model_drag_data_received (GtkTreeDragDest *drag_dest, GtkTreePath *dest_path, GtkSelectionData *selection_data)
+{
+ EMFolderTreeModel *model = (EMFolderTreeModel *) drag_dest;
+ gboolean retval = FALSE;
+
+ g_signal_emit (model, signals[DRAG_DATA_RECEIVED], 0, &retval, dest_path, selection_data);
+
+ return retval;
+}
+
+static gboolean
+model_row_drop_possible (GtkTreeDragDest *drag_dest, GtkTreePath *dest_path, GtkSelectionData *selection_data)
+{
+ EMFolderTreeModel *model = (EMFolderTreeModel *) drag_dest;
+ gboolean retval = FALSE;
+
+ g_signal_emit (model, signals[ROW_DROP_POSSIBLE], 0, &retval, dest_path, selection_data);
+
+ return retval;
+}
+
+static gboolean
+model_row_draggable (GtkTreeDragSource *drag_source, GtkTreePath *src_path)
+{
+ EMFolderTreeModel *model = (EMFolderTreeModel *) drag_source;
+ gboolean retval = FALSE;
+
+ g_signal_emit (model, signals[ROW_DRAGGABLE], 0, &retval, src_path);
+
+ return retval;
+}
+
+static gboolean
+model_drag_data_get (GtkTreeDragSource *drag_source, GtkTreePath *src_path, GtkSelectionData *selection_data)
+{
+ EMFolderTreeModel *model = (EMFolderTreeModel *) drag_source;
+ gboolean retval = FALSE;
+
+ g_signal_emit (model, signals[DRAG_DATA_GET], 0, &retval, src_path, selection_data);
+
+ return retval;
+}
+
+static gboolean
+model_drag_data_delete (GtkTreeDragSource *drag_source, GtkTreePath *src_path)
+{
+ EMFolderTreeModel *model = (EMFolderTreeModel *) drag_source;
+ gboolean retval = FALSE;
+
+ g_signal_emit (model, signals[DRAG_DATA_DELETE], 0, &retval, src_path);
+
+ return retval;
+}
+
+
+EMFolderTreeModel *
+em_folder_tree_model_new (int n_columns, GType *types)
+{
+ EMFolderTreeModel *model;
+
+ model = g_object_new (EM_TYPE_FOLDER_TREE_MODEL, NULL);
+ gtk_tree_store_set_column_types ((GtkTreeStore *) model, n_columns, types);
+
+ return model;
+}
diff --git a/mail/em-folder-tree-model.h b/mail/em-folder-tree-model.h
new file mode 100644
index 0000000000..c52509ad63
--- /dev/null
+++ b/mail/em-folder-tree-model.h
@@ -0,0 +1,81 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2003 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef __EM_FOLDER_TREE_MODEL_H__
+#define __EM_FOLDER_TREE_MODEL_H__
+
+#include <gtk/gtktreednd.h>
+#include <gtk/gtktreestore.h>
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+#define EM_TYPE_FOLDER_TREE_MODEL (em_folder_tree_model_get_type ())
+#define EM_FOLDER_TREE_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EM_TYPE_FOLDER_TREE_MODEL, EMFolderTreeModel))
+#define EM_FOLDER_TREE_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EM_TYPE_FOLDER_TREE_MODEL, EMFolderTreeModelClass))
+#define EM_IS_FOLDER_TREE_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EM_TYPE_FOLDER_TREE_MODEL))
+#define EM_IS_FOLDER_TREE_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EM_TYPE_FOLDER_TREE_MODEL))
+#define EM_FOLDER_TREE_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EM_TYPE_FOLDER_TREE_MODEL, EMFolderTreeModelClass))
+
+typedef struct _EMFolderTreeModel EMFolderTreeModel;
+typedef struct _EMFolderTreeModelClass EMFolderTreeModelClass;
+
+struct _EMFolderTreeModel {
+ GtkTreeStore parent_object;
+
+};
+
+struct _EMFolderTreeModelClass {
+ GtkTreeStoreClass parent_class;
+
+ /* signals */
+ gboolean (* drag_data_received) (EMFolderTreeModel *model,
+ GtkTreePath *dest_path,
+ GtkSelectionData *selection_data);
+ gboolean (* row_drop_possible) (EMFolderTreeModel *model,
+ GtkTreePath *dest_path,
+ GtkSelectionData *selection_data);
+
+ gboolean (* row_draggable) (EMFolderTreeModel *model,
+ GtkTreePath *src_path);
+ gboolean (* drag_data_get) (EMFolderTreeModel *model,
+ GtkTreePath *src_path,
+ GtkSelectionData *selection_data);
+ gboolean (* drag_data_delete) (EMFolderTreeModel *model,
+ GtkTreePath *src_path);
+};
+
+
+GType em_folder_tree_model_get_type (void);
+
+
+EMFolderTreeModel *em_folder_tree_model_new (int n_columns, GType *types);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EM_FOLDER_TREE_MODEL_H__ */
diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c
index e6274abe37..49efb8a2ec 100644
--- a/mail/em-folder-tree.c
+++ b/mail/em-folder-tree.c
@@ -25,13 +25,41 @@
#include <config.h>
#endif
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
#include <gtk/gtk.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <camel/camel-session.h>
+#include <camel/camel-store.h>
+#include <camel/camel-folder.h>
+#include <camel/camel-stream-mem.h>
+
+#include "e-util/e-mktemp.h"
+#include "e-util/e-request.h"
+#include "e-util/e-dialog-utils.h"
+
+#include "mail-mt.h"
+#include "mail-ops.h"
+#include "mail-tools.h"
+
+#include "em-utils.h"
+#include "em-popup.h"
+#include "em-marshal.h"
#include "em-folder-tree.h"
+#include "em-folder-selector.h"
+#include "em-folder-selection.h"
+#define d(x) x
+
enum {
COL_STRING_DISPLAY_NAME, /* string that appears in the tree */
COL_POINTER_CAMEL_STORE, /* CamelStore object */
@@ -50,29 +78,94 @@ enum {
static GType col_types[] = {
G_TYPE_STRING, /* display name */
G_TYPE_POINTER, /* store object */
- G_TYPE_STRING, /* full_name */
+ G_TYPE_STRING, /* path */
G_TYPE_STRING, /* uri */
G_TYPE_UINT, /* unread count */
G_TYPE_BOOLEAN, /* is a store node */
G_TYPE_BOOLEAN, /* has not-yet-loaded subfolders */
};
+struct _emft_store_info {
+ CamelStore *store;
+ GtkTreeRowReference *row;
+ GHashTable *path_hash; /* maps CamelFolderInfo::path's to GtkTreeRowReferences */
+
+ char *display_name;
+
+ unsigned int created_id;
+ unsigned int deleted_id;
+ unsigned int renamed_id;
+ unsigned int subscribed_id;
+ unsigned int unsubscribed_id;
+};
+
struct _EMFolderTreePrivate {
GtkTreeView *treeview;
- GHashTable *store_hash; /* maps CamelStore's to GtkTreePath's */
+ GHashTable *store_hash; /* maps CamelStore's to store-info's */
+ GHashTable *uri_hash; /* maps URI's to GtkTreeRowReferences */
char *selected_uri;
+ char *selected_path;
+
+ /* dnd signal ids */
+ guint ddr, rdp, rd, ddg, ddd;
+};
+
+enum {
+ FOLDER_SELECTED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+
+#define MESSAGE_RFC822_TYPE "message/rfc822"
+#define TEXT_URI_LIST_TYPE "text/uri-list"
+#define UID_LIST_TYPE "x-uid-list"
+#define FOLDER_TYPE "x-folder"
+
+/* Drag & Drop types */
+enum DndDragType {
+ DND_DRAG_TYPE_FOLDER, /* drag an evo folder */
+ DND_DRAG_TYPE_TEXT_URI_LIST, /* drag to an mbox file */
};
+enum DndDropType {
+ DND_DROP_TYPE_UID_LIST, /* drop a list of message uids */
+ DND_DROP_TYPE_FOLDER, /* drop an evo folder */
+ DND_DROP_TYPE_MESSAGE_RFC822, /* drop a message/rfc822 stream */
+ DND_DROP_TYPE_TEXT_URI_LIST, /* drop an mbox file */
+};
+
+static GtkTargetEntry drag_types[] = {
+ { UID_LIST_TYPE, 0, DND_DRAG_TYPE_FOLDER },
+ { TEXT_URI_LIST_TYPE, 0, DND_DRAG_TYPE_TEXT_URI_LIST },
+};
+
+static const int num_drag_types = sizeof (drag_types) / sizeof (drag_types[0]);
+
+static GtkTargetEntry drop_types[] = {
+ { UID_LIST_TYPE, 0, DND_DROP_TYPE_UID_LIST },
+ { FOLDER_TYPE, 0, DND_DROP_TYPE_FOLDER },
+ { MESSAGE_RFC822_TYPE, 0, DND_DROP_TYPE_MESSAGE_RFC822 },
+ { TEXT_URI_LIST_TYPE, 0, DND_DROP_TYPE_TEXT_URI_LIST },
+};
+
+static const int num_drop_types = sizeof (drop_types) / sizeof (drop_types[0]);
+
+
+extern CamelSession *session;
+
+
static void em_folder_tree_class_init (EMFolderTreeClass *klass);
-static void em_folder_tree_init (EMFolderTree *tree);
+static void em_folder_tree_init (EMFolderTree *emft);
static void em_folder_tree_destroy (GtkObject *obj);
static void em_folder_tree_finalize (GObject *obj);
-static void tree_row_expanded (GtkTreeView *treeview, GtkTreeIter *root, GtkTreePath *path, EMFolderTree *ftree);
-static gboolean tree_button_press (GtkWidget *treeview, GdkEventButton *event, EMFolderTree *ftree);
-static void tree_selection_changed (GtkTreeSelection *selection, EMFolderTree *ftree);
+static void tree_row_expanded (GtkTreeView *treeview, GtkTreeIter *root, GtkTreePath *path, EMFolderTree *emft);
+static gboolean tree_button_press (GtkWidget *treeview, GdkEventButton *event, EMFolderTree *emft);
+static void tree_selection_changed (GtkTreeSelection *selection, EMFolderTree *emft);
static GtkVBoxClass *parent_class = NULL;
@@ -113,7 +206,16 @@ em_folder_tree_class_init (EMFolderTreeClass *klass)
object_class->finalize = em_folder_tree_finalize;
gtk_object_class->destroy = em_folder_tree_destroy;
- /* FIXME: init signals */
+ signals[FOLDER_SELECTED] =
+ g_signal_new ("folder-selected",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (EMFolderTreeClass, folder_selected),
+ NULL, NULL,
+ em_marshal_VOID__STRING_STRING,
+ G_TYPE_NONE, 2,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
}
@@ -144,8 +246,7 @@ enum {
FOLDER_ICON_NORMAL,
FOLDER_ICON_INBOX,
FOLDER_ICON_OUTBOX,
- FOLDER_ICON_TRASH,
- FOLDER_ICON_JUNK
+ FOLDER_ICON_TRASH
};
static GdkPixbuf *folder_icons[4];
@@ -160,31 +261,28 @@ render_pixbuf (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
char *path;
if (!initialised) {
- folder_icons[0] = gdk_pixbuf_load_from_file (EVOLUTION_ICONSDIR "/folder-mini.png");
- folder_icons[1] = gdk_pixbuf_load_from_file (EVOLUTION_ICONSDIR "/inbox-mini.png");
- folder_icons[2] = gdk_pixbuf_load_from_file (EVOLUTION_ICONSDIR "/outbox-mini.png");
- folder_icons[3] = gdk_pixbuf_load_from_file (EVOLUTION_ICONSDIR "/evolution-trash-mini.png");
- folder_icons[4] = gdk_pixbuf_load_from_file (EVOLUTION_ICONSDIR "/evolution-junk-mini.png");
+ folder_icons[0] = gdk_pixbuf_new_from_file (EVOLUTION_ICONSDIR "/folder-mini.png", NULL);
+ folder_icons[1] = gdk_pixbuf_new_from_file (EVOLUTION_ICONSDIR "/inbox-mini.png", NULL);
+ folder_icons[2] = gdk_pixbuf_new_from_file (EVOLUTION_ICONSDIR "/outbox-mini.png", NULL);
+ folder_icons[3] = gdk_pixbuf_new_from_file (EVOLUTION_ICONSDIR "/evolution-trash-mini.png", NULL);
initialised = TRUE;
}
gtk_tree_model_get (model, iter, COL_STRING_FOLDER_PATH, &path,
- COL_BOO_IS_STORE, &is_store, -1);
+ COL_BOOL_IS_STORE, &is_store, -1);
- if (!is_store) {
- if (!strcasecmp (name, "/Inbox"))
+ if (!is_store && path != NULL) {
+ if (!strcasecmp (path, "/Inbox"))
pixbuf = folder_icons[FOLDER_ICON_INBOX];
- else if (!strcasecmp (name, "/Outbox"))
+ else if (!strcasecmp (path, "/Outbox"))
pixbuf = folder_icons[FOLDER_ICON_OUTBOX];
- else if (!strcasecmp (name, "/Trash"))
+ else if (!strcasecmp (path, "/Trash"))
pixbuf = folder_icons[FOLDER_ICON_TRASH];
- else if (!strcasecmp (name, "/Junk"))
- pixbuf = folder_icons[FOLDER_ICON_JUNK];
else
pixbuf = folder_icons[FOLDER_ICON_NORMAL];
}
- g_object_set (renderer, "pixbuf", pixbuf, -1);
+ g_object_set (renderer, "pixbuf", pixbuf, NULL);
}
static void
@@ -193,10 +291,11 @@ render_display_name (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
{
gboolean is_store, bold;
unsigned int unread;
+ char *display;
char *name;
gtk_tree_model_get (model, iter, COL_STRING_DISPLAY_NAME, &name,
- COL_BOO_IS_STORE, &is_store,
+ COL_BOOL_IS_STORE, &is_store,
COL_UINT_UNREAD, &unread, -1);
if (!(bold = is_store || unread)) {
@@ -204,22 +303,131 @@ render_display_name (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
bold = subdirs_contain_unread (model, iter);
}
- g_object_set (renderer, "text", name,
+ if (!is_store && unread)
+ display = g_strdup_printf ("%s (%u)", name, unread);
+ else
+ display = g_strdup (name);
+
+ g_object_set (renderer, "text", display,
"weight", bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL,
"foreground_set", unread ? TRUE : FALSE,
"foreground", unread ? "#0000ff" : "#000000", NULL);
+
+ g_free (display);
+}
+
+static void
+em_folder_tree_init (EMFolderTree *emft)
+{
+ struct _EMFolderTreePrivate *priv;
+
+ priv = g_new0 (struct _EMFolderTreePrivate, 1);
+ priv->store_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+ priv->uri_hash = g_hash_table_new (g_str_hash, g_str_equal);
+ priv->selected_uri = NULL;
+ priv->selected_path = NULL;
+ priv->treeview = NULL;
+ emft->priv = priv;
+}
+
+static void
+path_hash_free (gpointer key, gpointer value, gpointer user_data)
+{
+ g_free (key);
+ gtk_tree_row_reference_free (value);
+}
+
+static void
+store_info_free (struct _emft_store_info *si)
+{
+ camel_object_remove_event (si->store, si->created_id);
+ camel_object_remove_event (si->store, si->deleted_id);
+ camel_object_remove_event (si->store, si->renamed_id);
+ camel_object_remove_event (si->store, si->subscribed_id);
+ camel_object_remove_event (si->store, si->unsubscribed_id);
+
+ g_free (si->display_name);
+ camel_object_unref (si->store);
+ gtk_tree_row_reference_free (si->row);
+ g_hash_table_foreach (si->path_hash, path_hash_free, NULL);
+ g_free (si);
+}
+
+static void
+store_hash_free (gpointer key, gpointer value, gpointer user_data)
+{
+ struct _emft_store_info *si = value;
+
+ store_info_free (si);
+}
+
+static void
+uri_hash_free (gpointer key, gpointer value, gpointer user_data)
+{
+ g_free (key);
+ gtk_tree_row_reference_free (value);
+}
+
+static void
+em_folder_tree_finalize (GObject *obj)
+{
+ EMFolderTree *emft = (EMFolderTree *) obj;
+
+ g_hash_table_foreach (emft->priv->store_hash, store_hash_free, NULL);
+ g_hash_table_destroy (emft->priv->store_hash);
+
+ g_hash_table_foreach (emft->priv->uri_hash, uri_hash_free, NULL);
+ g_hash_table_destroy (emft->priv->uri_hash);
+
+ g_free (emft->priv->selected_uri);
+ g_free (emft->priv->selected_path);
+ g_free (emft->priv);
+
+ G_OBJECT_CLASS (parent_class)->finalize (obj);
}
+static void
+em_folder_tree_destroy (GtkObject *obj)
+{
+ struct _EMFolderTreePrivate *priv = ((EMFolderTree *) obj)->priv;
+
+ if (priv->ddr != 0) {
+ g_signal_handler_disconnect (obj, priv->ddr);
+ priv->ddr = 0;
+ }
+
+ if (priv->rdp != 0) {
+ g_signal_handler_disconnect (obj, priv->rdp);
+ priv->rdp = 0;
+ }
+
+ if (priv->rd != 0) {
+ g_signal_handler_disconnect (obj, priv->rd);
+ priv->rd = 0;
+ }
+
+ if (priv->ddg != 0) {
+ g_signal_handler_disconnect (obj, priv->ddg);
+ priv->ddg = 0;
+ }
+
+ if (priv->ddd != 0) {
+ g_signal_handler_disconnect (obj, priv->ddd);
+ priv->ddd = 0;
+ }
+
+ GTK_OBJECT_CLASS (parent_class)->destroy (obj);
+}
+
+
static GtkTreeView *
-folder_tree_new (void)
+folder_tree_new (EMFolderTreeModel *model)
{
GtkTreeSelection *selection;
GtkTreeViewColumn *column;
GtkCellRenderer *renderer;
- GtkTreeStore *model;
GtkWidget *tree;
- model = gtk_tree_store_newv (COL_LAST, col_types);
tree = gtk_tree_view_new_with_model ((GtkTreeModel *) model);
column = gtk_tree_view_column_new ();
@@ -244,126 +452,578 @@ folder_tree_new (void)
}
static void
-em_folder_tree_init (EMFolderTree *tree)
+em_folder_tree_construct (EMFolderTree *emft, EMFolderTreeModel *model)
{
- struct _EMFolderTreePrivate *priv;
+ struct _EMFolderTreePrivate *priv = emft->priv;
GtkTreeSelection *selection;
GtkWidget *scrolled;
- priv = g_new (struct _EMFolderTreePrivate, 1);
- priv->store_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
- priv->uri_hash = g_hash_table_new (g_str_hash, g_str_equal);
- priv->selected_uri = NULL;
-
scrolled = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), GTK_SHADOW_IN);
- priv->treeview = folder_tree_new ();
+ priv->treeview = folder_tree_new (model);
gtk_widget_show ((GtkWidget *) priv->treeview);
- g_signal_connect (priv->treeview, "row-expanded", G_CALLBACK (tree_row_expanded), tree);
- g_signal_connect (priv->treeview, "button-press-event", G_CALLBACK (tree_button_press), tree);
+ g_signal_connect (priv->treeview, "row-expanded", G_CALLBACK (tree_row_expanded), emft);
+ g_signal_connect (priv->treeview, "button-press-event", G_CALLBACK (tree_button_press), emft);
selection = gtk_tree_view_get_selection ((GtkTreeView *) priv->treeview);
- g_signal_connect (selection, "changed", G_CALLBACK (tree_selection_changed), tree);
+ g_signal_connect (selection, "changed", G_CALLBACK (tree_selection_changed), emft);
gtk_container_add ((GtkContainer *) scrolled, (GtkWidget *) priv->treeview);
gtk_widget_show (scrolled);
- gtk_box_pack_start ((GtkBox *) tree, scrolled, TRUE, TRUE, 0);
+ gtk_box_pack_start ((GtkBox *) emft, scrolled, TRUE, TRUE, 0);
}
+
+
static void
-store_hash_free (gpointer key, gpointer value, gpointer user_data)
+drop_uid_list (EMFolderTree *emft, CamelFolder *dest, gboolean move, GtkSelectionData *selection, CamelException *ex)
{
- gtk_tree_path_free (value);
- camel_object_unref (key);
+ CamelFolder *src;
+ GPtrArray *uids;
+ char *src_uri;
+
+ em_utils_selection_get_uidlist (selection, &src_uri, &uids);
+
+ if (!(src = mail_tool_uri_to_folder (src_uri, 0, ex))) {
+ em_utils_uids_free (uids);
+ g_free (src_uri);
+ return;
+ }
+
+ g_free (src_uri);
+
+ camel_folder_transfer_messages_to (src, uids, dest, NULL, move, ex);
+ em_utils_uids_free (uids);
+ camel_object_unref (src);
}
static void
-em_folder_tree_finalize (GObject *obj)
+drop_folder (EMFolderTree *emft, CamelFolder *dest, gboolean move, GtkSelectionData *selection, CamelException *ex)
{
- EMFolderTree *tree = (EMFolderTree *) obj;
+ CamelFolder *src;
- g_hash_table_foreach (tree->priv->store_hash, store_hash_free, NULL);
- g_hash_table_destroy (tree->priv->store_hash);
+ /* get the folder being dragged */
+ if (!(src = mail_tool_uri_to_folder (selection->data, 0, ex)))
+ return;
- g_free (tree->priv->selected_uri);
- g_free (tree->priv);
+ if (src->parent_store == dest->parent_store && move) {
+ /* simple rename() action */
+ char *old_name, *new_name;
+
+ old_name = g_strdup (src->full_name);
+ new_name = g_strdup_printf ("%s/%s", dest->full_name, src->name);
+
+ camel_store_rename_folder (dest->parent_store, old_name, new_name, ex);
+
+ g_free (old_name);
+ g_free (new_name);
+ } else {
+ /* copy the folder to the new location */
+ CamelFolder *folder;
+ char *path;
+
+ path = g_strdup_printf ("%s/%s", dest->full_name, src->name);
+ if ((folder = camel_store_get_folder (dest->parent_store, path, CAMEL_STORE_FOLDER_CREATE, ex))) {
+ GPtrArray *uids;
+
+ uids = camel_folder_get_uids (src);
+ camel_folder_transfer_messages_to (src, uids, folder, NULL, FALSE, ex);
+ camel_folder_free_uids (src, uids);
+
+ camel_object_unref (folder);
+ }
+
+ g_free (path);
+ }
- G_OBJECT_CLASS (parent_class)->finalize (obj);
+ camel_object_unref (src);
+}
+
+static gboolean
+import_message_rfc822 (CamelFolder *dest, CamelStream *stream, gboolean scan_from, CamelException *ex)
+{
+ CamelMimeParser *mp;
+
+ mp = camel_mime_parser_new ();
+ camel_mime_parser_scan_from (mp, scan_from);
+ camel_mime_parser_init_with_stream (mp, stream);
+
+ while (camel_mime_parser_step (mp, 0, 0) == CAMEL_MIME_PARSER_STATE_FROM) {
+ CamelMessageInfo *info;
+ CamelMimeMessage *msg;
+
+ msg = camel_mime_message_new ();
+ if (camel_mime_part_construct_from_parser (CAMEL_MIME_PART (msg), mp) == -1) {
+ camel_object_unref (msg);
+ camel_object_unref (mp);
+ return FALSE;
+ }
+
+ /* append the message to the folder... */
+ info = g_new0 (CamelMessageInfo, 1);
+ camel_folder_append_message (dest, msg, info, NULL, ex);
+ camel_object_unref (msg);
+
+ if (camel_exception_is_set (ex)) {
+ camel_object_unref (mp);
+ return FALSE;
+ }
+
+ /* skip over the FROM_END state */
+ camel_mime_parser_step (mp, 0, 0);
+ }
+
+ camel_object_unref (mp);
+
+ return TRUE;
}
static void
-em_folder_tree_destroy (GtkObject *obj)
+drop_message_rfc822 (EMFolderTree *emft, CamelFolder *dest, GtkSelectionData *selection, CamelException *ex)
{
- GTK_OBJECT_CLASS (parent_class)->destroy (obj);
+ CamelStream *stream;
+ gboolean scan_from;
+
+ scan_from = selection->length > 5 && !strncmp (selection->data, "From ", 5);
+ stream = camel_stream_mem_new_with_buffer (selection->data, selection->length);
+
+ import_message_rfc822 (dest, stream, scan_from, ex);
+
+ camel_object_unref (stream);
+}
+
+static void
+drop_text_uri_list (EMFolderTree *emft, CamelFolder *dest, GtkSelectionData *selection, CamelException *ex)
+{
+ char **urls, *url, *tmp;
+ CamelStream *stream;
+ CamelURL *uri;
+ int fd, i;
+
+ tmp = g_strndup (selection->data, selection->length);
+ urls = g_strsplit (tmp, "\n", 0);
+ g_free (tmp);
+
+ for (i = 0; urls[i] != NULL; i++) {
+ /* get the path component */
+ url = g_strstrip (urls[i]);
+ uri = camel_url_new (url, NULL);
+ g_free (url);
+
+ if (!uri || strcmp (uri->protocol, "file") != 0) {
+ camel_url_free (uri);
+ continue;
+ }
+
+ url = uri->path;
+ uri->path = NULL;
+ camel_url_free (uri);
+
+ if ((fd = open (url, O_RDONLY)) == -1) {
+ g_free (url);
+ continue;
+ }
+
+ stream = camel_stream_fs_new_with_fd (fd);
+ if (!import_message_rfc822 (dest, stream, TRUE, ex)) {
+ /* FIXME: should we abort now? or continue? */
+ /* for now lets just continue... */
+ camel_exception_clear (ex);
+ }
+
+ camel_object_unref (stream);
+ g_free (url);
+ }
+
+ g_free (urls);
+}
+
+static gboolean
+drag_data_received_cb (EMFolderTreeModel *model, GtkTreePath *dest_path, GtkSelectionData *selection, EMFolderTree *emft)
+{
+ CamelFolder *folder;
+ CamelStore *store;
+ CamelException ex;
+ GtkTreeIter iter;
+ char *path;
+
+ /* this means we are receiving no data */
+ if (!selection->data || selection->length == -1)
+ return FALSE;
+
+ gtk_tree_model_get_iter ((GtkTreeModel *) model, &iter, dest_path);
+ gtk_tree_model_get ((GtkTreeModel *) model, &iter,
+ COL_POINTER_CAMEL_STORE, &store,
+ COL_STRING_FOLDER_PATH, &path, -1);
+
+ camel_exception_init (&ex);
+ if ((folder = camel_store_get_folder (store, path, 0, &ex))) {
+ /* FIXME: would have been nicer if we could 'move'
+ * messages and/or folders. but alas, gtktreeview
+ * drag&drop sucks ass and doesn't give us the
+ * context->action to check for GDK_ACTION_MOVE, so we
+ * can't. Yay. */
+ gboolean move = FALSE;
+
+ if (selection->target == gdk_atom_intern ("x-uid-list", FALSE)) {
+ /* import a list of uids from another evo folder */
+ drop_uid_list (emft, folder, move, selection, &ex);
+ d(printf ("* dropped a x-uid-list\n"));
+ } else if (selection->target == gdk_atom_intern ("x-folder", FALSE)) {
+ /* copy or move (aka rename) a folder */
+ drop_folder (emft, folder, move, selection, &ex);
+ d(printf ("* dropped a x-folder\n"));
+ } else if (selection->target == gdk_atom_intern ("message/rfc822", FALSE)) {
+ /* import a message/rfc822 stream */
+ drop_message_rfc822 (emft, folder, selection, &ex);
+ d(printf ("* dropped a message/rfc822\n"));
+ } else if (selection->target == gdk_atom_intern ("text/uri-list", FALSE)) {
+ /* import an mbox, maildir, or mh folder? */
+ drop_text_uri_list (emft, folder, selection, &ex);
+ d(printf ("* dropped a text/uri-list\n"));
+ } else {
+ g_assert_not_reached ();
+ }
+ }
+
+ if (camel_exception_is_set (&ex)) {
+ /* FIXME: error dialog? */
+ camel_exception_clear (&ex);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+row_drop_possible_cb (EMFolderTreeModel *model, GtkTreePath *dest_path, GtkSelectionData *selection, EMFolderTree *emft)
+{
+ GtkTreeIter iter;
+ gboolean is_store;
+
+ gtk_tree_model_get_iter ((GtkTreeModel *) model, &iter, dest_path);
+ gtk_tree_model_get ((GtkTreeModel *) model, &iter, COL_BOOL_IS_STORE, &is_store, -1);
+
+ if (selection->target == gdk_atom_intern ("x-uid-list", FALSE)) {
+ if (is_store)
+ return FALSE;
+
+ return TRUE;
+ } else if (selection->target == gdk_atom_intern ("x-folder", FALSE)) {
+ return TRUE;
+ } else if (selection->target == gdk_atom_intern ("message/rfc822", FALSE)) {
+ if (is_store)
+ return FALSE;
+
+ return TRUE;
+ } else if (selection->target == gdk_atom_intern ("text/uri-list", FALSE)) {
+ if (is_store)
+ return FALSE;
+
+ return TRUE;
+ } else {
+ g_assert_not_reached ();
+ return FALSE;
+ }
+}
+
+static gboolean
+row_draggable_cb (EMFolderTreeModel *model, GtkTreePath *src_path, EMFolderTree *emft)
+{
+ GtkTreeIter iter;
+ gboolean is_store;
+
+ gtk_tree_model_get_iter ((GtkTreeModel *) model, &iter, src_path);
+ gtk_tree_model_get ((GtkTreeModel *) model, &iter, COL_BOOL_IS_STORE, &is_store, -1);
+
+ return !is_store;
+}
+
+static void
+drag_text_uri_list (EMFolderTree *emft, CamelFolder *src, GtkSelectionData *selection, CamelException *ex)
+{
+ CamelFolder *dest;
+ const char *tmpdir;
+ CamelStore *store;
+ GPtrArray *uids;
+ char *url;
+
+ if (!(tmpdir = e_mkdtemp ("drag-n-drop-XXXXXX"))) {
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+ _("Could not create temporary directory: %s"),
+ g_strerror (errno));
+ return;
+ }
+
+ url = g_strdup_printf ("mbox:%s", tmpdir);
+ if (!(store = camel_session_get_store (session, url, ex))) {
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+ _("Could not create temporary mbox store: %s"),
+ camel_exception_get_description (ex));
+ g_free (url);
+
+ return;
+ }
+
+ if (!(dest = camel_store_get_folder (store, "mbox", CAMEL_STORE_FOLDER_CREATE, ex))) {
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+ _("Could not create temporary mbox folder: %s"),
+ camel_exception_get_description (ex));
+
+ camel_object_unref (store);
+ g_free (url);
+
+ return;
+ }
+
+ camel_object_unref (store);
+ uids = camel_folder_get_uids (src);
+
+ camel_folder_transfer_messages_to (src, uids, dest, NULL, FALSE, ex);
+ if (camel_exception_is_set (ex)) {
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+ _("Could not copy messages to temporary mbox folder: %s"),
+ camel_exception_get_description (ex));
+ } else {
+ memcpy (url, "file", 4);
+ gtk_selection_data_set (selection, selection->target, 8, url, strlen (url));
+ }
+
+ camel_folder_free_uids (src, uids);
+ camel_object_unref (dest);
+ g_free (url);
+}
+
+static gboolean
+drag_data_get_cb (EMFolderTreeModel *model, GtkTreePath *src_path, GtkSelectionData *selection, EMFolderTree *emft)
+{
+ CamelFolder *folder;
+ CamelStore *store;
+ CamelException ex;
+ GtkTreeIter iter;
+ char *path, *uri;
+
+ gtk_tree_model_get_iter ((GtkTreeModel *) model, &iter, src_path);
+ gtk_tree_model_get ((GtkTreeModel *) model, &iter,
+ COL_POINTER_CAMEL_STORE, &store,
+ COL_STRING_FOLDER_PATH, &path,
+ COL_STRING_URI, &uri, -1);
+
+ camel_exception_init (&ex);
+
+ if (selection->target == gdk_atom_intern ("x-folder", FALSE)) {
+ /* dragging to a new location in the folder tree */
+ gtk_selection_data_set (selection, selection->target, 8, uri, strlen (uri) + 1);
+ } else if (selection->target == gdk_atom_intern ("text/uri-list", FALSE)) {
+ /* dragging to nautilus or something, probably */
+ if ((folder = camel_store_get_folder (store, path, 0, &ex))) {
+ drag_text_uri_list (emft, folder, selection, &ex);
+ camel_object_unref (folder);
+ }
+ } else {
+ g_assert_not_reached ();
+ }
+
+ if (camel_exception_is_set (&ex)) {
+ /* FIXME: error dialog? */
+ camel_exception_clear (&ex);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+drag_data_delete_cb (EMFolderTreeModel *model, GtkTreePath *src_path, EMFolderTree *emft)
+{
+ gboolean is_store;
+ CamelStore *store;
+ CamelException ex;
+ GtkTreeIter iter;
+ char *path;
+
+ gtk_tree_model_get_iter ((GtkTreeModel *) model, &iter, src_path);
+ gtk_tree_model_get ((GtkTreeModel *) model, &iter,
+ COL_POINTER_CAMEL_STORE, &store,
+ COL_STRING_FOLDER_PATH, &path,
+ COL_BOOL_IS_STORE, &is_store, -1);
+
+ if (is_store)
+ return FALSE;
+
+ camel_exception_init (&ex);
+ camel_store_delete_folder (store, path, &ex);
+ if (camel_exception_is_set (&ex)) {
+ /* FIXME: error dialog? */
+ camel_exception_clear (&ex);
+ return FALSE;
+ }
+
+ return TRUE;
}
GtkWidget *
em_folder_tree_new (void)
{
- return g_object_new (EM_TYPE_FOLDER_TREE, NULL);
+ struct _EMFolderTreePrivate *priv;
+ EMFolderTreeModel *model;
+ EMFolderTree *emft;
+
+ model = em_folder_tree_model_new (COL_LAST, col_types);
+ emft = (EMFolderTree *) em_folder_tree_new_with_model (model);
+
+ priv = emft->priv;
+ priv->ddr = g_signal_connect (model, "drag-data-received", G_CALLBACK (drag_data_received_cb), emft);
+ priv->rdp = g_signal_connect (model, "row-drop-possible", G_CALLBACK (row_drop_possible_cb), emft);
+ priv->rd = g_signal_connect (model, "row-draggable", G_CALLBACK (row_draggable_cb), emft);
+ priv->ddg = g_signal_connect (model, "drag-data-get", G_CALLBACK (drag_data_get_cb), emft);
+ priv->ddd = g_signal_connect (model, "drag-data-delete", G_CALLBACK (drag_data_delete_cb), emft);
+
+ gtk_drag_source_set ((GtkWidget *) emft, 0, drag_types, num_drag_types, GDK_ACTION_COPY | GDK_ACTION_MOVE);
+ gtk_drag_dest_set ((GtkWidget *) emft, GTK_DEST_DEFAULT_ALL, drop_types, num_drop_types, GDK_ACTION_COPY | GDK_ACTION_MOVE);
+
+ return (GtkWidget *) emft;
+}
+
+
+GtkWidget *
+em_folder_tree_new_with_model (EMFolderTreeModel *model)
+{
+ EMFolderTree *emft;
+
+ emft = g_object_new (EM_TYPE_FOLDER_TREE, NULL);
+ em_folder_tree_construct (emft, model);
+
+ return (GtkWidget *) emft;
}
static void
-tree_row_expanded (GtkTreeView *treeview, GtkTreeIter *root, GtkTreePath *path, EMFolderTree *ftree)
+tree_store_set_folder_info (GtkTreeStore *model, GtkTreeIter *iter,
+ struct _EMFolderTreePrivate *priv,
+ struct _emft_store_info *si,
+ CamelFolderInfo *fi)
{
+ GtkTreeRowReference *uri_row, *path_row;
+ unsigned int unread;
+ GtkTreePath *path;
+ GtkTreeIter sub;
+ gboolean load;
+
+ load = (fi->flags & CAMEL_FOLDER_CHILDREN) && !(fi->flags & CAMEL_FOLDER_NOINFERIORS);
+
+ path = gtk_tree_model_get_path ((GtkTreeModel *) model, iter);
+ uri_row = gtk_tree_row_reference_new ((GtkTreeModel *) model, path);
+ path_row = gtk_tree_row_reference_copy (uri_row);
+ gtk_tree_path_free (path);
+
+ g_hash_table_insert (priv->uri_hash, g_strdup (fi->url), uri_row);
+ g_hash_table_insert (si->path_hash, g_strdup (fi->path), path_row);
+
+ unread = fi->unread_message_count == -1 ? 0 : fi->unread_message_count;
+
+ gtk_tree_store_set (model, iter,
+ COL_STRING_DISPLAY_NAME, fi->name,
+ COL_POINTER_CAMEL_STORE, si->store,
+ COL_STRING_FOLDER_PATH, fi->path,
+ COL_STRING_URI, fi->url,
+ COL_UINT_UNREAD, unread,
+ COL_BOOL_IS_STORE, FALSE,
+ COL_BOOL_LOAD_SUBDIRS, load,
+ -1);
+
+ if (load) {
+ /* create a placeholder node for our subfolders... */
+ gtk_tree_store_append (model, &sub, iter);
+ gtk_tree_store_set (model, &sub,
+ COL_STRING_DISPLAY_NAME, _("Loading..."),
+ COL_POINTER_CAMEL_STORE, si->store,
+ COL_STRING_FOLDER_PATH, fi->path,
+ COL_BOOL_LOAD_SUBDIRS, TRUE,
+ COL_BOOL_IS_STORE, FALSE,
+ COL_STRING_URI, fi->url,
+ COL_UINT_UNREAD, 0,
+ -1);
+ }
+}
+
+static void
+tree_row_expanded (GtkTreeView *treeview, GtkTreeIter *root, GtkTreePath *tree_path, EMFolderTree *emft)
+{
+ /* FIXME: might be best to call get_folder_info in another thread and add the nodes to the treeview in the callback? */
+ struct _EMFolderTreePrivate *priv = emft->priv;
+ struct _emft_store_info *si;
CamelFolderInfo *fi, *child;
CamelStore *store;
+ CamelException ex;
GtkTreeStore *model;
GtkTreeIter iter;
- char *full_name;
gboolean load;
+ char *path;
+ char *top;
model = (GtkTreeStore *) gtk_tree_view_get_model (treeview);
gtk_tree_model_get ((GtkTreeModel *) model, root,
- COL_STRING_FOLDER_NAME, &full_name,
+ COL_STRING_FOLDER_PATH, &path,
COL_POINTER_CAMEL_STORE, &store,
COL_BOOL_LOAD_SUBDIRS, &load,
-1);
if (!load)
return;
+ if (!(si = g_hash_table_lookup (emft->priv->store_hash, store))) {
+ g_assert_not_reached ();
+ return;
+ }
+
/* get the first child (which will be a dummy if we haven't loaded the child folders yet) */
gtk_tree_model_iter_children ((GtkTreeModel *) model, &iter, root);
+ /* FIXME: this sucks ass, need to fix camel so that using path as @top will Just Work (tm) */
+ /* NOTE: CamelImapStore will handle "" as toplevel, but CamelMboxStore wants NULL */
+ if (!path || !strcmp (path, "/"))
+ top = NULL;
+ else
+ top = path + 1;
+
/* FIXME: are there any flags we want to pass when getting folder-info's? */
camel_exception_init (&ex);
- if (!(fi = camel_store_get_folder_info (store, full_name, 0, &ex))) {
+ if (!(fi = camel_store_get_folder_info (store, top, 0, &ex))) {
/* FIXME: report error to user? or simply re-collapse node? or both? */
+ g_warning ("can't get folder-info's for store '%s' at path='%s'", si->display_name, path);
+ gtk_tree_store_remove (model, &iter);
camel_exception_clear (&ex);
return;
}
- if (!(child = fi->child)) {
+ /* FIXME: camel is totally on crack here, @top's folder info
+ * should be @fi and fi->childs should be what we want to fill
+ * our tree with... *sigh* */
+ if (!strcmp (fi->path, path))
+ child = fi->sibling;
+ else
+ child = fi;
+
+ if (child == NULL) {
/* no children afterall... remove the "Loading..." placeholder node */
gtk_tree_store_remove (model, &iter);
} else {
do {
- load = (child->flags & CAMEL_FOLDER_CHILDREN) && !(child->flags & CAMEL_FOLDER_NOINFERIORS);
-
- gtk_tree_store_set (model, &iter,
- COL_STRING_DISPLAY_NAME, child->name,
- COL_POINTER_CAMEL_STORE, store,
- COL_STRING_FOLDER_PATH, child->path,
- COL_STRING_URI, child->url,
- COL_UINT_UNREAD, child->unread_message_count,
- COL_BOOL_IS_STORE, FALSE,
- COL_BOOL_LOAD_SUBDIRS, load,
- -1);
+ tree_store_set_folder_info (model, &iter, priv, si, child);
if ((child = child->sibling) != NULL)
gtk_tree_store_append (model, &iter, root);
} while (child != NULL);
}
- gtk_tree_store_set (model, root, COL_BOOL_LOAD_SUBDIRS, FALSE);
+ gtk_tree_store_set (model, root, COL_BOOL_LOAD_SUBDIRS, FALSE, -1);
camel_store_free_folder_info (store, fi);
}
@@ -371,273 +1031,305 @@ tree_row_expanded (GtkTreeView *treeview, GtkTreeIter *root, GtkTreePath *path,
#if 0
static void
-emc_popup_view(GtkWidget *w, MailComponent *mc)
+emft_popup_view (GtkWidget *item, EMFolderTree *emft)
{
}
static void
-emc_popup_open_new(GtkWidget *w, MailComponent *mc)
+emft_popup_open_new (GtkWidget *item, EMFolderTree *emft)
{
}
#endif
/* FIXME: This must be done in another thread */
static void
-em_copy_folders(CamelStore *tostore, const char *tobase, CamelStore *fromstore, const char *frombase, int delete)
+em_copy_folders (CamelStore *tostore, const char *tobase, CamelStore *fromstore, const char *frombase, int delete)
{
GString *toname, *fromname;
CamelFolderInfo *fi;
GList *pending = NULL, *deleting = NULL, *l;
guint32 flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE;
- CamelException *ex = camel_exception_new();
+ CamelException ex;
int fromlen;
const char *tmp;
-
- if (camel_store_supports_subscriptions(fromstore))
+
+ camel_exception_init (&ex);
+
+ if (camel_store_supports_subscriptions (fromstore))
flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
-
- fi = camel_store_get_folder_info(fromstore, frombase, flags, ex);
- if (camel_exception_is_set(ex))
+
+ fi = camel_store_get_folder_info (fromstore, frombase, flags, &ex);
+ if (camel_exception_is_set (&ex))
goto done;
-
- pending = g_list_append(pending, fi);
-
- toname = g_string_new("");
- fromname = g_string_new("");
-
- tmp = strrchr(frombase, '/');
+
+ pending = g_list_append (pending, fi);
+
+ toname = g_string_new ("");
+ fromname = g_string_new ("");
+
+ tmp = strrchr (frombase, '/');
if (tmp == NULL)
fromlen = 0;
else
- fromlen = tmp-frombase+1;
-
- printf("top name is '%s'\n", fi->full_name);
-
+ fromlen = tmp - frombase + 1;
+
+ d(printf ("top name is '%s'\n", fi->full_name));
+
while (pending) {
CamelFolderInfo *info = pending->data;
-
- pending = g_list_remove_link(pending, pending);
+
+ pending = g_list_remove_link (pending, pending);
while (info) {
CamelFolder *fromfolder, *tofolder;
GPtrArray *uids;
-
+
if (info->child)
- pending = g_list_append(pending, info->child);
+ pending = g_list_append (pending, info->child);
if (tobase[0])
- g_string_printf(toname, "%s/%s", tobase, info->full_name + fromlen);
+ g_string_printf (toname, "%s/%s", tobase, info->full_name + fromlen);
else
- g_string_printf(toname, "%s", info->full_name + fromlen);
-
- printf("Copying from '%s' to '%s'\n", info->full_name, toname->str);
-
+ g_string_printf (toname, "%s", info->full_name + fromlen);
+
+ d(printf ("Copying from '%s' to '%s'\n", info->full_name, toname->str));
+
/* This makes sure we create the same tree, e.g. from a nonselectable source */
/* Not sure if this is really the 'right thing', e.g. for spool stores, but it makes the ui work */
if ((info->flags & CAMEL_FOLDER_NOSELECT) == 0) {
- printf("this folder is selectable\n");
- fromfolder = camel_store_get_folder(fromstore, info->full_name, 0, ex);
+ d(printf ("this folder is selectable\n"));
+ fromfolder = camel_store_get_folder (fromstore, info->full_name, 0, &ex);
if (fromfolder == NULL)
goto exception;
-
- tofolder = camel_store_get_folder(tostore, toname->str, CAMEL_STORE_FOLDER_CREATE, ex);
+
+ tofolder = camel_store_get_folder (tostore, toname->str, CAMEL_STORE_FOLDER_CREATE, &ex);
if (tofolder == NULL) {
- camel_object_unref(fromfolder);
+ camel_object_unref (fromfolder);
goto exception;
}
-
- if (camel_store_supports_subscriptions(tostore)
- && !camel_store_folder_subscribed(tostore, toname->str))
- camel_store_subscribe_folder(tostore, toname->str, NULL);
-
- uids = camel_folder_get_uids(fromfolder);
- camel_folder_transfer_messages_to(fromfolder, uids, tofolder, NULL, delete, ex);
- camel_folder_free_uids(fromfolder, uids);
-
- camel_object_unref(fromfolder);
- camel_object_unref(tofolder);
+
+ if (camel_store_supports_subscriptions (tostore)
+ && !camel_store_folder_subscribed (tostore, toname->str))
+ camel_store_subscribe_folder (tostore, toname->str, NULL);
+
+ uids = camel_folder_get_uids (fromfolder);
+ camel_folder_transfer_messages_to (fromfolder, uids, tofolder, NULL, delete, &ex);
+ camel_folder_free_uids (fromfolder, uids);
+
+ camel_object_unref (fromfolder);
+ camel_object_unref (tofolder);
}
-
- if (camel_exception_is_set(ex))
+
+ if (camel_exception_is_set (&ex))
goto exception;
else if (delete)
- deleting = g_list_prepend(deleting, info);
-
+ deleting = g_list_prepend (deleting, info);
+
info = info->sibling;
}
}
-
+
/* delete the folders in reverse order from how we copyied them, if we are deleting any */
l = deleting;
while (l) {
CamelFolderInfo *info = l->data;
-
- printf("deleting folder '%s'\n", info->full_name);
-
- if (camel_store_supports_subscriptions(fromstore))
- camel_store_unsubscribe_folder(fromstore, info->full_name, NULL);
-
- camel_store_delete_folder(fromstore, info->full_name, NULL);
+
+ d(printf ("deleting folder '%s'\n", info->full_name));
+
+ if (camel_store_supports_subscriptions (fromstore))
+ camel_store_unsubscribe_folder (fromstore, info->full_name, NULL);
+
+ camel_store_delete_folder (fromstore, info->full_name, NULL);
l = l->next;
}
-
-exception:
- camel_store_free_folder_info(fromstore, fi);
- g_list_free(deleting);
-
- g_string_free(toname, TRUE);
- g_string_free(fromname, TRUE);
-done:
- printf("exception: %s\n", ex->desc?ex->desc:"<none>");
- camel_exception_free(ex);
+
+ exception:
+
+ camel_store_free_folder_info (fromstore, fi);
+ g_list_free (deleting);
+
+ g_string_free (toname, TRUE);
+ g_string_free (fromname, TRUE);
+
+ done:
+
+ d(printf ("exception: %s\n", ex.desc ? ex.desc : "<none>"));
+ camel_exception_clear (&ex);
}
struct _copy_folder_data {
- MailComponent *mc;
- int delete;
+ EMFolderTree *emft;
+ gboolean delete;
};
static void
-emc_popup_copy_folder_selected(const char *uri, void *data)
+emft_popup_copy_folder_selected (const char *uri, void *data)
{
- struct _copy_folder_data *d = data;
-
+ struct _copy_folder_data *cfd = data;
+ struct _EMFolderTreePrivate *priv;
+ CamelStore *fromstore, *tostore;
+ char *tobase, *frombase;
+ CamelException ex;
+ CamelURL *url;
+
if (uri == NULL) {
- g_free(d);
+ g_free (cfd);
return;
}
-
- if (uri) {
- EFolder *folder = e_storage_set_get_folder(d->mc->priv->storage_set, d->mc->priv->context_path);
- CamelException *ex = camel_exception_new();
- CamelStore *fromstore, *tostore;
- char *tobase, *frombase;
- CamelURL *url;
-
- printf("copying folder '%s' to '%s'\n", d->mc->priv->context_path, uri);
-
- fromstore = camel_session_get_store(session, e_folder_get_physical_uri(folder), ex);
- frombase = strchr(d->mc->priv->context_path+1, '/')+1;
-
- tostore = camel_session_get_store(session, uri, ex);
- url = camel_url_new(uri, NULL);
- if (url->fragment)
- tobase = url->fragment;
- else if (url->path && url->path[0])
- tobase = url->path+1;
- else
- tobase = "";
-
- em_copy_folders(tostore, tobase, fromstore, frombase, d->delete);
-
- camel_url_free(url);
- camel_exception_free(ex);
+
+ priv = cfd->emft->priv;
+
+ d(printf ("copying folder '%s' to '%s'\n", priv->selected_path, uri));
+
+ camel_exception_init (&ex);
+ if (!(fromstore = camel_session_get_store (session, priv->selected_uri, &ex))) {
+ /* FIXME: error dialog? */
+ camel_exception_clear (&ex);
+ return;
}
- g_free(d);
+
+ frombase = priv->selected_path + 1;
+
+ if (!(tostore = camel_session_get_store (session, uri, &ex))) {
+ /* FIXME: error dialog? */
+ camel_object_unref (fromstore);
+ camel_exception_clear (&ex);
+ return;
+ }
+
+ url = camel_url_new (uri, NULL);
+ if (url->fragment)
+ tobase = url->fragment;
+ else if (url->path && url->path[0])
+ tobase = url->path + 1;
+ else
+ tobase = "";
+
+ em_copy_folders (tostore, tobase, fromstore, frombase, cfd->delete);
+
+ camel_url_free (url);
+ g_free (cfd);
}
static void
-emc_popup_copy(GtkWidget *w, MailComponent *mc)
+emft_popup_copy (GtkWidget *item, EMFolderTree *emft)
{
- struct _copy_folder_data *d;
-
- d = g_malloc(sizeof(*d));
- d->mc = mc;
- d->delete = 0;
- em_select_folder(NULL, _("Select folder"), _("Select destination to copy folder into"), NULL, emc_popup_copy_folder_selected, d);
+ struct _copy_folder_data *cfd;
+
+ cfd = g_malloc (sizeof (*cfd));
+ cfd->emft = emft;
+ cfd->delete = FALSE;
+
+ em_select_folder (NULL, _("Select folder"),
+ _("Select destination to copy folder into"),
+ NULL, emft_popup_copy_folder_selected, cfd);
}
static void
-emc_popup_move(GtkWidget *w, MailComponent *mc)
+emft_popup_move (GtkWidget *item, EMFolderTree *emft)
{
- struct _copy_folder_data *d;
-
- d = g_malloc(sizeof(*d));
- d->mc = mc;
- d->delete = 1;
- em_select_folder(NULL, _("Select folder"), _("Select destination to move folder into"), NULL, emc_popup_copy_folder_selected, d);
+ struct _copy_folder_data *cfd;
+
+ cfd = g_malloc (sizeof (*cfd));
+ cfd->emft = emft;
+ cfd->delete = TRUE;
+
+ em_select_folder (NULL, _("Select folder"),
+ _("Select destination to move folder into"),
+ NULL, emft_popup_copy_folder_selected, cfd);
}
static void
-emc_popup_new_folder_create(EStorageSet *ess, EStorageResult result, void *data)
+emft_popup_new_folder_response (EMFolderSelector *emfs, int response, EMFolderTree *emft)
{
- d(printf ("folder created %s\n", result == E_STORAGE_OK ? "ok" : "failed"));
+ /* FIXME: ugh, kludge-a-licious: EMFolderSelector uses EMFolderTree so we can poke emfs->emft internals */
+ struct _EMFolderTreePrivate *priv = emfs->emft->priv;
+ struct _emft_store_info *si;
+ const char *uri, *parent;
+ CamelException ex;
+ char *path, *name;
+
+ if (response != GTK_RESPONSE_OK) {
+ gtk_widget_destroy ((GtkWidget *) emfs);
+ return;
+ }
+
+ uri = em_folder_selector_get_selected_uri (emfs);
+ path = (char *) em_folder_selector_get_selected_path (emfs);
+ d(printf ("Creating folder: %s (%s)\n", path, uri));
+
+ if (!(si = g_hash_table_lookup (priv->store_hash, uri)))
+ goto done;
+
+ /* FIXME: camel_store_create_folder should just take full path names */
+ path = g_strdup (path);
+ if (!(name = strrchr (path, '/'))) {
+ name = path;
+ parent = "";
+ } else {
+ *name++ = '\0';
+ parent = path;
+ }
+
+ d(printf ("creating folder name='%s' path='%s'\n", name, path));
+
+ camel_exception_init (&ex);
+ camel_store_create_folder (si->store, parent, name, &ex);
+ if (camel_exception_is_set (&ex)) {
+ d(printf ("Create failed: %s\n", ex.desc));
+ /* FIXME: error dialog? */
+ } else if (camel_store_supports_subscriptions (si->store)) {
+ camel_store_subscribe_folder (si->store, path, &ex);
+ if (camel_exception_is_set (&ex)) {
+ d(printf ("Subscribe failed: %s\n", ex.desc));
+ /* FIXME: error dialog? */
+ }
+ }
+
+ camel_exception_clear (&ex);
+
+ done:
+
+ g_free (path);
+
+ gtk_widget_destroy ((GtkWidget *) emfs);
}
static void
-emc_popup_new_folder_response (EMFolderSelector *emfs, guint response, MailComponent *mc)
+store_hash_add_store (gpointer key, gpointer value, gpointer user_data)
{
- /* FIXME: port this too :\ */
- if (response == GTK_RESPONSE_OK) {
- char *path, *tmp, *name, *full;
- EStorage *storage;
- CamelStore *store;
- CamelException *ex;
-
- printf("Creating folder: %s (%s)\n", em_folder_selector_get_selected(emfs),
- em_folder_selector_get_selected_uri(emfs));
-
- path = g_strdup(em_folder_selector_get_selected(emfs));
- tmp = strchr(path+1, '/');
- *tmp++ = 0;
- /* FIXME: camel_store_create_folder should just take full path names */
- full = g_strdup(tmp);
- name = strrchr(tmp, '/');
- if (name == NULL) {
- name = tmp;
- tmp = "";
- } else
- *name++ = 0;
-
- storage = e_storage_set_get_storage(mc->priv->storage_set, path+1);
- store = g_object_get_data((GObject *)storage, "em-store");
-
- printf("creating folder '%s' / '%s' on '%s'\n", tmp, name, path+1);
-
- ex = camel_exception_new();
- camel_store_create_folder(store, tmp, name, ex);
- if (camel_exception_is_set(ex)) {
- printf("Create failed: %s\n", ex->desc);
- } else if (camel_store_supports_subscriptions(store)) {
- camel_store_subscribe_folder(store, full, ex);
- if (camel_exception_is_set(ex)) {
- printf("Subscribe failed: %s\n", ex->desc);
- }
- }
-
- camel_exception_free (ex);
-
- g_free (full);
- g_free (path);
-
- /* Blah, this should just use camel, we get better error reporting if we do too */
- /*e_storage_set_async_create_folder(mc->priv->storage_set, path, "mail", "", emc_popup_new_folder_create, mc);*/
- }
+ struct _emft_store_info *si = value;
+ EMFolderTree *emft = user_data;
- gtk_widget_destroy ((GtkWidget *) emfs);
+ em_folder_tree_add_store (emft, si->store, si->display_name);
}
static void
-emc_popup_new_folder (GtkWidget *w, EMFolderTree *folder_tree)
+emft_popup_new_folder (GtkWidget *item, EMFolderTree *emft)
{
+ EMFolderTree *folder_tree;
GtkWidget *dialog;
- /* FIXME: ugh, need to port this (and em_folder_selector*) to use EMFolderTree I guess */
- dialog = em_folder_selector_create_new (mc->priv->storage_set, 0, _("Create folder"), _("Specify where to create the folder:"));
- em_folder_selector_set_selected ((EMFolderSelector *) dialog, mc->priv->context_path);
- g_signal_connect (dialog, "response", G_CALLBACK (emc_popup_new_folder_response), mc);
+ folder_tree = (EMFolderTree *) em_folder_tree_new ();
+ g_hash_table_foreach (emft->priv->store_hash, store_hash_add_store, folder_tree);
+
+ dialog = em_folder_selector_create_new (folder_tree, 0, _("Create folder"), _("Specify where to create the folder:"));
+ em_folder_selector_set_selected ((EMFolderSelector *) dialog, emft->priv->selected_uri);
+ g_signal_connect (dialog, "response", G_CALLBACK (emft_popup_new_folder_response), emft);
gtk_widget_show (dialog);
}
static void
-em_delete_rec (CamelStore *store, CamelFolderInfo *fi, CamelException *ex)
+emft_popup_delete_rec (CamelStore *store, CamelFolderInfo *fi, CamelException *ex)
{
while (fi) {
CamelFolder *folder;
- if (fi->child)
- em_delete_rec (store, fi->child, ex);
- if (camel_exception_is_set (ex))
- return;
+ if (fi->child) {
+ emft_popup_delete_rec (store, fi->child, ex);
+
+ if (camel_exception_is_set (ex))
+ return;
+ }
d(printf ("deleting folder '%s'\n", fi->full_name));
@@ -667,7 +1359,7 @@ em_delete_rec (CamelStore *store, CamelFolderInfo *fi, CamelException *ex)
}
static void
-em_delete_folders (CamelStore *store, const char *base, CamelException *ex)
+emft_popup_delete_folders (CamelStore *store, const char *base, CamelException *ex)
{
guint32 flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE;
CamelFolderInfo *fi;
@@ -679,14 +1371,14 @@ em_delete_folders (CamelStore *store, const char *base, CamelException *ex)
if (camel_exception_is_set (ex))
return;
- em_delete_rec (store, fi, ex);
+ emft_popup_delete_rec (store, fi, ex);
camel_store_free_folder_info (store, fi);
}
static void
-emc_popup_delete_response (GtkWidget *dialog, guint response, EMFolderTree *folder_tree)
+emft_popup_delete_response (GtkWidget *dialog, guint response, EMFolderTree *emft)
{
- struct _EMFolderTreePrivate *priv = folder_tree->priv;
+ struct _EMFolderTreePrivate *priv = emft->priv;
GtkTreeSelection *selection;
GtkTreeModel *model;
CamelStore *store;
@@ -703,9 +1395,8 @@ emc_popup_delete_response (GtkWidget *dialog, guint response, EMFolderTree *fold
gtk_tree_model_get (model, &iter, COL_STRING_FOLDER_PATH, &path,
COL_POINTER_CAMEL_STORE, &store, -1);
- /* FIXME: need to hook onto store changed event and delete view as well, somewhere else tho */
camel_exception_init (&ex);
- em_delete_folders (store, path, &ex);
+ emft_popup_delete_folders (store, path, &ex);
if (camel_exception_is_set (&ex)) {
e_notice (NULL, GTK_MESSAGE_ERROR, _("Could not delete folder: %s"), ex.desc);
camel_exception_clear (&ex);
@@ -713,9 +1404,9 @@ emc_popup_delete_response (GtkWidget *dialog, guint response, EMFolderTree *fold
}
static void
-emc_popup_delete_folder (GtkWidget *item, EMFolderTree *folder_tree)
+emft_popup_delete_folder (GtkWidget *item, EMFolderTree *emft)
{
- struct _EMFolderTreePrivate *priv = folder_tree->priv;
+ struct _EMFolderTreePrivate *priv = emft->priv;
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreeIter iter;
@@ -742,14 +1433,14 @@ emc_popup_delete_folder (GtkWidget *item, EMFolderTree *folder_tree)
gtk_window_set_title ((GtkWindow *) dialog, title);
g_free (title);
- g_signal_connect (dialog, "response", G_CALLBACK (emc_popup_delete_response), folder_tree);
+ g_signal_connect (dialog, "response", G_CALLBACK (emft_popup_delete_response), emft);
gtk_widget_show (dialog);
}
static void
-emc_popup_rename_folder (GtkWidget *item, EMFolderTree *folder_tree)
+emft_popup_rename_folder (GtkWidget *item, EMFolderTree *emft)
{
- struct _EMFolderTreePrivate *priv = folder_tree->priv;
+ struct _EMFolderTreePrivate *priv = emft->priv;
char *prompt, *folder_path, *name, *new_name, *uri;
GtkTreeSelection *selection;
gboolean done = FALSE;
@@ -761,14 +1452,14 @@ emc_popup_rename_folder (GtkWidget *item, EMFolderTree *folder_tree)
gtk_tree_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_STORE, &store,
+ COL_POINTER_CAMEL_STORE, &store,
COL_STRING_URI, &uri, -1);
prompt = g_strdup_printf (_("Rename the \"%s\" folder to:"), name);
while (!done) {
const char *why;
- new = e_request_string (NULL, _("Rename Folder"), prompt, name);
+ new_name = e_request_string (NULL, _("Rename Folder"), prompt, name);
if (new_name == NULL || !strcmp (name, new_name)) {
/* old name == new name */
done = TRUE;
@@ -794,7 +1485,7 @@ emc_popup_rename_folder (GtkWidget *item, EMFolderTree *folder_tree)
oldpath = folder_path + 1;
newpath = path + 1;
- printf ("renaming %s to %s\n", oldpath, newpath);
+ d(printf ("renaming %s to %s\n", oldpath, newpath));
camel_exception_clear (&ex);
camel_store_rename_folder (store, oldpath, newpath, &ex);
@@ -821,7 +1512,7 @@ struct _prop_data {
};
static void
-emc_popup_properties_response (GtkWidget *dialog, int response, struct _prop_data *prop_data)
+emft_popup_properties_response (GtkWidget *dialog, int response, struct _prop_data *prop_data)
{
CamelArgV *argv = prop_data->argv;
int i;
@@ -840,7 +1531,7 @@ emc_popup_properties_response (GtkWidget *dialog, int response, struct _prop_dat
break;
case CAMEL_ARG_STR:
g_free (arg->ca_str);
- arg->ca_str = gtk_entry_get_text ((GtkEntry *) prop_data->widgets[i]);
+ arg->ca_str = (char *) gtk_entry_get_text ((GtkEntry *) prop_data->widgets[i]);
break;
default:
g_assert_not_reached ();
@@ -853,7 +1544,7 @@ emc_popup_properties_response (GtkWidget *dialog, int response, struct _prop_dat
}
static void
-emc_popup_properties_free (void *data)
+emft_popup_properties_free (void *data)
{
struct _prop_data *prop_data = data;
int i;
@@ -869,7 +1560,7 @@ emc_popup_properties_free (void *data)
}
static void
-emc_popup_properties_got_folder (char *uri, CamelFolder *folder, void *data)
+emft_popup_properties_got_folder (char *uri, CamelFolder *folder, void *data)
{
GtkWidget *dialog, *w, *table, *label;
struct _prop_data *prop_data;
@@ -983,15 +1674,15 @@ emc_popup_properties_got_folder (char *uri, CamelFolder *folder, void *data)
/* we do 'apply on ok' ... since instant apply may apply some very long running tasks */
- g_signal_connect (dialog, "response", G_CALLBACK (emc_popup_properties_response), prop_data);
- g_object_set_data_full ((GObject *) dialog, "e-prop-data", prop_data, emc_popup_properties_free);
+ g_signal_connect (dialog, "response", G_CALLBACK (emft_popup_properties_response), prop_data);
+ g_object_set_data_full ((GObject *) dialog, "e-prop-data", prop_data, emft_popup_properties_free);
gtk_widget_show (dialog);
}
static void
-emc_popup_properties (GtkWidget *item, EMFolderTree *folder_tree)
+emft_popup_properties (GtkWidget *item, EMFolderTree *emft)
{
- struct _EMFolderTreePrivate *priv = folder_tree->priv;
+ struct _EMFolderTreePrivate *priv = emft->priv;
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreeIter iter;
@@ -1001,30 +1692,30 @@ emc_popup_properties (GtkWidget *item, EMFolderTree *folder_tree)
gtk_tree_selection_get_selected (selection, &model, &iter);
gtk_tree_model_get (model, &iter, COL_STRING_URI, &uri, -1);
- mail_get_folder (uri, 0, emc_popup_properties_got_folder, folder_tree, mail_thread_new);
+ mail_get_folder (uri, 0, emft_popup_properties_got_folder, emft, mail_thread_new);
}
-static EMPopupItem emc_popup_menu[] = {
+static EMPopupItem emft_popup_menu[] = {
#if 0
- { EM_POPUP_ITEM, "00.emc.00", N_("_View"), G_CALLBACK (emc_popup_view), NULL, NULL, 0 },
- { EM_POPUP_ITEM, "00.emc.01", N_("Open in _New Window"), G_CALLBACK (emc_popup_open_new), NULL, NULL, 0 },
+ { EM_POPUP_ITEM, "00.emc.00", N_("_View"), G_CALLBACK (emft_popup_view), NULL, NULL, 0 },
+ { EM_POPUP_ITEM, "00.emc.01", N_("Open in _New Window"), G_CALLBACK (emft_popup_open_new), NULL, NULL, 0 },
{ EM_POPUP_BAR, "10.emc" },
#endif
- { EM_POPUP_ITEM, "10.emc.00", N_("_Copy"), G_CALLBACK (emc_popup_copy), NULL, "folder-copy-16.png", 0 },
- { EM_POPUP_ITEM, "10.emc.01", N_("_Move"), G_CALLBACK (emc_popup_move), NULL, "folder-move-16.png", 0 },
-
+ { EM_POPUP_ITEM, "10.emc.00", N_("_Copy"), G_CALLBACK (emft_popup_copy), NULL, "folder-copy-16.png", 0 },
+ { EM_POPUP_ITEM, "10.emc.01", N_("_Move"), G_CALLBACK (emft_popup_move), NULL, "folder-move-16.png", 0 },
+
{ EM_POPUP_BAR, "20.emc" },
- { EM_POPUP_ITEM, "20.emc.00", N_("_New Folder..."), G_CALLBACK (emc_popup_new_folder), NULL, "folder-mini.png", 0 },
- { EM_POPUP_ITEM, "20.emc.01", N_("_Delete"), G_CALLBACK (emc_popup_delete_folder), NULL, "evolution-trash-mini.png", 0 },
- { EM_POPUP_ITEM, "20.emc.01", N_("_Rename"), G_CALLBACK (emc_popup_rename_folder), NULL, NULL, 0 },
-
+ { EM_POPUP_ITEM, "20.emc.00", N_("_New Folder..."), G_CALLBACK (emft_popup_new_folder), NULL, "folder-mini.png", 0 },
+ { EM_POPUP_ITEM, "20.emc.01", N_("_Delete"), G_CALLBACK (emft_popup_delete_folder), NULL, "evolution-trash-mini.png", 0 },
+ { EM_POPUP_ITEM, "20.emc.01", N_("_Rename"), G_CALLBACK (emft_popup_rename_folder), NULL, NULL, 0 },
+
{ EM_POPUP_BAR, "80.emc" },
- { EM_POPUP_ITEM, "80.emc.00", N_("_Properties..."), G_CALLBACK (emc_popup_properties), NULL, "configure_16_folder.xpm", 0 },
+ { EM_POPUP_ITEM, "80.emc.00", N_("_Properties..."), G_CALLBACK (emft_popup_properties), NULL, "configure_16_folder.xpm", 0 },
};
static gboolean
-tree_button_press (GtkWidget *treeview, GdkEventButton *event, EMFolderTree *ftree)
+tree_button_press (GtkWidget *treeview, GdkEventButton *event, EMFolderTree *emft)
{
GSList *menus = NULL;
GtkMenu *menu;
@@ -1037,10 +1728,10 @@ tree_button_press (GtkWidget *treeview, GdkEventButton *event, EMFolderTree *ftr
/* handle right-click by opening a context menu */
emp = em_popup_new ("com.ximian.mail.storageset.popup.select");
- for (i = 0; i < sizeof (emc_popup_menu) / sizeof (emc_popup_menu[0]); i++) {
- EMPopupItem *item = &emc_popup_menu[i];
+ for (i = 0; i < sizeof (emft_popup_menu) / sizeof (emft_popup_menu[0]); i++) {
+ EMPopupItem *item = &emft_popup_menu[i];
- item->activate_data = ftree;
+ item->activate_data = emft;
menus = g_slist_prepend (menus, item);
}
@@ -1050,9 +1741,9 @@ tree_button_press (GtkWidget *treeview, GdkEventButton *event, EMFolderTree *ftr
if (event == NULL || event->type == GDK_KEY_PRESS) {
/* FIXME: menu pos function */
- gtk_menu_popup (menu, NULL, NULL, NULL, NULL, 0, event->key.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);
}
return TRUE;
@@ -1060,32 +1751,202 @@ tree_button_press (GtkWidget *treeview, GdkEventButton *event, EMFolderTree *ftr
static void
-tree_selection_changed (GtkTreeSelection *selection, EMFolderTRee *ftree)
+tree_selection_changed (GtkTreeSelection *selection, EMFolderTree *emft)
{
- /* new folder has been selected */
+ struct _EMFolderTreePrivate *priv = emft->priv;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ char *path, *uri;
+
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+ return;
+
+ gtk_tree_model_get (model, &iter, COL_STRING_FOLDER_PATH, &path,
+ COL_STRING_URI, &uri, -1);
+
+ g_free (priv->selected_uri);
+ priv->selected_uri = g_strdup (uri);
+
+ g_free (priv->selected_path);
+ priv->selected_path = g_strdup (path);
+
+ g_signal_emit (emft, signals[FOLDER_SELECTED], 0, path, uri);
+}
+
+
+static void
+folder_subscribed_cb (CamelStore *store, void *event_data, EMFolderTree *emft)
+{
+ CamelFolderInfo *fi = event_data;
+ struct _emft_store_info *si;
+ GtkTreeRowReference *row;
+ GtkTreeIter parent, iter;
+ GtkTreeModel *model;
+ GtkTreePath *path;
+ gboolean load;
+ char *dirname;
+
+ if (!(si = g_hash_table_lookup (emft->priv->store_hash, store)))
+ return;
+
+ /* make sure we don't already know about it? */
+ if (g_hash_table_lookup (si->path_hash, fi->path))
+ return;
+
+ /* get our parent folder's path */
+ if (!(dirname = g_path_get_dirname (fi->path)))
+ return;
+
+ if (!strcmp (dirname, "/")) {
+ /* user subscribed to a toplevel folder */
+ row = si->row;
+ g_free (dirname);
+ } else {
+ row = g_hash_table_lookup (si->path_hash, dirname);
+ g_free (dirname);
+
+ /* if row is NULL, don't bother adding to the tree,
+ * when the user expands enough nodes - it will be
+ * added auto-magically */
+ if (row == NULL)
+ return;
+ }
+
+ path = gtk_tree_row_reference_get_path (row);
+ model = gtk_tree_view_get_model (emft->priv->treeview);
+ if (!(gtk_tree_model_get_iter (model, &parent, path))) {
+ gtk_tree_path_free (path);
+ return;
+ }
+
+ gtk_tree_path_free (path);
+
+ /* make sure parent's subfolders have already been loaded */
+ gtk_tree_model_get (model, &parent, COL_BOOL_LOAD_SUBDIRS, &load, -1);
+ if (load)
+ return;
+
+ /* append a new node */
+ gtk_tree_store_append ((GtkTreeStore *) model, &iter, &parent);
+
+ tree_store_set_folder_info ((GtkTreeStore *) model, &iter, emft->priv, si, fi);
+}
+
+static void
+remove_folders (EMFolderTree *emft, GtkTreeModel *model, struct _emft_store_info *si, GtkTreeIter *toplevel)
+{
+ struct _EMFolderTreePrivate *priv = emft->priv;
+ GtkTreeRowReference *row;
+ char *uri, *folder_path;
+ gboolean is_store, go;
+ GtkTreeIter iter;
+
+ if (gtk_tree_model_iter_children (model, &iter, toplevel)) {
+ do {
+ GtkTreeIter next = iter;
+
+ go = gtk_tree_model_iter_next (model, &next);
+ remove_folders (emft, model, si, &iter);
+ iter = next;
+ } while (go);
+ }
+
+ gtk_tree_model_get (model, toplevel, COL_STRING_URI, &uri,
+ COL_STRING_FOLDER_PATH, &folder_path,
+ COL_BOOL_IS_STORE, &is_store, -1);
+
+ if ((row = g_hash_table_lookup (si->path_hash, folder_path))) {
+ g_hash_table_remove (si->path_hash, folder_path);
+ gtk_tree_row_reference_free (row);
+ }
+
+ if ((row = g_hash_table_lookup (priv->uri_hash, uri))) {
+ g_hash_table_remove (priv->uri_hash, uri);
+ gtk_tree_row_reference_free (row);
+ }
+
+ gtk_tree_store_remove ((GtkTreeStore *) model, toplevel);
+
+ if (is_store) {
+ g_hash_table_remove (priv->store_hash, si->store);
+ store_info_free (si);
+ }
+}
+
+static void
+folder_unsubscribed_cb (CamelStore *store, void *event_data, EMFolderTree *emft)
+{
+ CamelFolderInfo *fi = event_data;
+ struct _emft_store_info *si;
+ GtkTreeRowReference *row;
+ GtkTreeModel *model;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+
+ if (!(si = g_hash_table_lookup (emft->priv->store_hash, store)))
+ return;
+
+ if (!(row = g_hash_table_lookup (si->path_hash, fi->path)))
+ return;
+
+ path = gtk_tree_row_reference_get_path (row);
+ model = gtk_tree_view_get_model (emft->priv->treeview);
+ if (!(gtk_tree_model_get_iter (model, &iter, path))) {
+ gtk_tree_path_free (path);
+ return;
+ }
+
+ remove_folders (emft, model, si, &iter);
+}
+
+static void
+folder_created_cb (CamelStore *store, void *event_data, EMFolderTree *emft)
+{
+ /* we only want created events to do more work if we don't support subscriptions */
+ if (!camel_store_supports_subscriptions (store))
+ folder_subscribed_cb (store, event_data, emft);
+}
+
+static void
+folder_deleted_cb (CamelStore *store, void *event_data, EMFolderTree *emft)
+{
+ /* we only want deleted events to do more work if we don't support subscriptions */
+ if (!camel_store_supports_subscriptions (store))
+ folder_unsubscribed_cb (store, event_data, emft);
+}
+
+static void
+folder_renamed_cb (CamelStore *store, void *event_data, EMFolderTree *emft)
+{
+ /* FIXME: implement me */
}
void
-em_folder_tree_add_store (EMFolderTree *tree, CamelStore *store, const char *display_name)
+em_folder_tree_add_store (EMFolderTree *emft, CamelStore *store, const char *display_name)
{
struct _EMFolderTreePrivate *priv;
+ struct _emft_store_info *si;
+ GtkTreeRowReference *row;
GtkTreeIter root, iter;
GtkTreeStore *model;
GtkTreePath *path;
char *uri;
- g_return_if_fail (EM_IS_FOLDER_TREE (tree));
+ g_return_if_fail (EM_IS_FOLDER_TREE (emft));
g_return_if_fail (CAMEL_IS_STORE (store));
g_return_if_fail (display_name != NULL);
- priv = tree->priv;
+ priv = emft->priv;
model = (GtkTreeStore *) gtk_tree_view_get_model (priv->treeview);
- if ((path = g_hash_table_lookup (priv->store_hash, store))) {
+ if ((si = g_hash_table_lookup (priv->store_hash, store))) {
const char *name;
+ path = gtk_tree_row_reference_get_path (si->row);
gtk_tree_model_get_iter ((GtkTreeModel *) model, &iter, path);
+ gtk_tree_path_free (path);
+
gtk_tree_model_get ((GtkTreeModel *) model, &iter, COL_STRING_DISPLAY_NAME, (char **) &name, -1);
g_warning ("the store `%s' is already in the folder tree as `%s'",
@@ -1102,13 +1963,21 @@ em_folder_tree_add_store (EMFolderTree *tree, CamelStore *store, const char *dis
COL_STRING_DISPLAY_NAME, display_name,
COL_POINTER_CAMEL_STORE, store,
COL_STRING_FOLDER_PATH, "/",
+ COL_BOOL_LOAD_SUBDIRS, TRUE,
COL_BOOL_IS_STORE, TRUE,
COL_STRING_URI, uri, -1);
- camel_object_ref (store);
path = gtk_tree_model_get_path ((GtkTreeModel *) model, &iter);
- g_hash_table_insert (priv->store_hash, store, path);
- g_free (uri);
+ row = gtk_tree_row_reference_new ((GtkTreeModel *) model, path);
+ gtk_tree_path_free (path);
+
+ si = g_new (struct _emft_store_info, 1);
+ si->display_name = g_strdup (display_name);
+ camel_object_ref (store);
+ si->store = store;
+ si->row = row;
+ si->path_hash = g_hash_table_new (g_str_hash, g_str_equal);
+ g_hash_table_insert (priv->store_hash, store, si);
/* each store has folders... but we don't load them until the user demands them */
root = iter;
@@ -1116,38 +1985,77 @@ em_folder_tree_add_store (EMFolderTree *tree, CamelStore *store, const char *dis
gtk_tree_store_set (model, &iter,
COL_STRING_DISPLAY_NAME, _("Loading..."),
COL_POINTER_CAMEL_STORE, store,
+ COL_STRING_FOLDER_PATH, "/",
COL_BOOL_LOAD_SUBDIRS, TRUE,
COL_BOOL_IS_STORE, FALSE,
COL_STRING_URI, uri,
COL_UINT_UNREAD, 0,
-1);
+
+ g_free (uri);
+
+ /* listen to store events */
+#define CAMEL_CALLBACK(func) ((CamelObjectEventHookFunc) func)
+ si->created_id = camel_object_hook_event (store, "folder_created", CAMEL_CALLBACK (folder_created_cb), emft);
+ si->deleted_id = camel_object_hook_event (store, "folder_deleted", CAMEL_CALLBACK (folder_deleted_cb), emft);
+ si->renamed_id = camel_object_hook_event (store, "folder_renamed", CAMEL_CALLBACK (folder_renamed_cb), emft);
+ si->subscribed_id = camel_object_hook_event (store, "folder_subscribed", CAMEL_CALLBACK (folder_subscribed_cb), emft);
+ si->unsubscribed_id = camel_object_hook_event (store, "folder_unsubscribed", CAMEL_CALLBACK (folder_unsubscribed_cb), emft);
}
void
-em_folder_tree_remove_store (EMFolderTree *tree, CamelStore *store)
+em_folder_tree_remove_store (EMFolderTree *emft, CamelStore *store)
{
struct _EMFolderTreePrivate *priv;
- GtkTreeStore *model;
+ struct _emft_store_info *si;
+ GtkTreeModel *model;
+ GtkTreePath *path;
GtkTreeIter iter;
- g_return_if_fail (EM_IS_FOLDER_TREE (tree));
+ g_return_if_fail (EM_IS_FOLDER_TREE (emft));
g_return_if_fail (CAMEL_IS_STORE (store));
- priv = tree->priv;
- model = (GtkTreeStore *) gtk_tree_view_get_model (priv->treeview);
+ priv = emft->priv;
+ model = gtk_tree_view_get_model (priv->treeview);
- if (!(path = g_hash_table_lookup (priv->store_hash, store))) {
- g_warning ("the store `%s' is not in the folder tree", display_name);
+ if (!(si = g_hash_table_lookup (priv->store_hash, store))) {
+ g_warning ("the store `%s' is not in the folder tree", si->display_name);
return;
}
- gtk_tree_model_get_iter ((GtkTreeModel *) model, &iter, path);
+ path = gtk_tree_row_reference_get_path (si->row);
+ gtk_tree_model_get_iter (model, &iter, path);
+ gtk_tree_path_free (path);
+
+ /* recursively remove subfolders and finally the toplevel store */
+ remove_folders (emft, model, si, &iter);
+}
+
+
+void
+em_folder_tree_set_selected (EMFolderTree *emft, const char *uri)
+{
+ g_return_if_fail (EM_IS_FOLDER_TREE (emft));
- gtk_tree_store_remove (model, &iter);
- g_hash_table_remove (priv->store_hash, store);
+ /* FIXME: implement me */
+}
+
+
+const char *
+em_folder_tree_get_selected_uri (EMFolderTree *emft)
+{
+ g_return_val_if_fail (EM_IS_FOLDER_TREE (emft), NULL);
- camel_object_unref (store);
- gtk_tree_path_free (path);
+ return emft->priv->selected_uri;
+}
+
+
+const char *
+em_folder_tree_get_selected_path (EMFolderTree *emft)
+{
+ g_return_val_if_fail (EM_IS_FOLDER_TREE (emft), NULL);
+
+ return emft->priv->selected_path;
}
diff --git a/mail/em-folder-tree.h b/mail/em-folder-tree.h
index 7a5ce72cc3..938813b34a 100644
--- a/mail/em-folder-tree.h
+++ b/mail/em-folder-tree.h
@@ -27,6 +27,8 @@
#include <gtk/gtkvbox.h>
#include <camel/camel-store.h>
+#include "em-folder-tree-model.h"
+
#ifdef __cplusplus
extern "C" {
#pragma }
@@ -51,15 +53,22 @@ struct _EMFolderTree {
struct _EMFolderTreeClass {
GtkVBoxClass parent_class;
+ /* signals */
+ void (* folder_selected) (EMFolderTree *emft, const char *path, const char *uri);
};
GType em_folder_tree_get_type (void);
GtkWidget *em_folder_tree_new (void);
+GtkWidget *em_folder_tree_new_with_model (EMFolderTreeModel *model);
+
+void em_folder_tree_add_store (EMFolderTree *emft, CamelStore *store, const char *display_name);
+void em_folder_tree_remove_store (EMFolderTree *emft, CamelStore *store);
-void em_folder_tree_add_store (EMFolderTree *tree, CamelStore *store, const char *display_name);
-void em_folder_tree_remove_store (EMFolderTree *tree, CamelStore *store);
+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);
#ifdef __cplusplus
}
diff --git a/mail/em-marshal.list b/mail/em-marshal.list
index 0c8bfbbbfb..4a19a91441 100644
--- a/mail/em-marshal.list
+++ b/mail/em-marshal.list
@@ -1,2 +1,5 @@
BOOLEAN:BOXED,POINTER,POINTER
-NONE:POINTER
+BOOLEAN:POINTER,POINTER
+VOID:STRING,STRING
+BOOLEAN:POINTER
+VOID:POINTER
diff --git a/mail/mail-component-factory.c b/mail/mail-component-factory.c
index d941e8edbc..326f9177db 100644
--- a/mail/mail-component-factory.c
+++ b/mail/mail-component-factory.c
@@ -37,6 +37,8 @@
#include "mail-config.h"
#include "mail-mt.h"
+#include "shell/evolution-shell-client.h"
+
#include <bonobo-activation/bonobo-activation.h>
#include <bonobo/bonobo-shlib-factory.h>
diff --git a/mail/mail-component.c b/mail/mail-component.c
index 12cc03ca78..f2e6a903c4 100644
--- a/mail/mail-component.c
+++ b/mail/mail-component.c
@@ -33,10 +33,8 @@
#include <fcntl.h>
#include <errno.h>
-#include "e-storage.h"
-#include "e-storage-set.h"
-#include "e-storage-browser.h"
-#include "e-storage-set-view.h"
+#include "em-folder-tree.h"
+#include "em-folder-browser.h"
#include "em-folder-selector.h"
#include "em-folder-selection.h"
@@ -72,164 +70,38 @@
#define d(x) x
-#define MESSAGE_RFC822_TYPE "message/rfc822"
-#define TEXT_URI_LIST_TYPE "text/uri-list"
-#define UID_LIST_TYPE "x-uid-list"
-#define FOLDER_TYPE "x-folder"
-
-/* Drag & Drop types */
-enum DndDragType {
- DND_DRAG_TYPE_FOLDER, /* drag an evo folder */
- DND_DRAG_TYPE_TEXT_URI_LIST, /* drag to an mbox file */
-};
-
-enum DndDropType {
- DND_DROP_TYPE_UID_LIST, /* drop a list of message uids */
- DND_DROP_TYPE_FOLDER, /* drop an evo folder */
- DND_DROP_TYPE_MESSAGE_RFC822, /* drop a message/rfc822 stream */
- DND_DROP_TYPE_TEXT_URI_LIST, /* drop an mbox file */
-};
-
-static GtkTargetEntry drag_types[] = {
- { UID_LIST_TYPE, 0, DND_DRAG_TYPE_FOLDER },
- { TEXT_URI_LIST_TYPE, 0, DND_DRAG_TYPE_TEXT_URI_LIST },
-};
-
-static const int num_drag_types = sizeof (drag_types) / sizeof (drag_types[0]);
-
-static GtkTargetEntry drop_types[] = {
- { UID_LIST_TYPE, 0, DND_DROP_TYPE_UID_LIST },
- { FOLDER_TYPE, 0, DND_DROP_TYPE_FOLDER },
- { MESSAGE_RFC822_TYPE, 0, DND_DROP_TYPE_MESSAGE_RFC822 },
- { TEXT_URI_LIST_TYPE, 0, DND_DROP_TYPE_TEXT_URI_LIST },
-};
-
-static const int num_drop_types = sizeof (drop_types) / sizeof (drop_types[0]);
-
#define PARENT_TYPE bonobo_object_get_type ()
static BonoboObjectClass *parent_class = NULL;
struct _MailComponentPrivate {
char *base_directory;
-
+
+ EMFolderTree *emft;
+
MailAsyncEvent *async_event;
- GHashTable *storages_hash; /* storage by store */
-
- EFolderTypeRegistry *folder_type_registry;
- EStorageSet *storage_set;
-
+ GHashTable *store_hash; /* display_name by store */
+
RuleContext *search_context;
-
+
char *context_path; /* current path for right-click menu */
-
+
CamelStore *local_store;
};
-static int emc_tree_right_click(ETree *tree, gint row, ETreePath path, gint col, GdkEvent *event, MailComponent *component);
-
/* Utility functions. */
-/* EPFIXME: Eeek, this totally sucks. See comment in e-storage.h,
- async_open_folder() should NOT be a signal. */
-
-struct _StorageConnectedData {
- EStorage *storage;
- char *path;
- EStorageDiscoveryCallback callback;
- void *callback_data;
-};
-typedef struct _StorageConnectedData StorageConnectedData;
-
-static void
-storage_connected_callback (CamelStore *store,
- CamelFolderInfo *info,
- StorageConnectedData *data)
-{
- EStorageResult result;
-
- if (info != NULL)
- result = E_STORAGE_OK;
- else
- result = E_STORAGE_GENERICERROR;
-
- (* data->callback) (data->storage, result, data->path, data->callback_data);
-
- g_object_unref (data->storage);
- g_free (data->path);
- g_free (data);
-}
-
static void
-storage_async_open_folder_callback (EStorage *storage,
- const char *path,
- EStorageDiscoveryCallback callback,
- void *callback_data,
- CamelStore *store)
+add_storage (MailComponent *component, const char *name, CamelService *store, CamelException *ex)
{
- StorageConnectedData *storage_connected_data = g_new0 (StorageConnectedData, 1);
-
- g_object_ref (storage);
-
- storage_connected_data->storage = storage;
- storage_connected_data->path = g_strdup (path);
- storage_connected_data->callback = callback;
- storage_connected_data->callback_data = callback_data;
-
- mail_note_store (store, NULL, storage,
- (void *) storage_connected_callback, storage_connected_data);
+ camel_object_ref (store);
+ g_hash_table_insert (component->priv->store_hash, store, g_strdup (name));
+ em_folder_tree_add_store (component->priv->emft, (CamelStore *) store, name);
+ mail_note_store ((CamelStore *) store, NULL, NULL, NULL);
}
static void
-add_storage (MailComponent *component,
- const char *name,
- CamelService *store,
- CamelException *ex)
-{
- EStorage *storage;
- EFolder *root_folder;
-
- root_folder = e_folder_new (name, "noselect", "");
- storage = e_storage_new (name, root_folder);
- e_storage_declare_has_subfolders(storage, "/", _("Connecting..."));
-
- camel_object_ref(store);
-
- g_object_set_data((GObject *)storage, "em-store", store);
- g_hash_table_insert (component->priv->storages_hash, store, storage);
-
- g_signal_connect(storage, "async_open_folder",
- G_CALLBACK (storage_async_open_folder_callback), store);
-
-#if 0 /* Some private test code - zed */
- {
- static void *model;
-
- if (model == NULL) {
- model = em_store_model_new();
- em_store_model_view_new(model);
- }
-
- em_store_model_add_store(model, store);
- }
-#endif
-
-#if 0
- /* EPFIXME these are not needed anymore. */
- g_signal_connect(storage, "create_folder", G_CALLBACK(storage_create_folder), store);
- g_signal_connect(storage, "remove_folder", G_CALLBACK(storage_remove_folder), store);
- g_signal_connect(storage, "xfer_folder", G_CALLBACK(storage_xfer_folder), store);
-#endif
-
- e_storage_set_add_storage (component->priv->storage_set, storage);
-
- mail_note_store ((CamelStore *) store, NULL, storage, NULL, NULL);
-
- g_object_unref (storage);
-}
-
-static void
-load_accounts(MailComponent *component, EAccountList *accounts)
+load_accounts (MailComponent *component, EAccountList *accounts)
{
EIterator *iter;
@@ -247,7 +119,7 @@ load_accounts(MailComponent *component, EAccountList *accounts)
account = (EAccount *) e_iterator_get (iter);
service = account->source;
name = account->name;
-
+
if (account->enabled && service->url != NULL)
mail_component_load_storage_by_uri (component, service->url, name);
@@ -257,39 +129,21 @@ load_accounts(MailComponent *component, EAccountList *accounts)
g_object_unref (iter);
}
-static inline gboolean
-type_is_mail (const char *type)
-{
- return !strcmp (type, "mail") || !strcmp (type, "mail/public");
-}
-
-static inline gboolean
-type_is_vtrash (const char *type)
-{
- return !strcmp (type, "vtrash");
-}
-
-static inline gboolean
-type_is_vjunk (const char *type)
-{
- return !strcmp (type, "vjunk");
-}
-
static void
storage_go_online (gpointer key, gpointer value, gpointer data)
{
CamelStore *store = key;
CamelService *service = CAMEL_SERVICE (store);
-
+
if (! (service->provider->flags & CAMEL_PROVIDER_IS_REMOTE)
|| (service->provider->flags & CAMEL_PROVIDER_IS_EXTERNAL))
return;
-
+
if ((CAMEL_IS_DISCO_STORE (service)
&& camel_disco_store_status (CAMEL_DISCO_STORE (service)) == CAMEL_DISCO_STORE_OFFLINE)
|| service->status != CAMEL_SERVICE_DISCONNECTED) {
mail_store_set_offline (store, FALSE, NULL, NULL);
- mail_note_store (store, NULL, NULL, NULL, NULL);
+ mail_note_store (store, NULL, NULL, NULL);
}
}
@@ -369,7 +223,6 @@ setup_local_store(MailComponent *component)
g_free(store_uri);
}
-/* EStorageBrowser callbacks. */
static BonoboControl *
create_noselect_control (void)
@@ -378,498 +231,51 @@ create_noselect_control (void)
label = gtk_label_new (_("This folder cannot contain messages."));
gtk_widget_show (label);
+
return bonobo_control_new (label);
}
static GtkWidget *
-create_view_callback (EStorageBrowser *browser,
- const char *path,
- void *unused_data)
+create_view_widget (EMFolderTree *emft, const char *path, const char *uri)
{
BonoboControl *control;
- EFolder *folder;
- const char *folder_type;
- const char *physical_uri;
-
- folder = e_storage_set_get_folder (e_storage_browser_peek_storage_set (browser), path);
- if (folder == NULL) {
- g_warning ("No folder at %s", path);
- return gtk_label_new ("(You should not be seeing this label)");
- }
-
- folder_type = e_folder_get_type_string (folder);
- physical_uri = e_folder_get_physical_uri (folder);
-
- if (type_is_mail (folder_type)) {
- const char *noselect;
- CamelURL *url;
-
- url = camel_url_new (physical_uri, NULL);
- noselect = url ? camel_url_get_param (url, "noselect") : NULL;
- if (noselect && !strcasecmp (noselect, "yes"))
- control = create_noselect_control ();
- else
- control = folder_browser_factory_new_control (physical_uri);
- camel_url_free (url);
- } else if (type_is_vtrash (folder_type)) {
- if (!strncasecmp (physical_uri, "file:", 5))
- control = folder_browser_factory_new_control ("vtrash:file:/");
- else
- control = folder_browser_factory_new_control (physical_uri);
- } else if (type_is_vjunk (folder_type)) {
- if (!strncasecmp (physical_uri, "file:", 5))
- control = folder_browser_factory_new_control ("vjunk:file:/");
- else
- control = folder_browser_factory_new_control (physical_uri);
- } else
- return NULL;
+ const char *noselect;
+ CamelURL *url;
+
+ url = camel_url_new (uri, NULL);
+ noselect = url ? camel_url_get_param (url, "noselect") : NULL;
+ if (noselect && !strcasecmp (noselect, "yes"))
+ control = create_noselect_control ();
+ else
+ control = folder_browser_factory_new_control (uri);
+ camel_url_free (url);
if (!control)
return NULL;
-
- /* EPFIXME: This leaks the control. */
- return bonobo_widget_new_control_from_objref (BONOBO_OBJREF (control), CORBA_OBJECT_NIL);
-}
-
-static void
-browser_page_switched_callback (EStorageBrowser *browser,
- GtkWidget *old_page,
- GtkWidget *new_page,
- BonoboControl *parent_control)
-{
- if (BONOBO_IS_WIDGET (old_page)) {
- BonoboControlFrame *control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (old_page));
-
- bonobo_control_frame_control_deactivate (control_frame);
- }
-
- if (BONOBO_IS_WIDGET (new_page)) {
- BonoboControlFrame *control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (new_page));
- Bonobo_UIContainer ui_container = bonobo_control_get_remote_ui_container (parent_control, NULL);
-
- /* This is necessary because we are not embedding the folder browser control
- directly; we are putting the folder browser control into a notebook which
- is then exported to the shell as a control. So we need to forward the
- notebook's UIContainer to the folder browser. */
- bonobo_control_frame_set_ui_container (control_frame, ui_container, NULL);
-
- bonobo_control_frame_control_activate (control_frame);
- }
-}
-
-static CamelFolder *
-foo_get_folder (EStorageSetView *view, const char *path, CamelException *ex)
-{
- /* <NotZed> either do
- mail_tool_uri_to_folder(ess_get_folder(path).physicaluri),
- or split the path into 'path' and 'storage name' and do get
- ess_get_storage() -> store -> open_folder
- */
- CamelFolder *folder;
- EStorageSet *set;
- EFolder *efolder;
- const char *uri;
-
- set = e_storage_set_view_get_storage_set (view);
- efolder = e_storage_set_get_folder (set, path);
- uri = e_folder_get_physical_uri (efolder);
-
- folder = mail_tool_uri_to_folder (uri, 0, ex);
-
- return folder;
-}
-
-static void
-drag_text_uri_list (EStorageSetView *view, const char *path, GtkSelectionData *selection, gpointer user_data)
-{
- CamelFolder *src, *dest;
- const char *tmpdir;
- CamelStore *store;
- CamelException ex;
- GtkWidget *dialog;
- GPtrArray *uids;
- char *uri;
-
- camel_exception_init (&ex);
-
- if (!(src = foo_get_folder (view, path, &ex))) {
- dialog = gtk_message_dialog_new ((GtkWindow *) view, GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
- _("Could not open source folder: %s"),
- camel_exception_get_description (&ex));
-
- gtk_dialog_run ((GtkDialog *) dialog);
- gtk_widget_destroy (dialog);
-
- camel_exception_clear (&ex);
-
- return;
- }
- if (!(tmpdir = e_mkdtemp ("drag-n-drop-XXXXXX"))) {
- dialog = gtk_message_dialog_new ((GtkWindow *) view, GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
- _("Could not create temporary directory: %s"),
- g_strerror (errno));
-
- gtk_dialog_run ((GtkDialog *) dialog);
- gtk_widget_destroy (dialog);
-
- camel_object_unref (src);
-
- return;
- }
-
- uri = g_strdup_printf ("mbox:%s", tmpdir);
- if (!(store = camel_session_get_store (session, uri, &ex))) {
- dialog = gtk_message_dialog_new ((GtkWindow *) view, GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
- _("Could not create temporary mbox store: %s"),
- camel_exception_get_description (&ex));
-
- gtk_dialog_run ((GtkDialog *) dialog);
- gtk_widget_destroy (dialog);
-
- camel_exception_clear (&ex);
- camel_object_unref (src);
- g_free (uri);
-
- return;
- }
-
- if (!(dest = camel_store_get_folder (store, "mbox", CAMEL_STORE_FOLDER_CREATE, &ex))) {
- dialog = gtk_message_dialog_new ((GtkWindow *) view, GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
- _("Could not create temporary mbox folder: %s"),
- camel_exception_get_description (&ex));
-
- gtk_dialog_run ((GtkDialog *) dialog);
- gtk_widget_destroy (dialog);
-
- camel_exception_clear (&ex);
- camel_object_unref (store);
- camel_object_unref (src);
- g_free (uri);
-
- return;
- }
-
- camel_object_unref (store);
- uids = camel_folder_get_uids (src);
-
- camel_folder_transfer_messages_to (src, uids, dest, NULL, FALSE, &ex);
- if (camel_exception_is_set (&ex)) {
- dialog = gtk_message_dialog_new ((GtkWindow *) view, GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
- _("Could not copy messages to temporary mbox folder: %s"),
- camel_exception_get_description (&ex));
-
- gtk_dialog_run ((GtkDialog *) dialog);
- gtk_widget_destroy (dialog);
-
- camel_folder_free_uids (src, uids);
- camel_exception_clear (&ex);
- camel_object_unref (dest);
- camel_object_unref (src);
- g_free (uri);
-
- return;
- }
-
- camel_folder_free_uids (src, uids);
- camel_object_unref (dest);
- camel_object_unref (src);
-
- memcpy (uri, "file", 4);
-
- gtk_selection_data_set (selection, selection->target, 8,
- uri, strlen (uri));
-
- g_free (uri);
-}
-
-static void
-folder_dragged_cb (EStorageSetView *view, const char *path, GdkDragContext *context,
- GtkSelectionData *selection, guint info, guint time, gpointer user_data)
-{
- printf ("dragging folder `%s'\n", path);
-
- switch (info) {
- case DND_DRAG_TYPE_FOLDER:
- /* dragging @path to a new location in the folder tree */
- gtk_selection_data_set (selection, selection->target, 8, path, strlen (path) + 1);
- break;
- case DND_DRAG_TYPE_TEXT_URI_LIST:
- /* dragging @path to some place external to evolution */
- drag_text_uri_list (view, path, selection, user_data);
- break;
- default:
- g_assert_not_reached ();
- }
-}
-
-static void
-drop_uid_list (EStorageSetView *view, const char *path, gboolean move, GtkSelectionData *selection, gpointer user_data)
-{
- CamelFolder *src, *dest;
- CamelException ex;
- GPtrArray *uids;
- char *src_uri;
-
- em_utils_selection_get_uidlist (selection, &src_uri, &uids);
-
- camel_exception_init (&ex);
-
- if (!(src = mail_tool_uri_to_folder (src_uri, 0, &ex))) {
- /* FIXME: report error to user? */
- camel_exception_clear (&ex);
- em_utils_uids_free (uids);
- g_free (src_uri);
- return;
- }
-
- g_free (src_uri);
-
- if (!(dest = foo_get_folder (view, path, &ex))) {
- /* FIXME: report error to user? */
- camel_exception_clear (&ex);
- em_utils_uids_free (uids);
- camel_object_unref (src);
- return;
- }
-
- camel_folder_transfer_messages_to (src, uids, dest, NULL, move, &ex);
- if (camel_exception_is_set (&ex)) {
- /* FIXME: report error to user? */
- camel_exception_clear (&ex);
- em_utils_uids_free (uids);
- camel_object_unref (dest);
- camel_object_unref (src);
- return;
- }
-
- em_utils_uids_free (uids);
- camel_object_unref (dest);
- camel_object_unref (src);
-}
-
-static void
-drop_folder (EStorageSetView *view, const char *path, gboolean move, GtkSelectionData *selection, gpointer user_data)
-{
- CamelFolder *src, *dest;
- CamelFolder *store;
- CamelException ex;
-
- camel_exception_init (&ex);
-
- /* get the destination folder (where the user dropped). this
- * will become the parent folder of the folder that got
- * dragged */
- if (!(dest = foo_get_folder (view, path, &ex))) {
- /* FIXME: report error to user? */
- camel_exception_clear (&ex);
- return;
- }
-
- /* get the folder being dragged */
- if (!(src = foo_get_folder (view, selection->data, &ex))) {
- /* FIXME: report error to user? */
- camel_exception_clear (&ex);
- camel_object_unref (dest);
- return;
- }
-
- if (src->parent_store == dest->parent_store && move) {
- /* simple rename() action */
- char *old_name, *new_name;
-
- old_name = g_strdup (src->full_name);
- new_name = g_strdup_printf ("%s/%s", dest->full_name, src->name);
- camel_object_unref (src);
-
- camel_store_rename_folder (dest->parent_store, old_name, new_name, &ex);
- if (camel_exception_is_set (&ex)) {
- /* FIXME: report error to user? */
- camel_exception_clear (&ex);
- camel_object_unref (dest);
- g_free (old_name);
- g_free (new_name);
- return;
- }
-
- camel_object_unref (dest);
- g_free (old_name);
- g_free (new_name);
- } else {
- /* copy the folder */
- camel_object_unref (dest);
- camel_object_unref (src);
- }
-}
-
-static gboolean
-import_message_rfc822 (CamelFolder *dest, CamelStream *stream, gboolean scan_from, CamelException *ex)
-{
- CamelMimeParser *mp;
-
- mp = camel_mime_parser_new ();
- camel_mime_parser_scan_from (mp, scan_from);
- camel_mime_parser_init_with_stream (mp, stream);
-
- while (camel_mime_parser_step (mp, 0, 0) == CAMEL_MIME_PARSER_STATE_FROM) {
- CamelMessageInfo *info;
- CamelMimeMessage *msg;
-
- msg = camel_mime_message_new ();
- if (camel_mime_part_construct_from_parser (CAMEL_MIME_PART (msg), mp) == -1) {
- camel_object_unref (msg);
- camel_object_unref (mp);
- return FALSE;
- }
-
- /* append the message to the folder... */
- info = g_new0 (CamelMessageInfo, 1);
- camel_folder_append_message (dest, msg, info, NULL, ex);
- camel_object_unref (msg);
-
- if (camel_exception_is_set (ex)) {
- camel_object_unref (mp);
- return FALSE;
- }
-
- /* skip over the FROM_END state */
- camel_mime_parser_step (mp, 0, 0);
- }
-
- camel_object_unref (mp);
-
- return TRUE;
-}
-
-static void
-drop_message_rfc822 (EStorageSetView *view, const char *path, GtkSelectionData *selection, gpointer user_data)
-{
- CamelFolder *folder;
- CamelStream *stream;
- CamelException ex;
- gboolean scan_from;
-
- camel_exception_init (&ex);
-
- if (!(folder = foo_get_folder (view, path, &ex))) {
- /* FIXME: report error to user? */
- camel_exception_clear (&ex);
- return;
- }
-
- scan_from = selection->length > 5 && !strncmp (selection->data, "From ", 5);
- stream = camel_stream_mem_new_with_buffer (selection->data, selection->length);
-
- if (!import_message_rfc822 (folder, stream, scan_from, &ex)) {
- /* FIXME: report to user? */
- }
-
- camel_exception_clear (&ex);
-
- camel_object_unref (stream);
- camel_object_unref (folder);
+ /* EPFIXME: This leaks the control. */
+ return bonobo_widget_new_control_from_objref (BONOBO_OBJREF (control), CORBA_OBJECT_NIL);
}
static void
-drop_text_uri_list (EStorageSetView *view, const char *path, GtkSelectionData *selection, gpointer user_data)
+folder_selected_cb (EMFolderTree *emft, const char *path, const char *uri, GtkBox *vbox)
{
- CamelFolder *folder;
- CamelStream *stream;
- CamelException ex;
- char **urls, *tmp;
- int i;
-
- camel_exception_init (&ex);
-
- if (!(folder = foo_get_folder (view, path, &ex))) {
- /* FIXME: report to user? */
- camel_exception_clear (&ex);
- return;
- }
-
- tmp = g_strndup (selection->data, selection->length);
- urls = g_strsplit (tmp, "\n", 0);
- g_free (tmp);
+ GtkWidget *view;
+ GList *l, *n;
- for (i = 0; urls[i] != NULL; i++) {
- CamelURL *uri;
- char *url;
- int fd;
-
- /* get the path component */
- url = g_strstrip (urls[i]);
- uri = camel_url_new (url, NULL);
- g_free (url);
-
- if (!uri || strcmp (uri->protocol, "file") != 0) {
- camel_url_free (uri);
- continue;
- }
-
- url = uri->path;
- uri->path = NULL;
- camel_url_free (uri);
-
- if ((fd = open (url, O_RDONLY)) == -1) {
- g_free (url);
- continue;
- }
-
- stream = camel_stream_fs_new_with_fd (fd);
- if (!import_message_rfc822 (folder, stream, TRUE, &ex)) {
- /* FIXME: report to user? */
- }
-
- camel_exception_clear (&ex);
- camel_object_unref (stream);
- g_free (url);
+ /* there should only ever be 1 child */
+ l = gtk_container_get_children (GTK_CONTAINER (vbox));
+ while (l != NULL) {
+ n = l->next;
+ gtk_widget_destroy (l->data);
+ g_list_free_1 (l);
+ l = n;
}
- camel_object_unref (folder);
- g_free (urls);
-}
-
-static void
-folder_receive_drop_cb (EStorageSetView *view, const char *path, GdkDragContext *context,
- GtkSelectionData *selection, guint info, guint time, gpointer user_data)
-{
- gboolean move = context->action == GDK_ACTION_MOVE;
-
- /* this means we are receiving no data */
- if (!selection->data || selection->length == -1)
- return;
-
- switch (info) {
- case DND_DROP_TYPE_UID_LIST:
- /* import a list of uids from another evo folder */
- drop_uid_list (view, path, move, selection, user_data);
- printf ("* dropped a x-uid-list\n");
- break;
- case DND_DROP_TYPE_FOLDER:
- /* rename a folder */
- drop_folder (view, path, move, selection, user_data);
- printf ("* dropped a x-folder\n");
- break;
- case DND_DROP_TYPE_MESSAGE_RFC822:
- /* import a message/rfc822 stream */
- drop_message_rfc822 (view, path, selection, user_data);
- printf ("* dropped a message/rfc822\n");
- break;
- case DND_DROP_TYPE_TEXT_URI_LIST:
- /* import an mbox, maildir, or mh folder? */
- drop_text_uri_list (view, path, selection, user_data);
- printf ("* dropped a text/uri-list\n");
- break;
- default:
- g_assert_not_reached ();
- }
+ view = create_view_widget (emft, path, uri);
+ gtk_widget_show (view);
- gtk_drag_finish (context, TRUE, TRUE, time);
+ gtk_box_pack_start_defaults (vbox, view);
}
@@ -879,49 +285,50 @@ static void
impl_dispose (GObject *object)
{
MailComponentPrivate *priv = MAIL_COMPONENT (object)->priv;
-
- if (priv->storage_set != NULL) {
- g_object_unref (priv->storage_set);
- priv->storage_set = NULL;
- }
-
- if (priv->folder_type_registry != NULL) {
- g_object_unref (priv->folder_type_registry);
- priv->folder_type_registry = NULL;
- }
-
+
if (priv->search_context != NULL) {
g_object_unref (priv->search_context);
priv->search_context = NULL;
}
-
+
if (priv->local_store != NULL) {
camel_object_unref (CAMEL_OBJECT (priv->local_store));
priv->local_store = NULL;
}
-
+
(* G_OBJECT_CLASS (parent_class)->dispose) (object);
}
static void
+store_hash_free (gpointer key, gpointer value, gpointer user_data)
+{
+ CamelStore *store = key;
+ char *name = value;
+
+ g_free (name);
+ camel_object_unref (store);
+}
+
+static void
impl_finalize (GObject *object)
{
MailComponentPrivate *priv = MAIL_COMPONENT (object)->priv;
-
+
g_free (priv->base_directory);
-
+
mail_async_event_destroy (priv->async_event);
-
- g_hash_table_destroy (priv->storages_hash); /* EPFIXME free the data within? */
-
+
+ g_hash_table_foreach (priv->store_hash, store_hash_free, NULL);
+ g_hash_table_destroy (priv->store_hash);
+
if (mail_async_event_destroy (priv->async_event) == -1) {
g_warning("Cannot destroy async event: would deadlock");
g_warning(" system may be unstable at exit");
}
-
- g_free(priv->context_path);
+
+ g_free (priv->context_path);
g_free (priv);
-
+
(* G_OBJECT_CLASS (parent_class)->finalize) (object);
}
@@ -930,45 +337,30 @@ impl_finalize (GObject *object)
static void
impl_createControls (PortableServer_Servant servant,
- Bonobo_Control *corba_sidebar_control,
+ Bonobo_Control *corba_tree_control,
Bonobo_Control *corba_view_control,
CORBA_Environment *ev)
{
MailComponent *mail_component = MAIL_COMPONENT (bonobo_object_from_servant (servant));
MailComponentPrivate *priv = mail_component->priv;
- EStorageBrowser *browser;
+ BonoboControl *tree_control;
+ BonoboControl *view_control;
GtkWidget *tree_widget;
- GtkWidget *tree_widget_scrolled;
GtkWidget *view_widget;
- BonoboControl *sidebar_control;
- BonoboControl *view_control;
-
- browser = e_storage_browser_new (priv->storage_set, "/", create_view_callback, NULL);
-
- tree_widget = e_storage_browser_peek_tree_widget (browser);
- tree_widget_scrolled = e_storage_browser_peek_tree_widget_scrolled (browser);
- view_widget = e_storage_browser_peek_view_widget (browser);
-
- e_storage_set_view_set_drag_types ((EStorageSetView *) tree_widget, drag_types, num_drag_types);
- e_storage_set_view_set_drop_types ((EStorageSetView *) tree_widget, drop_types, num_drop_types);
- e_storage_set_view_set_allow_dnd ((EStorageSetView *) tree_widget, TRUE);
- g_signal_connect (tree_widget, "folder_dragged", G_CALLBACK (folder_dragged_cb), browser);
- g_signal_connect (tree_widget, "folder_receive_drop", G_CALLBACK (folder_receive_drop_cb), browser);
+ tree_widget = (GtkWidget *) priv->emft;
+ view_widget = gtk_vbox_new (0, TRUE);
- gtk_widget_show (tree_widget_scrolled);
+ gtk_widget_show (tree_widget);
gtk_widget_show (view_widget);
-
- sidebar_control = bonobo_control_new (tree_widget_scrolled);
+
+ tree_control = bonobo_control_new (tree_widget);
view_control = bonobo_control_new (view_widget);
-
- *corba_sidebar_control = CORBA_Object_duplicate (BONOBO_OBJREF (sidebar_control), ev);
+
+ *corba_tree_control = CORBA_Object_duplicate (BONOBO_OBJREF (tree_control), ev);
*corba_view_control = CORBA_Object_duplicate (BONOBO_OBJREF (view_control), ev);
-
- g_signal_connect_object (browser, "page_switched",
- G_CALLBACK (browser_page_switched_callback), view_control, 0);
-
- g_signal_connect(tree_widget, "right_click", G_CALLBACK(emc_tree_right_click), mail_component);
+
+ g_signal_connect (tree_widget, "folder-selected", G_CALLBACK (folder_selected_cb), view_widget);
}
@@ -1042,14 +434,13 @@ mail_component_init (MailComponent *component)
if (camel_mkdir (priv->base_directory, 0777) == -1 && errno != EEXIST)
abort ();
+ priv->emft = em_folder_tree_new ();
+
/* EPFIXME: Turn into an object? */
mail_session_init (priv->base_directory);
priv->async_event = mail_async_event_new();
- priv->storages_hash = g_hash_table_new (NULL, NULL);
-
- priv->folder_type_registry = e_folder_type_registry_new ();
- priv->storage_set = e_storage_set_new (priv->folder_type_registry);
+ priv->store_hash = g_hash_table_new (NULL, NULL);
/* migrate evolution 1.x folders to 2.0's location/format */
mail_dir = g_strdup_printf ("%s/mail", priv->base_directory);
@@ -1218,35 +609,34 @@ store_disconnect (CamelStore *store,
void *data)
{
camel_service_disconnect (CAMEL_SERVICE (store), TRUE, NULL);
- camel_object_unref (CAMEL_OBJECT (store));
+ camel_object_unref (store);
}
void
-mail_component_remove_storage (MailComponent *component,
- CamelStore *store)
+mail_component_remove_storage (MailComponent *component, CamelStore *store)
{
MailComponentPrivate *priv = component->priv;
- EStorage *storage;
+ char *name;
- /* Because the storages_hash holds a reference to each store
+ /* Because the store_hash holds a reference to each store
* used as a key in it, none of them will ever be gc'ed, meaning
* any call to camel_session_get_{service,store} with the same
* URL will always return the same object. So this works.
*/
- storage = g_hash_table_lookup (priv->storages_hash, store);
- if (!storage)
+ if (!(name = g_hash_table_lookup (priv->store_hash, store)))
return;
- g_hash_table_remove (priv->storages_hash, store);
+ g_hash_table_remove (priv->store_hash, store);
+ g_free (name);
/* so i guess potentially we could have a race, add a store while one
being removed. ?? */
mail_note_store_remove (store);
-
- e_storage_set_remove_storage (priv->storage_set, storage);
- mail_async_event_emit(priv->async_event, MAIL_ASYNC_THREAD, (MailAsyncFunc) store_disconnect, store, NULL, NULL);
+ em_folder_tree_remove_store (priv->emft, store);
+
+ mail_async_event_emit (priv->async_event, MAIL_ASYNC_THREAD, (MailAsyncFunc) store_disconnect, store, NULL, NULL);
}
@@ -1272,46 +662,29 @@ mail_component_remove_storage_by_uri (MailComponent *component,
}
-EStorage *
-mail_component_lookup_storage (MailComponent *component,
- CamelStore *store)
-{
- EStorage *storage;
-
- /* Because the storages_hash holds a reference to each store
- * used as a key in it, none of them will ever be gc'ed, meaning
- * any call to camel_session_get_{service,store} with the same
- * URL will always return the same object. So this works.
- */
-
- storage = g_hash_table_lookup (component->priv->storages_hash, store);
- if (storage)
- g_object_ref (storage);
-
- return storage;
-}
-
-
int
mail_component_get_storage_count (MailComponent *component)
{
- return g_hash_table_size (component->priv->storages_hash);
+ return g_hash_table_size (component->priv->store_hash);
}
-EStorageSet *
-mail_component_peek_storage_set (MailComponent *component)
+void
+mail_component_storages_foreach (MailComponent *component, GHFunc func, void *user_data)
{
- return component->priv->storage_set;
+ g_hash_table_foreach (component->priv->store_hash, func, user_data);
}
-void
-mail_component_storages_foreach (MailComponent *component,
- GHFunc func,
- void *data)
+EMFolderTreeModel *
+mail_component_get_tree_model (MailComponent *component)
{
- g_hash_table_foreach (component->priv->storages_hash, func, data);
+ EMFolderTreeModel *model;
+
+ model = (EMFolderTreeModel *) gtk_tree_view_get_model ((GtkTreeView *) component->priv->emft);
+ g_object_ref (model);
+
+ return model;
}
extern struct _CamelSession *session;
@@ -1502,681 +875,3 @@ mail_component_evomail_uri_from_folder (MailComponent *component,
BONOBO_TYPE_FUNC_FULL (MailComponent, GNOME_Evolution_Component, PARENT_TYPE, mail_component)
-
-
-/* ********************************************************************** */
-#if 0
-static void
-emc_popup_view(GtkWidget *w, MailComponent *mc)
-{
-
-}
-
-static void
-emc_popup_open_new(GtkWidget *w, MailComponent *mc)
-{
-}
-#endif
-
-/* FIXME: This must be done in another thread */
-static void
-em_copy_folders(CamelStore *tostore, const char *tobase, CamelStore *fromstore, const char *frombase, int delete)
-{
- GString *toname, *fromname;
- CamelFolderInfo *fi;
- GList *pending = NULL, *deleting = NULL, *l;
- guint32 flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE;
- CamelException *ex = camel_exception_new();
- int fromlen;
- const char *tmp;
-
- if (camel_store_supports_subscriptions(fromstore))
- flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
-
- fi = camel_store_get_folder_info(fromstore, frombase, flags, ex);
- if (camel_exception_is_set(ex))
- goto done;
-
- pending = g_list_append(pending, fi);
-
- toname = g_string_new("");
- fromname = g_string_new("");
-
- tmp = strrchr(frombase, '/');
- if (tmp == NULL)
- fromlen = 0;
- else
- fromlen = tmp-frombase+1;
-
- printf("top name is '%s'\n", fi->full_name);
-
- while (pending) {
- CamelFolderInfo *info = pending->data;
-
- pending = g_list_remove_link(pending, pending);
- while (info) {
- CamelFolder *fromfolder, *tofolder;
- GPtrArray *uids;
-
- if (info->child)
- pending = g_list_append(pending, info->child);
- if (tobase[0])
- g_string_printf(toname, "%s/%s", tobase, info->full_name + fromlen);
- else
- g_string_printf(toname, "%s", info->full_name + fromlen);
-
- printf("Copying from '%s' to '%s'\n", info->full_name, toname->str);
-
- /* This makes sure we create the same tree, e.g. from a nonselectable source */
- /* Not sure if this is really the 'right thing', e.g. for spool stores, but it makes the ui work */
- if ((info->flags & CAMEL_FOLDER_NOSELECT) == 0) {
- printf("this folder is selectable\n");
- fromfolder = camel_store_get_folder(fromstore, info->full_name, 0, ex);
- if (fromfolder == NULL)
- goto exception;
-
- tofolder = camel_store_get_folder(tostore, toname->str, CAMEL_STORE_FOLDER_CREATE, ex);
- if (tofolder == NULL) {
- camel_object_unref(fromfolder);
- goto exception;
- }
-
- if (camel_store_supports_subscriptions(tostore)
- && !camel_store_folder_subscribed(tostore, toname->str))
- camel_store_subscribe_folder(tostore, toname->str, NULL);
-
- uids = camel_folder_get_uids(fromfolder);
- camel_folder_transfer_messages_to(fromfolder, uids, tofolder, NULL, delete, ex);
- camel_folder_free_uids(fromfolder, uids);
-
- camel_object_unref(fromfolder);
- camel_object_unref(tofolder);
- }
-
- if (camel_exception_is_set(ex))
- goto exception;
- else if (delete)
- deleting = g_list_prepend(deleting, info);
-
- info = info->sibling;
- }
- }
-
- /* delete the folders in reverse order from how we copyied them, if we are deleting any */
- l = deleting;
- while (l) {
- CamelFolderInfo *info = l->data;
-
- printf("deleting folder '%s'\n", info->full_name);
-
- if (camel_store_supports_subscriptions(fromstore))
- camel_store_unsubscribe_folder(fromstore, info->full_name, NULL);
-
- camel_store_delete_folder(fromstore, info->full_name, NULL);
- l = l->next;
- }
-
-exception:
- camel_store_free_folder_info(fromstore, fi);
- g_list_free(deleting);
-
- g_string_free(toname, TRUE);
- g_string_free(fromname, TRUE);
-done:
- printf("exception: %s\n", ex->desc?ex->desc:"<none>");
- camel_exception_free(ex);
-}
-
-struct _copy_folder_data {
- MailComponent *mc;
- int delete;
-};
-
-static void
-emc_popup_copy_folder_selected(const char *uri, void *data)
-{
- struct _copy_folder_data *d = data;
-
- if (uri == NULL) {
- g_free(d);
- return;
- }
-
- if (uri) {
- EFolder *folder = e_storage_set_get_folder(d->mc->priv->storage_set, d->mc->priv->context_path);
- CamelException *ex = camel_exception_new();
- CamelStore *fromstore, *tostore;
- char *tobase, *frombase;
- CamelURL *url;
-
- printf("copying folder '%s' to '%s'\n", d->mc->priv->context_path, uri);
-
- fromstore = camel_session_get_store(session, e_folder_get_physical_uri(folder), ex);
- frombase = strchr(d->mc->priv->context_path+1, '/')+1;
-
- tostore = camel_session_get_store(session, uri, ex);
- url = camel_url_new(uri, NULL);
- if (url->fragment)
- tobase = url->fragment;
- else if (url->path && url->path[0])
- tobase = url->path+1;
- else
- tobase = "";
-
- em_copy_folders(tostore, tobase, fromstore, frombase, d->delete);
-
- camel_url_free(url);
- camel_exception_free(ex);
- }
- g_free(d);
-}
-
-static void
-emc_popup_copy(GtkWidget *w, MailComponent *mc)
-{
- struct _copy_folder_data *d;
-
- d = g_malloc(sizeof(*d));
- d->mc = mc;
- d->delete = 0;
- em_select_folder(NULL, _("Select folder"), _("Select destination to copy folder into"), NULL, emc_popup_copy_folder_selected, d);
-}
-
-static void
-emc_popup_move(GtkWidget *w, MailComponent *mc)
-{
- struct _copy_folder_data *d;
-
- d = g_malloc(sizeof(*d));
- d->mc = mc;
- d->delete = 1;
- em_select_folder(NULL, _("Select folder"), _("Select destination to move folder into"), NULL, emc_popup_copy_folder_selected, d);
-}
-static void
-emc_popup_new_folder_create(EStorageSet *ess, EStorageResult result, void *data)
-{
- printf("folder created %s\n", result == E_STORAGE_OK?"ok":"failed");
-}
-
-static void
-emc_popup_new_folder_response(EMFolderSelector *emfs, guint response, MailComponent *mc)
-{
- if (response == GTK_RESPONSE_OK) {
- char *path, *tmp, *name, *full;
- EStorage *storage;
- CamelStore *store;
- CamelException *ex;
-
- printf("Creating folder: %s (%s)\n", em_folder_selector_get_selected(emfs),
- em_folder_selector_get_selected_uri(emfs));
-
- path = g_strdup(em_folder_selector_get_selected(emfs));
- tmp = strchr(path+1, '/');
- *tmp++ = 0;
- /* FIXME: camel_store_create_folder should just take full path names */
- full = g_strdup(tmp);
- name = strrchr(tmp, '/');
- if (name == NULL) {
- name = tmp;
- tmp = "";
- } else
- *name++ = 0;
-
- storage = e_storage_set_get_storage(mc->priv->storage_set, path+1);
- store = g_object_get_data((GObject *)storage, "em-store");
-
- printf("creating folder '%s' / '%s' on '%s'\n", tmp, name, path+1);
-
- ex = camel_exception_new();
- camel_store_create_folder(store, tmp, name, ex);
- if (camel_exception_is_set(ex)) {
- printf("Create failed: %s\n", ex->desc);
- } else if (camel_store_supports_subscriptions(store)) {
- camel_store_subscribe_folder(store, full, ex);
- if (camel_exception_is_set(ex)) {
- printf("Subscribe failed: %s\n", ex->desc);
- }
- }
-
- camel_exception_free(ex);
-
- g_free(full);
- g_free(path);
-
- /* Blah, this should just use camel, we get better error reporting if we do too */
- /*e_storage_set_async_create_folder(mc->priv->storage_set, path, "mail", "", emc_popup_new_folder_create, mc);*/
- }
- gtk_widget_destroy((GtkWidget *)emfs);
-}
-
-static void
-emc_popup_new_folder (GtkWidget *w, MailComponent *mc)
-{
- GtkWidget *dialog;
-
- dialog = em_folder_selector_create_new(mc->priv->storage_set, 0, _("Create folder"), _("Specify where to create the folder:"));
- em_folder_selector_set_selected((EMFolderSelector *)dialog, mc->priv->context_path);
- g_signal_connect(dialog, "response", G_CALLBACK(emc_popup_new_folder_response), mc);
- gtk_widget_show(dialog);
-}
-
-static void
-em_delete_rec(CamelStore *store, CamelFolderInfo *fi, CamelException *ex)
-{
- while (fi) {
- CamelFolder *folder;
-
- if (fi->child)
- em_delete_rec(store, fi->child, ex);
- if (camel_exception_is_set(ex))
- return;
-
- printf("deleting folder '%s'\n", fi->full_name);
-
- /* shouldn't camel do this itself? */
- if (camel_store_supports_subscriptions(store))
- camel_store_unsubscribe_folder(store, fi->full_name, NULL);
-
- folder = camel_store_get_folder(store, fi->full_name, 0, NULL);
- if (folder) {
- GPtrArray *uids = camel_folder_get_uids(folder);
- int i;
-
- camel_folder_freeze(folder);
- for (i = 0; i < uids->len; i++)
- camel_folder_delete_message(folder, uids->pdata[i]);
- camel_folder_sync(folder, TRUE, NULL);
- camel_folder_thaw(folder);
- camel_folder_free_uids(folder, uids);
- }
-
- camel_store_delete_folder(store, fi->full_name, ex);
- if (camel_exception_is_set(ex))
- return;
- fi = fi->sibling;
- }
-}
-
-static void
-em_delete_folders(CamelStore *store, const char *base, CamelException *ex)
-{
- CamelFolderInfo *fi;
- guint32 flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE;
-
- if (camel_store_supports_subscriptions(store))
- flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
-
- fi = camel_store_get_folder_info(store, base, flags, ex);
- if (camel_exception_is_set(ex))
- return;
-
- em_delete_rec(store, fi, ex);
- camel_store_free_folder_info(store, fi);
-}
-
-static void
-emc_popup_delete_response(GtkWidget *w, guint response, MailComponent *mc)
-{
- gtk_widget_destroy(w);
-
- if (response == GTK_RESPONSE_OK) {
- const char *path = strchr(mc->priv->context_path+1, '/')+1;
- EFolder *folder = e_storage_set_get_folder(mc->priv->storage_set, mc->priv->context_path);
- CamelException *ex = camel_exception_new();
- CamelStore *store;
-
- /* FIXME: need to hook onto store changed event and delete view as well, somewhere else tho */
- store = camel_session_get_store(session, e_folder_get_physical_uri(folder), ex);
- if (camel_exception_is_set(ex))
- goto exception;
-
- em_delete_folders(store, path, ex);
- if (!camel_exception_is_set(ex))
- goto noexception;
- exception:
- e_notice(NULL, GTK_MESSAGE_ERROR,
- _("Could not delete folder: %s"), ex->desc);
- noexception:
- camel_exception_free(ex);
- if (store)
- camel_object_unref(store);
- }
-}
-
-static void
-emc_popup_delete_folder(GtkWidget *w, MailComponent *mc)
-{
- GtkWidget *dialog;
- char *title;
- const char *path = strchr(mc->priv->context_path+1, '/')+1;
- EFolder *folder;
-
- folder = e_storage_set_get_folder(mc->priv->storage_set, mc->priv->context_path);
- if (folder == NULL)
- return;
-
- dialog = gtk_message_dialog_new(NULL,
- GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
- GTK_MESSAGE_QUESTION,
- GTK_BUTTONS_NONE,
- _("Really delete folder \"%s\" and all of its subfolders?"), path);
-
- gtk_dialog_add_button((GtkDialog *)dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
- gtk_dialog_add_button((GtkDialog *)dialog, GTK_STOCK_DELETE, GTK_RESPONSE_OK);
-
- gtk_dialog_set_default_response((GtkDialog *)dialog, GTK_RESPONSE_OK);
- gtk_container_set_border_width((GtkContainer *)dialog, 6);
- gtk_box_set_spacing((GtkBox *)((GtkDialog *)dialog)->vbox, 6);
-
- title = g_strdup_printf(_("Delete \"%s\""), path);
- gtk_window_set_title((GtkWindow *)dialog, title);
- g_free(title);
-
- g_signal_connect(dialog, "response", G_CALLBACK(emc_popup_delete_response), mc);
- gtk_widget_show(dialog);
-}
-
-static void
-emc_popup_rename_folder(GtkWidget *w, MailComponent *mc)
-{
- char *prompt, *new;
- EFolder *folder;
- const char *old, *why;
- int done = 0;
-
- folder = e_storage_set_get_folder(mc->priv->storage_set, mc->priv->context_path);
- if (folder == NULL)
- return;
-
- old = e_folder_get_name(folder);
- prompt = g_strdup_printf (_("Rename the \"%s\" folder to:"), e_folder_get_name(folder));
- while (!done) {
- new = e_request_string(NULL, _("Rename Folder"), prompt, old);
- if (new == NULL || strcmp(old, new) == 0)
- done = 1;
-#if 0
- else if (!e_shell_folder_name_is_valid(new, &why))
- e_notice(NULL, GTK_MESSAGE_ERROR, _("The specified folder name is not valid: %s"), why);
-#endif
- else {
- char *base, *path;
-
- /* FIXME: we can't use the os independent path crap here, since we want to control the format */
- base = g_path_get_dirname(mc->priv->context_path);
- path = g_build_filename(base, new, NULL);
-
- if (e_storage_set_get_folder(mc->priv->storage_set, path) != NULL) {
- e_notice(NULL, GTK_MESSAGE_ERROR,
- _("A folder named \"%s\" already exists. Please use a different name."), new);
- } else {
- CamelStore *store;
- CamelException *ex = camel_exception_new();
- const char *oldpath, *newpath;
-
- oldpath = strchr(mc->priv->context_path+1, '/');
- g_assert(oldpath);
- newpath = strchr(path+1, '/');
- g_assert(newpath);
- oldpath++;
- newpath++;
-
- printf("renaming %s to %s\n", oldpath, newpath);
-
- store = camel_session_get_store(session, e_folder_get_physical_uri(folder), ex);
- if (camel_exception_is_set(ex))
- goto exception;
-
- camel_store_rename_folder(store, oldpath, newpath, ex);
- if (!camel_exception_is_set(ex))
- goto noexception;
-
- exception:
- e_notice(NULL, GTK_MESSAGE_ERROR,
- _("Could not rename folder: %s"), ex->desc);
- noexception:
- if (store)
- camel_object_unref(store);
- camel_exception_free(ex);
-
- done = 1;
- }
- g_free(path);
- g_free(base);
- }
- g_free(new);
- }
-}
-
-struct _prop_data {
- void *object;
- CamelArgV *argv;
- GtkWidget **widgets;
-};
-
-static void
-emc_popup_properties_response(GtkWidget *dialog, int response, struct _prop_data *prop_data)
-{
- int i;
- CamelArgV *argv = prop_data->argv;
-
- if (response != GTK_RESPONSE_OK) {
- gtk_widget_destroy(dialog);
- return;
- }
-
- for (i=0;i<argv->argc;i++) {
- CamelArg *arg = &argv->argv[i];
-
- switch (arg->tag & CAMEL_ARG_TYPE) {
- case CAMEL_ARG_BOO:
- arg->ca_int = gtk_toggle_button_get_active ((GtkToggleButton *) prop_data->widgets[i]);
- break;
- case CAMEL_ARG_STR:
- g_free(arg->ca_str);
- arg->ca_str = gtk_entry_get_text ((GtkEntry *) prop_data->widgets[i]);
- break;
- default:
- printf("unknown property type set\n");
- }
- }
-
- camel_object_setv(prop_data->object, NULL, argv);
- gtk_widget_destroy(dialog);
-}
-
-static void
-emc_popup_properties_free(void *data)
-{
- struct _prop_data *prop_data = data;
- int i;
-
- 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_unref(prop_data->object);
- g_free(prop_data->argv);
- g_free(prop_data);
-}
-
-static void
-emc_popup_properties_got_folder (char *uri, CamelFolder *folder, void *data)
-{
- if (folder) {
- GtkWidget *dialog, *w, *table, *label;
- GSList *list, *l;
- char *name;
- int row = 1;
- gint32 count, i;
- struct _prop_data *prop_data;
- CamelArgV *argv;
- CamelArgGetV *arggetv;
-
- camel_object_get(folder, NULL, CAMEL_FOLDER_PROPERTIES, &list, CAMEL_FOLDER_NAME, &name, NULL);
-
- dialog = gtk_dialog_new_with_buttons(_("Folder properties"),
- NULL,
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_OK,
- GTK_RESPONSE_OK,
- NULL);
-
- /* TODO: maybe we want some basic properties here, like message counts/approximate size/etc */
- w = gtk_frame_new(_("Properties"));
- gtk_box_pack_start ((GtkBox *) ((GtkDialog *)dialog)->vbox, w, TRUE, TRUE, 6);
- table = gtk_table_new(g_slist_length(list)+1, 2, FALSE);
- gtk_container_add((GtkContainer *)w, table);
- label = gtk_label_new(_("Folder Name"));
- gtk_misc_set_alignment ((GtkMisc *) label, 1.0, 0.5);
- gtk_table_attach ((GtkTable *) table, label, 0, 1, 0, 1, GTK_FILL|GTK_EXPAND, 0, 3, 0);
- label = gtk_label_new(name);
- gtk_misc_set_alignment ((GtkMisc *) label, 0.0, 0.5);
- gtk_table_attach ((GtkTable *) table, label, 1, 2, 0, 1, GTK_FILL|GTK_EXPAND, 0, 3, 0);
-
- /* 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 = list;
- i = 0;
- while (l) {
- CamelProperty *prop = l->data;
-
- 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, argv->argv[i].ca_int != 0);
- gtk_table_attach ((GtkTable *) table, w, 0, 2, row, row+1, 0, 0, 3, 3);
- prop_data->widgets[i] = w;
- break;
- case CAMEL_ARG_STR:
- label = gtk_label_new(prop->description);
- gtk_misc_set_alignment ((GtkMisc *) label, 1.0, 0.5);
- gtk_table_attach ((GtkTable *) table, label, 0, 1, row, row+1, GTK_FILL|GTK_EXPAND, 0, 3, 3);
-
- w = gtk_entry_new();
- 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, 0, 3, 3);
- prop_data->widgets[i] = w;
- break;
- default:
- w = gtk_label_new("CamelFolder error: unsupported propery type");
- gtk_table_attach ((GtkTable *) table, w, 0, 2, row, row+1, 0, 0, 3, 3);
- break;
- }
-
- row++;
- l = l->next;
- }
-
- prop_data->object = folder;
- camel_object_ref(folder);
-
- camel_object_free(folder, CAMEL_FOLDER_PROPERTIES, list);
- camel_object_free(folder, CAMEL_FOLDER_NAME, name);
-
- /* we do 'apply on ok' ... since instant apply may apply some very long running tasks */
-
- g_signal_connect(dialog, "response", G_CALLBACK(emc_popup_properties_response), prop_data);
- g_object_set_data_full((GObject *)dialog, "e-prop-data", prop_data, emc_popup_properties_free);
- gtk_widget_show_all(dialog);
- }
-}
-
-static void
-emc_popup_properties(GtkWidget *w, MailComponent *mc)
-{
- EFolder *efolder;
-
- /* TODO: Make sure we only have one dialog open for any given folder */
-
- efolder = e_storage_set_get_folder(mc->priv->storage_set, mc->priv->context_path);
- if (efolder == NULL)
- return;
-
- mail_get_folder(e_folder_get_physical_uri(efolder), 0, emc_popup_properties_got_folder, mc, mail_thread_new);
-}
-
-static EMPopupItem emc_popup_menu[] = {
-#if 0
- { EM_POPUP_ITEM, "00.emc.00", N_("_View"), G_CALLBACK(emc_popup_view), NULL, NULL, 0 },
- { EM_POPUP_ITEM, "00.emc.01", N_("Open in _New Window"), G_CALLBACK(emc_popup_open_new), NULL, NULL, 0 },
-
- { EM_POPUP_BAR, "10.emc" },
-#endif
- { EM_POPUP_ITEM, "10.emc.00", N_("_Copy"), G_CALLBACK(emc_popup_copy), NULL, "folder-copy-16.png", 0 },
- { EM_POPUP_ITEM, "10.emc.01", N_("_Move"), G_CALLBACK(emc_popup_move), NULL, "folder-move-16.png", 0 },
-
- { EM_POPUP_BAR, "20.emc" },
- { EM_POPUP_ITEM, "20.emc.00", N_("_New Folder..."), G_CALLBACK(emc_popup_new_folder), NULL, "folder-mini.png", 0 },
- { EM_POPUP_ITEM, "20.emc.01", N_("_Delete"), G_CALLBACK(emc_popup_delete_folder), NULL, "evolution-trash-mini.png", 0 },
- { EM_POPUP_ITEM, "20.emc.01", N_("_Rename"), G_CALLBACK(emc_popup_rename_folder), NULL, NULL, 0 },
-
- { EM_POPUP_BAR, "80.emc" },
- { EM_POPUP_ITEM, "80.emc.00", N_("_Properties..."), G_CALLBACK(emc_popup_properties), NULL, "configure_16_folder.xpm", 0 },
-};
-
-
-static int
-emc_tree_right_click(ETree *tree, gint row, ETreePath path, gint col, GdkEvent *event, MailComponent *component)
-{
- char *name;
- ETreeModel *model = e_tree_get_model(tree);
- EMPopup *emp;
- int i;
- GSList *menus = NULL;
- struct _GtkMenu *menu;
-
- name = e_tree_memory_node_get_data((ETreeMemory *)model, path);
- g_free(component->priv->context_path);
- component->priv->context_path = g_strdup(name);
- printf("right click, path = '%s'\n", name);
-
- emp = em_popup_new("com.ximian.mail.storageset.popup.select");
-
- for (i=0;i<sizeof(emc_popup_menu)/sizeof(emc_popup_menu[0]);i++) {
- EMPopupItem *item = &emc_popup_menu[i];
-
- item->activate_data = component;
- menus = g_slist_prepend(menus, item);
- }
-
- em_popup_add_items(emp, menus, (GDestroyNotify)g_slist_free);
-
- menu = em_popup_create_menu_once(emp, NULL, 0, 0);
-
- if (event == NULL || event->type == GDK_KEY_PRESS) {
- /* FIXME: menu pos function */
- gtk_menu_popup(menu, NULL, NULL, NULL, NULL, 0, event->key.time);
- } else {
- gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event->button.button, event->button.time);
- }
-
- return TRUE;
-}
diff --git a/mail/mail-component.h b/mail/mail-component.h
index 0a31fdc815..818b8d2ff9 100644
--- a/mail/mail-component.h
+++ b/mail/mail-component.h
@@ -30,7 +30,7 @@
#include <filter/rule-context.h>
#include <bonobo/bonobo-object.h>
-#include "shell/e-storage-set.h"
+#include "em-folder-tree-model.h"
#include "Evolution.h"
@@ -48,13 +48,13 @@ typedef struct _MailComponentClass MailComponentClass;
struct _MailComponent {
BonoboObject parent;
-
+
MailComponentPrivate *priv;
};
struct _MailComponentClass {
BonoboObjectClass parent_class;
-
+
POA_GNOME_Evolution_Component__epv epv;
};
@@ -76,15 +76,14 @@ void mail_component_remove_storage (MailComponent *component,
CamelStore *store);
void mail_component_remove_storage_by_uri (MailComponent *component,
const char *uri);
-EStorage *mail_component_lookup_storage (MailComponent *component,
- CamelStore *store);
int mail_component_get_storage_count (MailComponent *component);
-EStorageSet *mail_component_peek_storage_set (MailComponent *component);
void mail_component_storages_foreach (MailComponent *component,
GHFunc func,
void *data);
+EMFolderTreeModel *mail_component_get_tree_model (MailComponent *component);
+
char *em_uri_from_camel (const char *curi);
char *em_uri_to_camel (const char *euri);
diff --git a/mail/mail-folder-cache.c b/mail/mail-folder-cache.c
index 05b006b777..23f6221544 100644
--- a/mail/mail-folder-cache.c
+++ b/mail/mail-folder-cache.c
@@ -98,8 +98,6 @@ struct _store_info {
CamelStore *store; /* the store for these folders */
- EStorage *storage;
-
/* Outstanding folderinfo requests */
EDList folderinfo_updates;
};
@@ -186,20 +184,12 @@ real_flush_updates(void *o, void *event_data, void *data)
{
struct _folder_update *up;
struct _store_info *si;
- EStorage *storage;
time_t now;
LOCK(info_lock);
while ((up = (struct _folder_update *)e_dlist_remhead(&updates))) {
si = g_hash_table_lookup(stores, up->store);
- if (si) {
- storage = si->storage;
- if (storage)
- g_object_ref (storage);
- } else {
- storage = NULL;
- }
-
+
UNLOCK(info_lock);
if (up->remove) {
@@ -207,20 +197,10 @@ real_flush_updates(void *o, void *event_data, void *data)
mail_vfolder_delete_uri(up->store, up->uri);
mail_filter_delete_uri(up->store, up->uri);
mail_config_uri_deleted(CAMEL_STORE_CLASS(CAMEL_OBJECT_GET_CLASS(up->store))->compare_folder_name, up->uri);
- if (up->unsub)
- e_storage_removed_folder (storage, up->path);
+
} else
mail_vfolder_add_uri(up->store, up->uri, TRUE);
} else {
- /* Its really a rename, but we have no way of telling the shell that, so remove it */
- if (up->oldpath) {
- if (storage != NULL) {
- d(printf("Removing old folder (rename?) '%s'\n", up->oldpath));
- e_storage_removed_folder(storage, up->oldpath);
- }
- /* ELSE? Shell supposed to handle the local snot case */
- }
-
/* We can tell the vfolder code though */
if (up->olduri && up->add) {
d(printf("renaming folder '%s' to '%s'\n", up->olduri, up->uri));
@@ -229,40 +209,7 @@ real_flush_updates(void *o, void *event_data, void *data)
mail_config_uri_renamed(CAMEL_STORE_CLASS(CAMEL_OBJECT_GET_CLASS(up->store))->compare_folder_name,
up->olduri, up->uri);
}
-
- if (up->name == NULL) {
- EFolder *folder = e_storage_get_folder (storage, up->path);
-
- if (folder != NULL) {
- d(printf("updating unread count to '%s' to %d\n", up->path, up->unread));
- e_folder_set_unread_count (folder, up->unread);
- } else {
- g_warning ("No folder at %s ?!", up->path);
- }
- } else if (storage != NULL) {
- char *type;
- EFolder *new_folder;
-
- if (strncmp(up->uri, "vtrash:", 7)==0) {
- type = "vtrash";
- } else if (strncmp(up->uri, "vjunk:", 6)==0) {
- type = "vjunk";
- } else
- type = "mail";
-
- new_folder = e_folder_new (up->name, type, NULL);
- d(printf("Adding new folder: %s\n", up->path));
-
- e_folder_set_physical_uri (new_folder, up->uri);
- e_folder_set_unread_count (new_folder, up->unread);
- if (CAMEL_IS_DISCO_STORE(up->store) && camel_disco_store_can_work_offline((CamelDiscoStore *)up->store))
- e_folder_set_can_sync_offline (new_folder, TRUE);
- else
- e_folder_set_can_sync_offline (new_folder, FALSE);
-
- e_storage_new_folder(storage, up->path, new_folder);
- }
-
+
if (!up->olduri && up->add)
mail_vfolder_add_uri(up->store, up->uri, FALSE);
}
@@ -285,9 +232,6 @@ real_flush_updates(void *o, void *event_data, void *data)
notify_idle_id = g_idle_add_full (G_PRIORITY_LOW, notify_idle_cb, NULL, NULL);
free_update(up);
-
- if (storage != NULL)
- g_object_unref (storage);
LOCK(info_lock);
}
@@ -429,9 +373,7 @@ setup_folder(CamelFolderInfo *fi, struct _store_info *si)
up = g_malloc0(sizeof(*up));
up->path = g_strdup(mfi->path);
- if (si->storage != NULL) {
- up->name = g_strdup(fi->name);
- }
+ up->name = g_strdup(fi->name);
up->uri = g_strdup(fi->url);
up->unread = (fi->unread_message_count==-1)?0:fi->unread_message_count;
up->store = si->store;
@@ -659,8 +601,7 @@ rename_folders(struct _store_info *si, const char *oldbase, const char *newbase,
g_free(old);
up->path = g_strdup(mfi->path);
- if (si->storage)
- up->name = g_strdup(fi->name);
+ up->name = g_strdup(fi->name);
up->uri = g_strdup(mfi->uri);
up->unread = fi->unread_message_count==-1?0:fi->unread_message_count;
up->store = si->store;
@@ -783,10 +724,7 @@ mail_note_store_remove(CamelStore *store)
mail_msg_cancel(ud->id);
ud = ud->next;
}
-
- /* This is the only gtk object we need to unref */
- mail_async_event_emit(mail_async_event, MAIL_ASYNC_GUI, (MailAsyncFunc)bonobo_object_unref, si->storage, 0, 0);
-
+
camel_object_unref(si->store);
g_hash_table_foreach(si->folders, (GHFunc)free_folder_info_hash, NULL);
g_hash_table_destroy(si->folders);
@@ -913,15 +851,13 @@ store_online_cb (CamelStore *store, void *data)
}
void
-mail_note_store(CamelStore *store, CamelOperation *op, EStorage *storage,
+mail_note_store(CamelStore *store, CamelOperation *op,
void (*done)(CamelStore *store, CamelFolderInfo *info, void *data), void *data)
{
struct _store_info *si;
struct _update_data *ud;
const char *buf;
guint timeout;
-
- g_return_if_fail (storage == NULL || E_IS_STORAGE (storage));
g_assert(CAMEL_IS_STORE(store));
g_assert(pthread_self() == mail_gui_thread);
@@ -941,15 +877,10 @@ mail_note_store(CamelStore *store, CamelOperation *op, EStorage *storage,
if (si == NULL) {
d(printf("Noting a new store: %p: %s\n", store, camel_url_to_string(((CamelService *)store)->url, 0)));
- /* FIXME: Need to ref the storages & store or something?? */
-
si = g_malloc0(sizeof(*si));
si->folders = g_hash_table_new(g_str_hash, g_str_equal);
si->folders_uri = g_hash_table_new(CAMEL_STORE_CLASS(CAMEL_OBJECT_GET_CLASS(store))->hash_folder_name,
CAMEL_STORE_CLASS(CAMEL_OBJECT_GET_CLASS(store))->compare_folder_name);
- si->storage = storage;
- if (storage != NULL)
- g_object_ref (storage);
si->store = store;
camel_object_ref((CamelObject *)store);
g_hash_table_insert(stores, store, si);
diff --git a/mail/mail-folder-cache.h b/mail/mail-folder-cache.h
index b9f8f44dfb..875579ad67 100644
--- a/mail/mail-folder-cache.h
+++ b/mail/mail-folder-cache.h
@@ -25,27 +25,27 @@
#ifndef _MAIL_FOLDER_CACHE_H
#define _MAIL_FOLDER_CACHE_H
-#include "e-storage.h"
+#include <camel/camel-store.h>
/* Add a store whose folders should appear in the shell
The folders are scanned from the store, and/or added at
runtime via the folder_created event */
void
-mail_note_store(CamelStore *store, CamelOperation *op, EStorage *storage,
- void (*done) (CamelStore *store, CamelFolderInfo *info, void *data),
- void *data);
+mail_note_store (CamelStore *store, CamelOperation *op,
+ void (*done) (CamelStore *store, CamelFolderInfo *info, void *data),
+ void *data);
/* de-note a store */
-void mail_note_store_remove(CamelStore *store);
+void mail_note_store_remove (CamelStore *store);
/* When a folder has been opened, notify it for watching.
The folder must have already been created on the store (which has already been noted)
before the folder can be opened
*/
-void mail_note_folder(CamelFolder *folder);
+void mail_note_folder (CamelFolder *folder);
/* Returns true if a folder is available (yet), and also sets *folderp (if supplied)
to a (referenced) copy of the folder if it has already been opened */
-int mail_note_get_folder_from_uri(const char *uri, CamelFolder **folderp);
+int mail_note_get_folder_from_uri (const char *uri, CamelFolder **folderp);
#endif
diff --git a/mail/mail-offline-handler.c b/mail/mail-offline-handler.c
index ce0bcf729f..5a39249765 100644
--- a/mail/mail-offline-handler.c
+++ b/mail/mail-offline-handler.c
@@ -271,7 +271,7 @@ storage_go_online (gpointer key, gpointer value, gpointer data)
if (service_is_relevant (CAMEL_SERVICE (store), FALSE)) {
mail_store_set_offline (store, FALSE, NULL, NULL);
- mail_note_store (store, NULL, NULL, NULL, NULL);
+ mail_note_store (store, NULL, NULL, NULL);
}
}
diff --git a/mail/mail-send-recv.c b/mail/mail-send-recv.c
index 6d70fe5047..193f7a0af4 100644
--- a/mail/mail-send-recv.c
+++ b/mail/mail-send-recv.c
@@ -42,8 +42,6 @@
#include "camel/camel-folder.h"
#include "camel/camel-operation.h"
-#include "evolution-storage.h"
-
#include "mail.h"
#include "mail-mt.h"
#include "mail-component.h"
@@ -664,19 +662,7 @@ receive_update_got_store (char *uri, CamelStore *store, void *data)
struct _send_info *info = data;
if (store) {
- EStorage *storage = mail_component_lookup_storage (mail_component_peek (), store);
-
- if (storage) {
- mail_note_store(store, info->cancel, storage, receive_update_done, info);
- /*bonobo_object_unref (BONOBO_OBJECT (storage));*/
- } else {
- /* If we get here, store must be an external
- * storage other than /local. (Eg, Exchange).
- * Do a get_folder_info just to force it to
- * update itself.
- */
- mail_get_folderinfo(store, info->cancel, receive_update_got_folderinfo, info);
- }
+ mail_get_folderinfo (store, info->cancel, receive_update_got_folderinfo, info);
} else {
receive_done ("", info);
}