From ca5c50ddfeda1a3a8aaaaa7e1a42ab4c34200283 Mon Sep 17 00:00:00 2001 From: Not Zed Date: Fri, 20 May 2005 13:12:05 +0000 Subject: Lots of work, filled out functions, cleaned up idl to make the data more 2005-05-20 Not Zed * Lots of work, filled out functions, cleaned up idl to make the data more useful, added a listener interface, etc. svn path=/trunk/; revision=29395 --- plugins/mail-remote/ChangeLog | 5 + plugins/mail-remote/Evolution-DataServer-Mail.idl | 74 ++++-- plugins/mail-remote/Makefile.am | 7 +- plugins/mail-remote/client.c | 101 +++++--- plugins/mail-remote/e-corba-utils.c | 10 + plugins/mail-remote/e-corba-utils.h | 4 + plugins/mail-remote/evolution-mail-folder.c | 21 +- plugins/mail-remote/evolution-mail-folder.h | 3 + plugins/mail-remote/evolution-mail-listener.c | 170 +++++++++++++ plugins/mail-remote/evolution-mail-listener.h | 52 ++++ plugins/mail-remote/evolution-mail-session.c | 181 ++++++++++++- plugins/mail-remote/evolution-mail-store.c | 293 +++++++++++++++++++--- plugins/mail-remote/evolution-mail-store.h | 5 + plugins/mail-remote/mail-remote.c | 8 +- 14 files changed, 825 insertions(+), 109 deletions(-) create mode 100644 plugins/mail-remote/evolution-mail-listener.c create mode 100644 plugins/mail-remote/evolution-mail-listener.h diff --git a/plugins/mail-remote/ChangeLog b/plugins/mail-remote/ChangeLog index f89a5d55f2..e144b4d7ac 100644 --- a/plugins/mail-remote/ChangeLog +++ b/plugins/mail-remote/ChangeLog @@ -1,3 +1,8 @@ +2005-05-20 Not Zed + + * Lots of work, filled out functions, cleaned up idl to make the + data more useful, added a listener interface, etc. + 2005-05-12 Not Zed * A remote mail interface plugin for evolution. diff --git a/plugins/mail-remote/Evolution-DataServer-Mail.idl b/plugins/mail-remote/Evolution-DataServer-Mail.idl index f6c15348ad..bcadaacd47 100644 --- a/plugins/mail-remote/Evolution-DataServer-Mail.idl +++ b/plugins/mail-remote/Evolution-DataServer-Mail.idl @@ -17,14 +17,40 @@ module Mail { string why; }; + exception FAILED { + string why; + }; + interface Folder; typedef sequence Folders; + struct FolderInfo { + string name; + string full_name; + Folder folder; + }; + typedef sequence FolderInfos; + interface Store; typedef sequence Stores; + struct StoreInfo { + string name; + string uid; + Store store; + }; + typedef sequence StoreInfos; + interface Session; + struct Message { + string uid; + string subject; + string to; + string from; + }; + typedef sequence Messages; + /* ********************************************************************** */ // NB: tiny subset of omg properties service typedef string PropertyName; @@ -37,13 +63,35 @@ module Mail { /* ********************************************************************** */ + enum ChangeType { + ADDED, + REMOVED, + CHANGED + }; + // ?? - interface Listener { - void storeAdded(in Store store); - void storeRemoved(in Store store); + struct SessionChange { + ChangeType type; + StoreInfos stores; + }; + typedef sequence SessionChanges; + + struct StoreChange { + ChangeType type; + Folders folders; + }; + typedef sequence StoreChanges; + + struct FolderChange { + ChangeType type; + Messages messages; + }; + typedef sequence FolderChanges; - void folderAdded(in Store store, in Folder folder); - void folderRemoved(in Store store, in Folder folder); + interface Listener : Bonobo::Unknown { + oneway void sessionChanged(in Session session, in SessionChange change); + oneway void storeChanged(in Session session, in Store store, in StoreChanges change); + oneway void folderChanged(in Session session, in Store store, in Folder folder, in FolderChanges changes); }; /* ********************************************************************** */ @@ -51,7 +99,7 @@ module Mail { interface Session : Bonobo::Unknown { boolean getProperties(in PropertyNames names, out Properties props); - Stores getStores(in string pattern); + StoreInfos getStores(in string pattern); void addListener(in Listener listener); void removeListener(in Listener listener); @@ -60,21 +108,13 @@ module Mail { interface Store : Bonobo::Unknown { boolean getProperties(in PropertyNames names, out Properties props); - Folders getFolders(in string pattern) - raises (NOT_SUPPORTED); + FolderInfos getFolders(in string pattern) + raises (NOT_SUPPORTED, FAILED); void sendMessage(in Bonobo::Stream msg, in string from, in string recipients) - raises (NOT_SUPPORTED); + raises (NOT_SUPPORTED, FAILED); }; - struct Message { - string uid; - string subject; - string to; - string from; - }; - - typedef sequence Messages; interface MessageIterator : Bonobo::Unknown { Messages next(in long limit); }; diff --git a/plugins/mail-remote/Makefile.am b/plugins/mail-remote/Makefile.am index 76c8b7b411..ccdcae2348 100644 --- a/plugins/mail-remote/Makefile.am +++ b/plugins/mail-remote/Makefile.am @@ -15,6 +15,8 @@ liborg_gnome_evolution_mail_remote_la_SOURCES = \ e-corba-utils.h \ evolution-mail-folder.c \ evolution-mail-folder.h \ + evolution-mail-listener.c \ + evolution-mail-listener.h \ evolution-mail-messageiterator.c \ evolution-mail-messageiterator.h \ evolution-mail-session.c \ @@ -30,7 +32,10 @@ client_SOURCES = \ client_LDADD = \ $(EVOLUTION_MAIL_LIBS) \ - liborg-gnome-evolution-mail-remote.la + evolution-mail-listener.o \ + Evolution-DataServer-Mail-common.o \ + Evolution-DataServer-Mail-stubs.o \ + Evolution-DataServer-Mail-skels.o noinst_PROGRAMS = \ client diff --git a/plugins/mail-remote/client.c b/plugins/mail-remote/client.c index d275de107d..c2e2427250 100644 --- a/plugins/mail-remote/client.c +++ b/plugins/mail-remote/client.c @@ -3,6 +3,10 @@ #include "Evolution-DataServer-Mail.h" +#include "evolution-mail-listener.h" + +static EvolutionMailListener *listener; + static GNOME_Evolution_Mail_Session get_session(void) { @@ -18,16 +22,26 @@ get_session(void) g_free(ior); } + if (sess != CORBA_OBJECT_NIL) { + listener = evolution_mail_listener_new(); + GNOME_Evolution_Mail_Session_addListener(sess, bonobo_object_corba_objref((BonoboObject *)listener), &ev); + if (ev._major != CORBA_NO_EXCEPTION) { + printf("AddListener failed: %s\n", ev._id); + CORBA_exception_free(&ev); + } + } + return sess; } -int main(int argc, char **argv) +static int domain(void *data) { GNOME_Evolution_Mail_Session sess; - GNOME_Evolution_Mail_Stores *stores; + GNOME_Evolution_Mail_StoreInfos *stores; + GNOME_Evolution_Mail_FolderInfos *folders; CORBA_Environment ev = { 0 }; + int i, j, f; - bonobo_init(&argc, argv); sess = get_session(); @@ -38,50 +52,71 @@ int main(int argc, char **argv) } printf("Got %d stores\n", stores->_length); - { + for (i=0;i_length;i++) { GNOME_Evolution_Mail_PropertyName namesarray[] = { "name", "uid" }; GNOME_Evolution_Mail_PropertyNames names = { - 1, 1, + 2, 2, namesarray, FALSE, }; GNOME_Evolution_Mail_Properties *props; - int i, j; - - for (i=0;i_length;i++) { - GNOME_Evolution_Mail_Store store = stores->_buffer[i]; - - printf("store %p\n", store); - - GNOME_Evolution_Mail_Store_getProperties(store, &names, &props, &ev); - if (ev._major != CORBA_NO_EXCEPTION) { - printf("getProperties failed\n"); - return 1; - } + GNOME_Evolution_Mail_Store store = stores->_buffer[i].store; + + printf("store %p '%s' uid '%s'\n", store, stores->_buffer[i].name, stores->_buffer[i].uid); + + GNOME_Evolution_Mail_Store_getProperties(store, &names, &props, &ev); + if (ev._major != CORBA_NO_EXCEPTION) { + printf("getProperties failed\n"); + return 1; + } - for (j=0;j_length;j++) { - printf(" %s = (%s)", props->_buffer[j].name, ORBit_tk_to_name(props->_buffer[j].value._type->kind)); - if (props->_buffer[j].value._type == TC_CORBA_string) { - printf(" '%s'\n", props->_buffer[j].value._value); - } else { - printf(" '%s' ", BONOBO_ARG_GET_STRING(&props->_buffer[j].value)); - printf(" \n"); - } + for (j=0;j_length;j++) { + printf(" %s = (%s)", props->_buffer[j].name, ORBit_tk_to_name(props->_buffer[j].value._type->kind)); + if (props->_buffer[j].value._type == TC_CORBA_string) { + printf(" '%s'\n", props->_buffer[j].value._value); + } else { + printf(" '%s' ", BONOBO_ARG_GET_STRING(&props->_buffer[j].value)); + printf(" \n"); } + } - CORBA_free(props); - - printf("attempt send mail to store\n"); - GNOME_Evolution_Mail_Store_sendMessage(store, NULL, "notzed@ximian.com", "notzed@novell.com, user@host", &ev); - if (ev._major != CORBA_NO_EXCEPTION) { - printf("sendmessage failed\n"); - /* FIXME:L leaks ex data? */ - CORBA_exception_init(&ev); + CORBA_free(props); +#if 0 + printf("attempt send mail to store\n"); + GNOME_Evolution_Mail_Store_sendMessage(store, NULL, "notzed@ximian.com", "notzed@novell.com, user@host", &ev); + if (ev._major != CORBA_NO_EXCEPTION) { + printf("sendmessage failed\n"); + /* FIXME:L leaks ex data? */ + CORBA_exception_init(&ev); + } +#endif + + folders = GNOME_Evolution_Mail_Store_getFolders(store, "", &ev); + if (ev._major != CORBA_NO_EXCEPTION) { + printf("getfolders failed\n"); + /* FIXME: leaks ex data? */ + CORBA_exception_free(&ev); + } else { + for (f = 0; f_length;f++) { + printf("folder %p full:'%s' name:'%s'\n", folders->_buffer[f].folder, folders->_buffer[f].full_name, folders->_buffer[f].name); } } } CORBA_free(stores); + + return 0; +} + +int main(int argc, char **argv) +{ + bonobo_init(&argc, argv); + + g_idle_add(domain, NULL); + + bonobo_main(); + + return 0; } diff --git a/plugins/mail-remote/e-corba-utils.c b/plugins/mail-remote/e-corba-utils.c index c9f18d0313..d10c95e771 100644 --- a/plugins/mail-remote/e-corba-utils.c +++ b/plugins/mail-remote/e-corba-utils.c @@ -1,6 +1,8 @@ #include "e-corba-utils.h" +#include "evolution-mail-store.h" + void e_mail_property_set_string(GNOME_Evolution_Mail_Property *prop, const char *name, const char *val) { @@ -19,3 +21,11 @@ e_mail_property_set_null(GNOME_Evolution_Mail_Property *prop, const char *name) prop->name = CORBA_string_dup(name); } +void +e_mail_storeinfo_set_store(GNOME_Evolution_Mail_StoreInfo *si, EvolutionMailStore *store) +{ + si->name = CORBA_string_dup(evolution_mail_store_get_name(store)); + si->uid = CORBA_string_dup(evolution_mail_store_get_uid(store)); + si->store = CORBA_Object_duplicate(bonobo_object_corba_objref((BonoboObject *)store), NULL); +} + diff --git a/plugins/mail-remote/e-corba-utils.h b/plugins/mail-remote/e-corba-utils.h index 3e86c49224..52b76b2255 100644 --- a/plugins/mail-remote/e-corba-utils.h +++ b/plugins/mail-remote/e-corba-utils.h @@ -4,7 +4,11 @@ #include "Evolution-DataServer-Mail.h" +struct _EvolutionMailStore; + void e_mail_property_set_string(GNOME_Evolution_Mail_Property *prop, const char *name, const char *val); void e_mail_property_set_null(GNOME_Evolution_Mail_Property *prop, const char *name); +void e_mail_storeinfo_set_store(GNOME_Evolution_Mail_StoreInfo *si, struct _EvolutionMailStore *store); + #endif /* !_E_CORBA_UTILS_H */ diff --git a/plugins/mail-remote/evolution-mail-folder.c b/plugins/mail-remote/evolution-mail-folder.c index b7bba2a5cb..d85ab7de08 100644 --- a/plugins/mail-remote/evolution-mail-folder.c +++ b/plugins/mail-remote/evolution-mail-folder.c @@ -44,8 +44,7 @@ static BonoboObjectClass *parent_class = NULL; #define _PRIVATE(o) (g_type_instance_get_private ((GTypeInstance *)o, evolution_mail_folder_get_type())) struct _EvolutionMailFolderPrivate { - char *full_name; - char *name; + int dummy; }; /* GObject methods */ @@ -59,10 +58,14 @@ impl_dispose (GObject *object) static void impl_finalize (GObject *object) { + EvolutionMailFolder *emf = (EvolutionMailFolder *)object; struct _EvolutionMailFolderPrivate *p = _PRIVATE(object); - g_free(p->full_name); - g_free(p->name); + p = p; + g_warning("EvolutionMailFolder is finalised!\n"); + + g_free(emf->full_name); + g_free(emf->name); (* G_OBJECT_CLASS (parent_class)->finalize) (object); } @@ -78,7 +81,6 @@ impl_getProperties(PortableServer_Servant _servant, EvolutionMailFolder *emf = (EvolutionMailFolder *)bonobo_object_from_servant(_servant); int i; GNOME_Evolution_Mail_Properties *props; - struct _EvolutionMailFolderPrivate *p = _PRIVATE(emf); CORBA_boolean ok = CORBA_TRUE; *propsp = props = GNOME_Evolution_Mail_Properties__alloc(); @@ -95,10 +97,10 @@ impl_getProperties(PortableServer_Servant _servant, if (!strcmp(name, "name")) { prop->value._type = TC_CORBA_string; - prop->value._value = CORBA_string_dup(p->name); + prop->value._value = CORBA_string_dup(emf->name); } else if (!strcmp(name, "full_name")) { prop->value._type = TC_CORBA_string; - prop->value._value = CORBA_string_dup(p->full_name); + prop->value._value = CORBA_string_dup(emf->full_name); } else { prop->value._type = TC_null; ok = CORBA_FALSE; @@ -139,10 +141,9 @@ EvolutionMailFolder * evolution_mail_folder_new(const char *name, const char *full_name) { EvolutionMailFolder *emf = g_object_new (EVOLUTION_MAIL_TYPE_FOLDER, NULL); - struct _EvolutionMailFolderPrivate *p = _PRIVATE(emf); - p->name = g_strdup(name); - p->full_name = g_strdup(full_name); + emf->name = g_strdup(name); + emf->full_name = g_strdup(full_name); return emf; } diff --git a/plugins/mail-remote/evolution-mail-folder.h b/plugins/mail-remote/evolution-mail-folder.h index 02bc0aa26a..40f6139d79 100644 --- a/plugins/mail-remote/evolution-mail-folder.h +++ b/plugins/mail-remote/evolution-mail-folder.h @@ -38,6 +38,9 @@ typedef struct _EvolutionMailFolderClass EvolutionMailFolderClass; struct _EvolutionMailFolder { BonoboObject parent; + + char *full_name; + char *name; }; struct _EvolutionMailFolderClass { diff --git a/plugins/mail-remote/evolution-mail-listener.c b/plugins/mail-remote/evolution-mail-listener.c new file mode 100644 index 0000000000..26dac759ee --- /dev/null +++ b/plugins/mail-remote/evolution-mail-listener.c @@ -0,0 +1,170 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* + * Copyright (C) 2005 Novell, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Michael Zucchi + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include "evolution-mail-listener.h" + +#include + +#include "evolution-mail-store.h" + +#define PARENT_TYPE bonobo_object_get_type () + +static BonoboObjectClass *parent_class = NULL; + +#define _PRIVATE(o) (g_type_instance_get_private ((GTypeInstance *)o, evolution_mail_listener_get_type())) + +struct _EvolutionMailListenerPrivate { + int dummy; +}; + +/* GObject methods */ + +static void +impl_dispose (GObject *object) +{ + struct _EvolutionMailListenerPrivate *p = _PRIVATE(object); + + p = p; + + (* G_OBJECT_CLASS (parent_class)->dispose) (object); +} + +static void +impl_finalize (GObject *object) +{ + (* G_OBJECT_CLASS (parent_class)->finalize) (object); +} + +/* Evolution.Mail.Listener */ + +static void +impl_sessionChanged(PortableServer_Servant _servant, + const GNOME_Evolution_Mail_Session session, + const GNOME_Evolution_Mail_SessionChange *change, CORBA_Environment * ev) +{ + EvolutionMailListener *ems = (EvolutionMailListener *)bonobo_object_from_servant(_servant); + const char *what; + int i; + + printf("session changed!\n"); + ems = ems; + + switch (change->type) { + case GNOME_Evolution_Mail_ADDED: + what = "added"; + break; + case GNOME_Evolution_Mail_CHANGED: + what = "changed"; + break; + case GNOME_Evolution_Mail_REMOVED: + what = "removed"; + break; + } + + printf("%d %s\n", change->stores._length, what); + for (i=0;istores._length;i++) { + printf("Store '%s' '%s'\n", change->stores._buffer[i].name, change->stores._buffer[i].uid); + } +} + +static void +impl_storeChanged(PortableServer_Servant _servant, + const GNOME_Evolution_Mail_Session session, + const GNOME_Evolution_Mail_Store store, + const GNOME_Evolution_Mail_StoreChanges * changes, + CORBA_Environment * ev) +{ + EvolutionMailListener *ems = (EvolutionMailListener *)bonobo_object_from_servant(_servant); + + printf("store changed!\n"); + ems = ems; +} + +static void +impl_folderChanged(PortableServer_Servant _servant, + const GNOME_Evolution_Mail_Session session, + const GNOME_Evolution_Mail_Store store, + const GNOME_Evolution_Mail_Folder folder, + const GNOME_Evolution_Mail_FolderChanges *changes, CORBA_Environment * ev) +{ + EvolutionMailListener *ems = (EvolutionMailListener *)bonobo_object_from_servant(_servant); + + printf("folder changed!\n"); + ems = ems; +} + +/* Initialization */ + +static void +evolution_mail_listener_class_init (EvolutionMailListenerClass *klass) +{ + POA_GNOME_Evolution_Mail_Listener__epv *epv = &klass->epv; + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + epv->sessionChanged = impl_sessionChanged; + epv->storeChanged = impl_storeChanged; + epv->folderChanged = impl_folderChanged; + + object_class->dispose = impl_dispose; + object_class->finalize = impl_finalize; + + g_type_class_add_private(klass, sizeof(struct _EvolutionMailListenerPrivate)); +} + +static void +evolution_mail_listener_init (EvolutionMailListener *ems, EvolutionMailListenerClass *klass) +{ + struct _EvolutionMailListenerPrivate *p = _PRIVATE(ems); + + p = p; +} + +EvolutionMailListener * +evolution_mail_listener_new(void) +{ + EvolutionMailListener *eml; +#if 0 + static PortableServer_POA poa = NULL; + + /* NB: to simplify signal handling, we should only run in the idle loop? */ + + if (poa == NULL) + poa = bonobo_poa_get_threaded (ORBIT_THREAD_HINT_PER_REQUEST, NULL); + eml = g_object_new(evolution_mail_listener_get_type(), "poa", poa, NULL); +#else + eml = g_object_new(evolution_mail_listener_get_type(), NULL); +#endif + return eml; +} + +BONOBO_TYPE_FUNC_FULL (EvolutionMailListener, GNOME_Evolution_Mail_Listener, PARENT_TYPE, evolution_mail_listener) diff --git a/plugins/mail-remote/evolution-mail-listener.h b/plugins/mail-remote/evolution-mail-listener.h new file mode 100644 index 0000000000..c33d605c61 --- /dev/null +++ b/plugins/mail-remote/evolution-mail-listener.h @@ -0,0 +1,52 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* + * Copyright (C) 2005 Novell, Inc. + * + * Author: Michael Zucchi + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef _EVOLUTION_MAIL_LISTENER_H_ +#define _EVOLUTION_MAIL_LISTENER_H_ + +#include +#include "Evolution-DataServer-Mail.h" + +#define EVOLUTION_MAIL_TYPE_LISTENER (evolution_mail_listener_get_type ()) +#define EVOLUTION_MAIL_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EVOLUTION_MAIL_TYPE_LISTENER, EvolutionMailListener)) +#define EVOLUTION_MAIL_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EVOLUTION_MAIL_TYPE_LISTENER, EvolutionMailListenerClass)) +#define EVOLUTION_MAIL_IS_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EVOLUTION_MAIL_TYPE_LISTENER)) +#define EVOLUTION_MAIL_IS_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EVOLUTION_MAIL_TYPE_LISTENER)) + +typedef struct _EvolutionMailListener EvolutionMailListener; +typedef struct _EvolutionMailListenerClass EvolutionMailListenerClass; + +struct _EvolutionMailListener { + BonoboObject parent; +}; + +struct _EvolutionMailListenerClass { + BonoboObjectClass parent_class; + + POA_GNOME_Evolution_Mail_Listener__epv epv; +}; + +GType evolution_mail_listener_get_type(void); + +EvolutionMailListener *evolution_mail_listener_new(void); + +#endif /* _EVOLUTION_MAIL_LISTENER_H_ */ diff --git a/plugins/mail-remote/evolution-mail-session.c b/plugins/mail-remote/evolution-mail-session.c index 90c989838d..7f1e854f1a 100644 --- a/plugins/mail-remote/evolution-mail-session.c +++ b/plugins/mail-remote/evolution-mail-session.c @@ -16,7 +16,7 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * - * Author: JP Rosevear + * Author: Michael Zucchi */ #ifdef HAVE_CONFIG_H @@ -31,9 +31,10 @@ #include #include "evolution-mail-session.h" -#include +#include #include "evolution-mail-store.h" +#include "e-corba-utils.h" #include @@ -49,8 +50,26 @@ static BonoboObjectClass *parent_class = NULL; struct _EvolutionMailSessionPrivate { EAccountList *accounts; GList *stores; + + /* FIXME: locking */ + GSList *listeners; + + guint account_added; + guint account_changed; + guint account_removed; }; +static int +is_storage(EAccount *ea) +{ + const char *uri; + CamelProvider *prov; + + return(uri = e_account_get_string(ea, E_ACCOUNT_SOURCE_URL)) + && (prov = camel_provider_get(uri, NULL)) + && (prov->flags & CAMEL_PROVIDER_IS_STORAGE); +} + /* GObject methods */ static void @@ -70,6 +89,8 @@ impl_dispose (GObject *object) static void impl_finalize (GObject *object) { + g_warning("EvolutionMailStore is finalised!\n"); + (* G_OBJECT_CLASS (parent_class)->finalize) (object); } @@ -88,18 +109,18 @@ impl_getProperties(PortableServer_Servant _servant, return CORBA_TRUE; } -static GNOME_Evolution_Mail_Stores * +static GNOME_Evolution_Mail_StoreInfos * impl_getStores(PortableServer_Servant _servant, const CORBA_char * pattern, CORBA_Environment * ev) { EvolutionMailSession *ems = (EvolutionMailSession *)bonobo_object_from_servant(_servant); struct _EvolutionMailSessionPrivate *p = _PRIVATE(ems); - GNOME_Evolution_Mail_Stores *seq; + GNOME_Evolution_Mail_StoreInfos *seq; int i, len; GList *l; - seq = GNOME_Evolution_Mail_Stores__alloc(); + seq = GNOME_Evolution_Mail_StoreInfos__alloc(); /* FIXME: pattern? */ @@ -107,20 +128,49 @@ impl_getStores(PortableServer_Servant _servant, seq->_length = len; seq->_maximum = len; - seq->_buffer = GNOME_Evolution_Mail_Stores_allocbuf(seq->_length); + seq->_buffer = GNOME_Evolution_Mail_StoreInfos_allocbuf(seq->_length); CORBA_sequence_set_release(seq, TRUE); l = p->stores; for (i=0;l && i_buffer[i] = bonobo_object_corba_objref(l->data); - bonobo_object_ref(l->data); /* ?? */ + EvolutionMailStore *store = l->data; + + e_mail_storeinfo_set_store(&seq->_buffer[i], store); l = g_list_next(l); } return seq; } +static void +impl_addListener(PortableServer_Servant _servant, + const GNOME_Evolution_Mail_Listener listener, + CORBA_Environment * ev) +{ + EvolutionMailSession *ems = (EvolutionMailSession *)bonobo_object_from_servant(_servant); + struct _EvolutionMailSessionPrivate *p = _PRIVATE(ems); + + printf("Adding listener to session\n"); + + p->listeners = g_slist_append(p->listeners, CORBA_Object_duplicate(listener, ev)); +} + +static void +impl_removeListener(PortableServer_Servant _servant, + const GNOME_Evolution_Mail_Listener listener, + CORBA_Environment * ev) +{ + EvolutionMailSession *ems = (EvolutionMailSession *)bonobo_object_from_servant(_servant); + struct _EvolutionMailSessionPrivate *p = _PRIVATE(ems); + + printf("Removing listener from session\n"); + + /* FIXME: need to use proper comparison function & free stuff, this works with orbit though */ + p->listeners = g_slist_remove(p->listeners, listener); + CORBA_Object_release(listener, ev); +} + /* Initialization */ static void @@ -134,20 +184,120 @@ evolution_mail_session_class_init (EvolutionMailSessionClass *klass) epv->getProperties = impl_getProperties; epv->getStores = impl_getStores; + epv->addListener = impl_addListener; + epv->removeListener = impl_removeListener; + object_class->dispose = impl_dispose; object_class->finalize = impl_finalize; g_type_class_add_private(klass, sizeof(struct _EvolutionMailSessionPrivate)); } +static void +ems_listener_event(EvolutionMailSession *ems, GNOME_Evolution_Mail_ChangeType how, EvolutionMailStore *store) +{ + struct _EvolutionMailSessionPrivate *p = _PRIVATE(ems); + GNOME_Evolution_Mail_SessionChange *change; + GSList *l; + + for (l=p->listeners;l;l=g_slist_next(l)) { + CORBA_Environment ev; + + change = GNOME_Evolution_Mail_SessionChange__alloc(); + change->type = how; + + change->stores._length = 1; + change->stores._maximum = 1; + change->stores._buffer = GNOME_Evolution_Mail_StoreInfos_allocbuf(change->stores._maximum); + CORBA_sequence_set_release(&change->stores, TRUE); + e_mail_storeinfo_set_store(&change->stores._buffer[0], store); + + GNOME_Evolution_Mail_Listener_sessionChanged(l->data, bonobo_object_corba_objref((BonoboObject *)ems), change, &ev); + if (ev._major != CORBA_NO_EXCEPTION) { + printf("listener.sessionChanged() failed: %s\n", ev._id); + /* TODO: if it fails, remove the listener? */ + CORBA_exception_free(&ev); + } else { + printf("listener.sessionChanged() successful\n"); + } + } +} + +static void +ems_account_added(EAccountList *eal, EAccount *ea, EvolutionMailSession *ems) +{ + struct _EvolutionMailSessionPrivate *p = _PRIVATE(ems); + + if (ea->enabled && is_storage(ea)) { + EvolutionMailStore *store; + + printf("Account added %s\n", ea->uid); + store = evolution_mail_store_new(ems, ea); + p->stores = g_list_append(p->stores, store); + ems_listener_event(ems, GNOME_Evolution_Mail_ADDED, store); + } +} + +static void +ems_account_changed(EAccountList *eal, EAccount *ea, EvolutionMailSession *ems) +{ + struct _EvolutionMailSessionPrivate *p = _PRIVATE(ems); + EvolutionMailStore *store = NULL; + GList *l; + + for (l = p->stores;l;l=l->next) { + if (((EvolutionMailStore *)l->data)->account == ea) { + store = l->data; + break; + } + } + + if (store) { + /* account has been disabled? */ + if (!ea->enabled) { + printf("Account changed, now disabled %s\n", ea->uid); + p->stores = g_list_remove(p->stores, store); + ems_listener_event(ems, GNOME_Evolution_Mail_REMOVED, store); + g_object_unref(store); + } else { + printf("Account changed, dont know how %s\n", ea->uid); + ems_listener_event(ems, GNOME_Evolution_Mail_CHANGED, store); + } + } else if (ea->enabled && is_storage(ea)) { + printf("Account changed, now added %s\n", ea->uid); + store = evolution_mail_store_new(ems, ea); + p->stores = g_list_append(p->stores, store); + ems_listener_event(ems, GNOME_Evolution_Mail_ADDED, store); + } +} + +static void +ems_account_removed(EAccountList *eal, EAccount *ea, EvolutionMailSession *ems) +{ + struct _EvolutionMailSessionPrivate *p = _PRIVATE(ems); + GList *l; + + /* for accounts we dont have, we dont care */ + + for (l = p->stores;l;l=l->next) { + EvolutionMailStore *store = l->data; + + if (store->account == ea) { + printf("Account removed %s\n", ea->uid); + p->stores = g_list_remove(p->stores, store); + ems_listener_event(ems, GNOME_Evolution_Mail_REMOVED, store); + g_object_unref(store); + break; + } + } +} + static void evolution_mail_session_init (EvolutionMailSession *ems, EvolutionMailSessionClass *klass) { GConfClient *gconf = gconf_client_get_default(); struct _EvolutionMailSessionPrivate *p = _PRIVATE(ems); EIterator *iter; - EvolutionMailStore *store; - extern CamelSession *session; /* FIXME: listen to changes */ @@ -160,8 +310,9 @@ evolution_mail_session_init (EvolutionMailSession *ems, EvolutionMailSessionClas EAccount *ea; if ((ea = (EAccount *)e_iterator_get(iter)) - && (store = evolution_mail_store_new(ems, (struct _EAccount *)ea))) { - p->stores = g_list_append(p->stores, store); + && ea->enabled + && is_storage(ea)) { + p->stores = g_list_append(p->stores, evolution_mail_store_new(ems, ea)); } e_iterator_next(iter); @@ -170,7 +321,11 @@ evolution_mail_session_init (EvolutionMailSession *ems, EvolutionMailSessionClas g_object_unref(gconf); - ems->session = session; + p->account_added = g_signal_connect(p->accounts, "account_added", G_CALLBACK(ems_account_added), ems); + p->account_changed = g_signal_connect(p->accounts, "account_changed", G_CALLBACK(ems_account_changed), ems); + p->account_removed = g_signal_connect(p->accounts, "account_removed", G_CALLBACK(ems_account_removed), ems); + + ems->session = mail_component_peek_session(NULL); } BONOBO_TYPE_FUNC_FULL (EvolutionMailSession, GNOME_Evolution_Mail_Session, PARENT_TYPE, evolution_mail_session) diff --git a/plugins/mail-remote/evolution-mail-store.c b/plugins/mail-remote/evolution-mail-store.c index d287c736bb..30d7b75cff 100644 --- a/plugins/mail-remote/evolution-mail-store.c +++ b/plugins/mail-remote/evolution-mail-store.c @@ -30,9 +30,11 @@ #include #include #include +#include -#include "evolution-mail-store.h" #include "evolution-mail-session.h" +#include "evolution-mail-store.h" +#include "evolution-mail-folder.h" #include "e-corba-utils.h" @@ -41,6 +43,8 @@ #include +#include "mail/mail-component.h" + #define FACTORY_ID "OAFIID:GNOME_Evolution_Mail_Store_Factory:" BASE_VERSION #define MAIL_STORE_ID "OAFIID:GNOME_Evolution_Mail_Store:" BASE_VERSION @@ -51,10 +55,19 @@ static BonoboObjectClass *parent_class = NULL; #define _PRIVATE(o) (g_type_instance_get_private ((GTypeInstance *)o, evolution_mail_store_get_type())) struct _EvolutionMailStorePrivate { - struct _EAccount *account; - CamelStore *store; EvolutionMailSession *session; + + GHashTable *folders; + /* sorted array of folders by full_name */ + GPtrArray *folders_array; + + guint32 folder_opened; + guint32 folder_created; + guint32 folder_deleted; + guint32 folder_renamed; + guint32 folder_subscribed; + guint32 folder_unsubscribed; }; /* GObject methods */ @@ -62,11 +75,17 @@ struct _EvolutionMailStorePrivate { static void impl_dispose (GObject *object) { + EvolutionMailStore *ems = (EvolutionMailStore *)object; struct _EvolutionMailStorePrivate *p = _PRIVATE(object); - if (p->account) { - g_object_unref(p->account); - p->account = NULL; + p = p; + + /* FIXME: unref store + unhook events */ + + if (ems->account) { + g_object_unref(ems->account); + ems->account = NULL; } (* G_OBJECT_CLASS (parent_class)->dispose) (object); @@ -75,6 +94,17 @@ impl_dispose (GObject *object) static void impl_finalize (GObject *object) { + struct _EvolutionMailStorePrivate *p = _PRIVATE(object); + + g_warning("EvolutionMailStore is finalised!\n"); + + if (p->folders) { + /* FIXME: bonobo unref? */ + g_hash_table_foreach(p->folders, (GHFunc)g_object_unref, NULL); + g_hash_table_destroy(p->folders); + g_ptr_array_free(p->folders_array, TRUE); + } + (* G_OBJECT_CLASS (parent_class)->finalize) (object); } @@ -89,7 +119,7 @@ impl_getProperties(PortableServer_Servant _servant, EvolutionMailStore *ems = (EvolutionMailStore *)bonobo_object_from_servant(_servant); int i; GNOME_Evolution_Mail_Properties *props; - struct _EvolutionMailStorePrivate *p = _PRIVATE(ems); + /*struct _EvolutionMailStorePrivate *p = _PRIVATE(ems);*/ CORBA_boolean ok = CORBA_TRUE; *propsp = props = GNOME_Evolution_Mail_Properties__alloc(); @@ -101,23 +131,13 @@ impl_getProperties(PortableServer_Servant _servant, for (i=0;i_length;i++) { const CORBA_char *name = names->_buffer[i]; GNOME_Evolution_Mail_Property *prop = &props->_buffer[i]; - char *val = NULL; printf("getting property '%s'\n", name); if (!strcmp(name, "name")) { - if (p->account) - val = p->account->name; - else - /* FIXME: name & i18n */ - val = "Local"; - e_mail_property_set_string(prop, name, val); + e_mail_property_set_string(prop, name, evolution_mail_store_get_name(ems)); } else if (!strcmp(name, "uid")) { - if (p->account) - val = p->account->uid; - else - val = "local@local"; - e_mail_property_set_string(prop, name, val); + e_mail_property_set_string(prop, name, evolution_mail_store_get_uid(ems)); } else { e_mail_property_set_null(prop, name); ok = CORBA_FALSE; @@ -127,7 +147,141 @@ impl_getProperties(PortableServer_Servant _servant, return ok; } -static GNOME_Evolution_Mail_Folders * +static void +ems_add_folders(struct _EvolutionMailStorePrivate *p, CamelFolderInfo *fi) +{ + while (fi) { + if (g_hash_table_lookup(p->folders, fi->full_name) == NULL) { + + /* FIXME: store of folder??? */ + EvolutionMailFolder *emf = evolution_mail_folder_new(fi->name, fi->full_name); + + g_hash_table_insert(p->folders, emf->full_name, emf); + g_ptr_array_add(p->folders_array, emf); + } + + if (fi->child) + ems_add_folders(p, fi->child); + + fi = fi->next; + } +} + +static void +ems_remove_folders(struct _EvolutionMailStorePrivate *p, CamelFolderInfo *fi) +{ + EvolutionMailFolder *emf; + + while (fi) { + emf = g_hash_table_lookup(p->folders, fi->full_name); + if (emf) { + g_hash_table_remove(p->folders, fi->full_name); + g_ptr_array_remove(p->folders_array, emf); + /* FIXME: pass emf to the store changed folder removed code */ + } else { + g_warning("Folder removed I didn't know existed '%s'\n", fi->full_name); + } + + if (fi->child) + ems_remove_folders(p, fi->child); + + fi = fi->next; + } +} + +static int +ems_sort_folders_cmp(const void *ap, const void *bp) +{ + const EvolutionMailFolder *a = ((const EvolutionMailFolder **)ap)[0]; + const EvolutionMailFolder *b = ((const EvolutionMailFolder **)bp)[0]; + + return strcmp(a->full_name, b->full_name); +} + +static void +ems_sort_folders(struct _EvolutionMailStorePrivate *p) +{ + qsort(p->folders_array->pdata, p->folders_array->len, sizeof(p->folders_array->pdata[0]), ems_sort_folders_cmp); +} + +static void +ems_folder_opened(CamelObject *o, void *d, void *data) +{ + EvolutionMailStore *ems = data; + CamelFolder *folder = d; + + ems = ems; + folder = folder; + /* noop */ +} + +static void +ems_folder_subscribed(CamelObject *o, void *d, void *data) +{ + EvolutionMailStore *ems = data; + struct _EvolutionMailStorePrivate *p = _PRIVATE(ems); + CamelFolderInfo *fi = d; + + ems_add_folders(p, fi); + + /* FIXME: store folder added event */ +} + +static void +ems_folder_unsubscribed(CamelObject *o, void *d, void *data) +{ + EvolutionMailStore *ems = data; + struct _EvolutionMailStorePrivate *p = _PRIVATE(ems); + CamelFolderInfo *fi = d; + + ems_remove_folders(p, fi); + + /* FIXME: store folder deleted event */ +} + +static void +ems_folder_created(CamelObject *o, void *d, void *data) +{ + CamelStore *store = (CamelStore *)o; + + if (!camel_store_supports_subscriptions(store)) + ems_folder_subscribed(o, d, data); +} + +static void +ems_folder_deleted(CamelObject *o, void *d, void *data) +{ + CamelStore *store = (CamelStore *)o; + + if (!camel_store_supports_subscriptions(store)) + ems_folder_subscribed(o, d, data); +} + +static void +ems_folder_renamed(CamelObject *o, void *d, void *data) +{ + EvolutionMailStore *ems = data; + struct _EvolutionMailStorePrivate *p = _PRIVATE(ems); + CamelRenameInfo *reninfo = d; + int i, oldlen; + + oldlen = strlen(reninfo->old_base); + + for (i=0;ifolders_array->len;i++) { + EvolutionMailFolder *folder = p->folders_array->pdata[i]; + + if (!strcmp(folder->full_name, reninfo->old_base) + || (strlen(folder->full_name) > oldlen + && folder->full_name[oldlen] == '/' + && strncmp(folder->full_name, reninfo->old_base, oldlen))) { + /* renamed folder */ + } + } + + /* FIXME: store folder changed event? */ +} + +static GNOME_Evolution_Mail_FolderInfos * impl_getFolders(PortableServer_Servant _servant, const CORBA_char * pattern, CORBA_Environment * ev) @@ -136,32 +290,78 @@ impl_getFolders(PortableServer_Servant _servant, struct _EvolutionMailStorePrivate *p = _PRIVATE(ems); CamelFolderInfo *fi; CamelException ex = { 0 }; + GNOME_Evolution_Mail_FolderInfos *folders = NULL; + int i; if (p->store == NULL) { - if (p->account == NULL) { + if (ems->account == NULL) { p->store = mail_component_peek_local_store(NULL); camel_object_ref(p->store); } else { const char *uri; - uri = e_account_get_string(p->account, E_ACCOUNT_SOURCE_URL); + uri = e_account_get_string(ems->account, E_ACCOUNT_SOURCE_URL); if (uri && *uri) { p->store = camel_session_get_store(p->session->session, uri, &ex); if (camel_exception_is_set(&ex)) { + GNOME_Evolution_Mail_FAILED *x; + camel_exception_clear(&ex); - return NULL; + x = GNOME_Evolution_Mail_FAILED__alloc(); + x->why = CORBA_string_dup("Unable to get store"); + CORBA_exception_set(ev, CORBA_USER_EXCEPTION, ex_GNOME_Evolution_Mail_FAILED, x); + return CORBA_OBJECT_NIL; } } else { - return NULL; + CORBA_exception_set(ev, CORBA_USER_EXCEPTION, ex_GNOME_Evolution_Mail_FAILED, NULL); + return CORBA_OBJECT_NIL; } } + + p->folder_opened = camel_object_hook_event(p->store, "folder_opened", ems_folder_opened, ems); + p->folder_created = camel_object_hook_event(p->store, "folder_created", ems_folder_created, ems); + p->folder_deleted = camel_object_hook_event(p->store, "folder_deleted", ems_folder_deleted, ems); + p->folder_renamed = camel_object_hook_event(p->store, "folder_renamed", ems_folder_renamed, ems); + p->folder_subscribed = camel_object_hook_event(p->store, "folder_subscribed", ems_folder_subscribed, ems); + p->folder_unsubscribed = camel_object_hook_event(p->store, "folder_unsubscribed", ems_folder_unsubscribed, ems); } - fi = camel_store_get_folder_info(p->store, pattern, CAMEL_STORE_FOLDER_INFO_RECURSIVE|CAMEL_STORE_FOLDER_INFO_FAST, &ex); + if (p->folders == NULL) { + fi = camel_store_get_folder_info(p->store, "", CAMEL_STORE_FOLDER_INFO_RECURSIVE|CAMEL_STORE_FOLDER_INFO_FAST, &ex); - /* flatten folders ... */ + if (fi) { + p->folders = g_hash_table_new(g_str_hash, g_str_equal); + p->folders_array = g_ptr_array_new(); + ems_add_folders(p, fi); + camel_store_free_folder_info(p->store, fi); + ems_sort_folders(p); + } else { + GNOME_Evolution_Mail_FAILED *x; - return NULL; + x = GNOME_Evolution_Mail_FAILED__alloc(); + x->why = CORBA_string_dup("Unable to list folders"); + CORBA_exception_set(ev, CORBA_USER_EXCEPTION, ex_GNOME_Evolution_Mail_FAILED, x); + + return CORBA_OBJECT_NIL; + } + } + + folders = GNOME_Evolution_Mail_FolderInfos__alloc(); + folders->_length = p->folders_array->len; + folders->_maximum = folders->_length; + folders->_buffer = GNOME_Evolution_Mail_FolderInfos_allocbuf(folders->_maximum); + CORBA_sequence_set_release(folders, CORBA_TRUE); + + for (i=0;ifolders_array->len;i++) { + EvolutionMailFolder *emf = p->folders_array->pdata[i]; + + folders->_buffer[i].name = CORBA_string_dup(emf->name); + folders->_buffer[i].full_name = CORBA_string_dup(emf->full_name); + folders->_buffer[i].folder = CORBA_Object_duplicate(bonobo_object_corba_objref((BonoboObject *)emf), NULL); + /* object ref?? */ + } + + return folders; } static void @@ -173,13 +373,15 @@ impl_sendMessage(PortableServer_Servant _servant, EvolutionMailStore *ems = (EvolutionMailStore *)bonobo_object_from_servant(_servant); struct _EvolutionMailStorePrivate *p = _PRIVATE(ems); + p = p; + printf("Sending message from '%s' to '%s'\n", from, recipients); - if (p->account == NULL) { + if (ems->account == NULL) { printf("Local mail can only store ...\n"); - } else if (p->account->transport && p->account->transport->url) { - printf("via '%s'\n", p->account->transport->url); + } else if (ems->account->transport && ems->account->transport->url) { + printf("via '%s'\n", ems->account->transport->url); } else { - printf("Account not setup for sending '%s'\n", p->account->name); + printf("Account not setup for sending '%s'\n", ems->account->name); } } @@ -213,11 +415,18 @@ BONOBO_TYPE_FUNC_FULL (EvolutionMailStore, GNOME_Evolution_Mail_Store, PARENT_TY EvolutionMailStore * evolution_mail_store_new(struct _EvolutionMailSession *s, struct _EAccount *ea) { - EvolutionMailStore *ems = g_object_new (EVOLUTION_MAIL_TYPE_STORE, NULL); - struct _EvolutionMailStorePrivate *p = _PRIVATE(ems); + EvolutionMailStore *ems; + struct _EvolutionMailStorePrivate *p; + static PortableServer_POA poa = NULL; + + if (poa == NULL) + poa = bonobo_poa_get_threaded (ORBIT_THREAD_HINT_PER_REQUEST, NULL); + + ems = g_object_new (EVOLUTION_MAIL_TYPE_STORE, "poa", poa, NULL); + p = _PRIVATE(ems); if (ea) { - p->account = ea; + ems->account = ea; g_object_ref(ea); } @@ -226,6 +435,22 @@ evolution_mail_store_new(struct _EvolutionMailSession *s, struct _EAccount *ea) return ems; } +const char *evolution_mail_store_get_name(EvolutionMailStore *ems) +{ + if (ems->account) + return ems->account->name; + else + return ("On This Computer"); +} + +const char *evolution_mail_store_get_uid(EvolutionMailStore *ems) +{ + if (ems->account) + return ems->account->uid; + else + return "local@local"; +} + #if 0 static BonoboObject * factory (BonoboGenericFactory *factory, diff --git a/plugins/mail-remote/evolution-mail-store.h b/plugins/mail-remote/evolution-mail-store.h index fef596e4f7..db42bf407f 100644 --- a/plugins/mail-remote/evolution-mail-store.h +++ b/plugins/mail-remote/evolution-mail-store.h @@ -39,6 +39,8 @@ typedef struct _EvolutionMailStoreClass EvolutionMailStoreClass; struct _EvolutionMailStore { BonoboObject parent; + + struct _EAccount *account; }; struct _EvolutionMailStoreClass { @@ -51,4 +53,7 @@ GType evolution_mail_store_get_type(void); EvolutionMailStore *evolution_mail_store_new(struct _EvolutionMailSession *s, struct _EAccount *ea); +const char *evolution_mail_store_get_name(EvolutionMailStore *); +const char *evolution_mail_store_get_uid(EvolutionMailStore *); + #endif /* _EVOLUTION_MAIL_STORE_H_ */ diff --git a/plugins/mail-remote/mail-remote.c b/plugins/mail-remote/mail-remote.c index 6ee41f6c9d..dedbb03596 100644 --- a/plugins/mail-remote/mail-remote.c +++ b/plugins/mail-remote/mail-remote.c @@ -5,10 +5,16 @@ #include "evolution-mail-session.h" #include -#define MAIL_SESSION_ID "OAFIID:GNOME_Evolution_Mail_Session:" BASE_VERSION +struct _EPlugin; +struct _ESEventTargetUpgrade; +void org_gnome_evolution_mail_remote_startup(struct _EPlugin *ep, struct _ESEventTargetUpgrade *target); int e_plugin_lib_enable(int enable); +void org_gnome_evolution_mail_remote_startup(struct _EPlugin *ep, struct _ESEventTargetUpgrade *target) { + /* noop */ ; +} + int e_plugin_lib_enable(int enable) { static EvolutionMailSession *sess; -- cgit v1.2.3