diff options
Diffstat (limited to 'calendar/gui')
-rw-r--r-- | calendar/gui/GNOME_Evolution_Calendar.oaf.in | 16 | ||||
-rw-r--r-- | calendar/gui/Makefile.am | 2 | ||||
-rw-r--r-- | calendar/gui/alarm-notify/alarm-queue.c | 52 | ||||
-rw-r--r-- | calendar/gui/calendar-component.c | 116 | ||||
-rw-r--r-- | calendar/gui/comp-editor-factory.c | 474 | ||||
-rw-r--r-- | calendar/gui/component-factory.c | 116 | ||||
-rw-r--r-- | calendar/gui/main.c | 35 |
7 files changed, 765 insertions, 46 deletions
diff --git a/calendar/gui/GNOME_Evolution_Calendar.oaf.in b/calendar/gui/GNOME_Evolution_Calendar.oaf.in index 0e07c3bfa2..4d80cfa0de 100644 --- a/calendar/gui/GNOME_Evolution_Calendar.oaf.in +++ b/calendar/gui/GNOME_Evolution_Calendar.oaf.in @@ -67,7 +67,7 @@ location="evolution-calendar"> <oaf_attribute name="repo_ids" type="stringv"> - <item value="IDL:GNOME:GenericFactory:1.0"/> + <item value="IDL:GNOME:ObjectFactory:1.0"/> </oaf_attribute> <oaf_attribute name="description" type="string" @@ -117,11 +117,23 @@ _value="A sample Bonobo control which displays an calendar."/> </oaf_server> -<oaf_server iid="OAFIID:GNOME_Evolution_Calendar_CompEditorFactory" +<oaf_server iid="OAFIID:GNOME_Evolution_Calendar_CompEditorFactory_Factory" type="exe" location="evolution-calendar"> <oaf_attribute name="repo_ids" type="stringv"> + <item value="IDL:GNOME/ObjectFactory:1.0"/> + </oaf_attribute> + + <oaf_attribute name="description" type="string" + _value="Factory to create a component editor factory"/> +</oaf_server> + +<oaf_server iid="OAFIID:GNOME_Evolution_Calendar_CompEditorFactory" + type="factory" + location="OAFIID:GNOME_Evolution_Calendar_CompEditorFactory_Factory"> + + <oaf_attribute name="repo_ids" type="stringv"> <item value="IDL:GNOME/Evolution/Calendar/CompEditorFactory:1.0"/> <item value="IDL:Bonobo/Unknown:1.0"/> </oaf_attribute> diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am index 133e39f1ce..2db2c26ced 100644 --- a/calendar/gui/Makefile.am +++ b/calendar/gui/Makefile.am @@ -74,6 +74,8 @@ evolution_calendar_SOURCES = \ calendar-view.h \ calendar-view-factory.c \ calendar-view-factory.h \ + comp-editor-factory.c \ + comp-editor-factory.h \ comp-util.c \ comp-util.h \ control-factory.c \ diff --git a/calendar/gui/alarm-notify/alarm-queue.c b/calendar/gui/alarm-notify/alarm-queue.c index b12eca317d..a2035c8b61 100644 --- a/calendar/gui/alarm-notify/alarm-queue.c +++ b/calendar/gui/alarm-notify/alarm-queue.c @@ -28,6 +28,8 @@ #include <libgnome/gnome-defs.h> #include <libgnome/gnome-i18n.h> #include <gtk/gtksignal.h> +#include <liboaf/liboaf.h> +#include <bonobo/bonobo-object.h> #include <cal-util/timeutil.h> #include "alarm.h" #include "alarm-notify-dialog.h" @@ -491,6 +493,54 @@ create_snooze (CompQueuedAlarms *cqa, gpointer alarm_id, int snooze_mins) cqa->queued_alarms = g_slist_prepend (cqa->queued_alarms, qa); } +/* Launches a component editor for a component */ +static void +edit_component (CompQueuedAlarms *cqa) +{ + CalComponent *comp; + const char *uid; + const char *uri; + CORBA_Environment ev; + GNOME_Evolution_Calendar_CompEditorFactory factory; + + comp = cqa->alarms->comp; + cal_component_get_uid (comp, &uid); + + uri = cal_client_get_uri (cqa->parent_client->client); + + /* Get the factory */ + + CORBA_exception_init (&ev); + factory = oaf_activate_from_id ("OAFIID:GNOME_Evolution_Calendar_CompEditorFactory", + 0, NULL, &ev); + + if (ev._major != CORBA_NO_EXCEPTION) { + g_message ("edit_component(): Could not activate the component editor factory"); + CORBA_exception_free (&ev); + return; + } + CORBA_exception_free (&ev); + + /* Edit the component */ + + CORBA_exception_init (&ev); + GNOME_Evolution_Calendar_CompEditorFactory_editExisting (factory, uri, (char *) uid, &ev); + + if (ev._major != CORBA_NO_EXCEPTION) + g_message ("edit_component(): Exception while editing the component"); + + CORBA_exception_free (&ev); + + /* Get rid of the factory */ + + CORBA_exception_init (&ev); + bonobo_object_release_unref (factory, &ev); + if (ev._major != CORBA_NO_EXCEPTION) + g_message ("edit_component(): Could not unref the calendar component factory"); + + CORBA_exception_free (&ev); +} + struct notify_dialog_closure { CompQueuedAlarms *cqa; gpointer alarm_id; @@ -510,7 +560,7 @@ notify_dialog_cb (AlarmNotifyResult result, int snooze_mins, gpointer data) break; case ALARM_NOTIFY_EDIT: - /* FIXME */ + edit_component (c->cqa); break; case ALARM_NOTIFY_CLOSE: diff --git a/calendar/gui/calendar-component.c b/calendar/gui/calendar-component.c index 32517d18bd..10d53a54ea 100644 --- a/calendar/gui/calendar-component.c +++ b/calendar/gui/calendar-component.c @@ -44,6 +44,10 @@ /* OAFIID for the component factory */ #define COMPONENT_FACTORY_ID "OAFIID:GNOME_Evolution_Calendar_ShellComponentFactory" +/* Folder type IDs */ +#define FOLDER_CALENDAR "calendar" +#define FOLDER_TASKS "tasks" + /* IDs for user creatable items */ #define CREATE_EVENT_ID "event" #define CREATE_TASK_ID "task" @@ -52,8 +56,16 @@ static BonoboGenericFactory *factory = NULL; char *evolution_dir; static const EvolutionShellComponentFolderType folder_types[] = { - { "calendar", "evolution-calendar.png", N_("Calendar"), N_("Folder containing appointments and events"), TRUE, NULL, NULL }, - { "tasks", "evolution-tasks.png", N_("Tasks"), N_("Folder containing to-do items"), TRUE, NULL, NULL }, + { FOLDER_CALENDAR, + "evolution-calendar.png", + N_("Calendar"), + N_("Folder containing appointments and events"), + TRUE, NULL, NULL }, + { FOLDER_TASKS, + "evolution-tasks.png", + N_("Tasks"), + N_("Folder containing to-do items"), + TRUE, NULL, NULL }, { NULL, NULL } }; @@ -343,6 +355,93 @@ owner_unset_cb (EvolutionShellComponent *shell_component, gtk_main_quit (); } +/* Computes the final URI for a calendar component */ +static char * +get_data_uri (const char *uri, CalComponentVType vtype) +{ + if (uri) { + if (vtype == CAL_COMPONENT_EVENT) + return g_concat_dir_and_file (uri, "calendar.ics"); + else if (vtype == CAL_COMPONENT_TODO) + return g_concat_dir_and_file (uri, "tasks.ics"); + else + g_assert_not_reached (); + } else { + if (vtype == CAL_COMPONENT_EVENT) + return g_concat_dir_and_file (g_get_home_dir (), + "evolution/local/Calendar/calendar.ics"); + else if (vtype == CAL_COMPONENT_TODO) + return g_concat_dir_and_file (g_get_home_dir (), + "evolution/local/Tasks/tasks.ics"); + else + g_assert_not_reached (); + } + + return NULL; +} + +/* Creates a calendar component at a specified URI. If the URI is NULL then it + * uses the default folder for that type of component. + */ +static void +create_component (const char *uri, CalComponentVType vtype) +{ + char *real_uri; + CORBA_Environment ev; + GNOME_Evolution_Calendar_CalObjType corba_type; + GNOME_Evolution_Calendar_CompEditorFactory factory; + + real_uri = get_data_uri (uri, vtype); + + switch (vtype) { + case CAL_COMPONENT_EVENT: + corba_type = GNOME_Evolution_Calendar_TYPE_EVENT; + break; + + case CAL_COMPONENT_TODO: + corba_type = GNOME_Evolution_Calendar_TYPE_TODO; + break; + + default: + g_assert_not_reached (); + return; + } + + /* Get the factory */ + + CORBA_exception_init (&ev); + factory = oaf_activate_from_id ("OAFIID:GNOME_Evolution_Calendar_CompEditorFactory", + 0, NULL, &ev); + + if (ev._major != CORBA_NO_EXCEPTION) { + g_message ("create_component(): Could not activate the component editor factory"); + CORBA_exception_free (&ev); + g_free (real_uri); + return; + } + CORBA_exception_free (&ev); + + /* Create the item */ + + CORBA_exception_init (&ev); + GNOME_Evolution_Calendar_CompEditorFactory_editNew (factory, real_uri, corba_type, &ev); + + if (ev._major != CORBA_NO_EXCEPTION) + g_message ("create_component(): Exception while creating the component"); + + CORBA_exception_free (&ev); + g_free (real_uri); + + /* Get rid of the factory */ + + CORBA_exception_init (&ev); + bonobo_object_release_unref (factory, &ev); + if (ev._major != CORBA_NO_EXCEPTION) + g_message ("create_component(): Could not unref the calendar component factory"); + + CORBA_exception_free (&ev); +} + /* Callback used when we must create a user-creatable item */ static void sc_user_create_new_item_cb (EvolutionShellComponent *shell_component, @@ -350,7 +449,18 @@ sc_user_create_new_item_cb (EvolutionShellComponent *shell_component, const char *parent_folder_physical_uri, const char *parent_folder_type) { - /* FIXME */ + if (strcmp (id, CREATE_EVENT_ID) == 0) { + if (strcmp (parent_folder_type, FOLDER_CALENDAR) == 0) + create_component (parent_folder_physical_uri, CAL_COMPONENT_EVENT); + else + create_component (NULL, CAL_COMPONENT_EVENT); + } else if (strcmp (id, CREATE_TASK_ID) == 0) { + if (strcmp (parent_folder_type, FOLDER_TASKS) == 0) + create_component (parent_folder_physical_uri, CAL_COMPONENT_TODO); + else + create_component (NULL, CAL_COMPONENT_TODO); + } else + g_assert_not_reached (); } #if 0 diff --git a/calendar/gui/comp-editor-factory.c b/calendar/gui/comp-editor-factory.c index b235fcbdd0..7d1bfaff2d 100644 --- a/calendar/gui/comp-editor-factory.c +++ b/calendar/gui/comp-editor-factory.c @@ -23,8 +23,12 @@ #include <config.h> #endif +#include <libgnomevfs/gnome-vfs.h> #include <cal-client/cal-client.h> +#include "calendar-config.h" #include "comp-editor-factory.h" +#include "dialogs/event-editor.h" +#include "dialogs/task-editor.h" @@ -44,24 +48,30 @@ typedef struct { } existing; struct { - CalObjType type; + CalComponentVType vtype; } new; } u; } Request; /* A client we have open */ typedef struct { + /* Our parent CompEditorFactory */ + CompEditorFactory *factory; + /* Uri of the calendar, used as key in the clients hash table */ GnomeVFSURI *uri; /* Client of the calendar */ CalClient *client; - /* Hash table of components that belong to this client */ + /* Hash table of Component structures that belong to this client */ GHashTable *uid_comp_hash; /* Pending requests; they are pending if the client is still being opened */ GSList *pending; + + /* Whether this is open or still waiting */ + guint open : 1; } OpenClient; /* A component that is being edited */ @@ -74,6 +84,9 @@ typedef struct { /* Component we are editing */ CalComponent *comp; + + /* Component editor that is open */ + CompEditor *editor; } Component; /* Private part of the CompEditorFactory structure */ @@ -89,7 +102,7 @@ static void comp_editor_factory_init (CompEditorFactory *factory); static void comp_editor_factory_destroy (GtkObject *object); static void impl_editExisting (PortableServer_Servant servant, - const CORBA_char *uri, + const CORBA_char *str_uri, const GNOME_Evolution_Calendar_CalObjUID uid, CORBA_Environment *ev); static void impl_editNew (PortableServer_Servant servant, @@ -129,6 +142,7 @@ comp_editor_factory_init (CompEditorFactory *factory) CompEditorFactoryPrivate *priv; priv = g_new (CompEditorFactoryPrivate, 1); + factory->priv = priv; priv->uri_client_hash = g_hash_table_new (gnome_vfs_uri_hash, gnome_vfs_uri_hequal); } @@ -144,25 +158,34 @@ free_component_cb (gpointer key, gpointer value, gpointer data) c->parent = NULL; c->uid = NULL; - cal_component_unref (c->comp); + gtk_object_unref (GTK_OBJECT (c->comp)); c->comp = NULL; g_free (c); } -/* Used from g_hash_table_foreach(); frees a client structure */ +/* Frees a Request structure */ static void -free_client_cb (gpointer key, gpointer value, gpointer data) +free_request (Request *r) { - OpenClient *oc; - GSList *l; + if (r->type == REQUEST_EXISTING) { + g_assert (r->u.existing.uid != NULL); + g_free (r->u.existing.uid); + } - oc = value; + g_free (r); +} + +/* Frees an OpenClient structure */ +static void +free_client (OpenClient *oc) +{ + GSList *l; gnome_vfs_uri_unref (oc->uri); oc->uri = NULL; - cal_client_unref (oc->client); + gtk_object_unref (GTK_OBJECT (oc->client)); oc->client = NULL; g_hash_table_foreach (oc->uid_comp_hash, free_component_cb, NULL); @@ -173,13 +196,7 @@ free_client_cb (gpointer key, gpointer value, gpointer data) Request *r; r = l->data; - - if (r->type == REQUEST_EXISTING) { - g_assert (r->u.existing.uid != NULL); - g_free (r->u.existing.uid); - } - - g_free (r); + free_request (r); } g_slist_free (oc->pending); oc->pending = NULL; @@ -187,6 +204,16 @@ free_client_cb (gpointer key, gpointer value, gpointer data) g_free (oc); } +/* Used from g_hash_table_foreach(); frees a client structure */ +static void +free_client_cb (gpointer key, gpointer value, gpointer data) +{ + OpenClient *oc; + + oc = value; + free_client (oc); +} + /* Destroy handler for the component editor factory */ static void comp_editor_factory_destroy (GtkObject *object) @@ -213,20 +240,275 @@ comp_editor_factory_destroy (GtkObject *object) +/* Callback used when a component editor gets destroyed */ +static void +editor_destroy_cb (GtkObject *object, gpointer data) +{ + Component *c; + OpenClient *oc; + CompEditorFactory *factory; + CompEditorFactoryPrivate *priv; + + c = data; + oc = c->parent; + factory = oc->factory; + priv = factory->priv; + + /* Free the Component */ + + g_hash_table_remove (oc->uid_comp_hash, c->uid); + gtk_object_unref (GTK_OBJECT (c->comp)); + g_free (c); + + /* See if we need to free the client */ + + g_assert (oc->pending == NULL); + + if (g_hash_table_size (oc->uid_comp_hash) != 0) + return; + + g_hash_table_remove (priv->uri_client_hash, oc->uri); + free_client (oc); +} + +/* Starts editing an existing component on a client that is already open */ +static void +edit_existing (OpenClient *oc, const char *uid) +{ + CalComponent *comp; + CalClientGetStatus status; + CompEditor *editor; + Component *c; + CalComponentVType vtype; + + g_assert (oc->open); + + /* Get the object */ + + status = cal_client_get_object (oc->client, uid, &comp); + + switch (status) { + case CAL_CLIENT_GET_SUCCESS: + /* see below */ + break; + + case CAL_CLIENT_GET_NOT_FOUND: + /* The object disappeared from the server */ + return; + + case CAL_CLIENT_GET_SYNTAX_ERROR: + g_message ("edit_exiting(): Syntax error while getting component `%s'", uid); + return; + + default: + g_assert_not_reached (); + return; + } + + /* Create the appropriate type of editor */ + + vtype = cal_component_get_vtype (comp); + + switch (vtype) { + case CAL_COMPONENT_EVENT: + editor = COMP_EDITOR (event_editor_new ()); + break; + + case CAL_COMPONENT_TODO: + editor = COMP_EDITOR (task_editor_new ()); + break; + + default: + g_message ("edit_exiting(): Unsupported object type %d", (int) vtype); + gtk_object_unref (GTK_OBJECT (comp)); + return; + } + + /* Set the client/object on the editor */ + + c = g_new (Component, 1); + c->parent = oc; + cal_component_get_uid (comp, &c->uid); + c->comp = comp; + c->editor = editor; + + g_hash_table_insert (oc->uid_comp_hash, (char *) c->uid, c); + + gtk_signal_connect (GTK_OBJECT (editor), "destroy", + GTK_SIGNAL_FUNC (editor_destroy_cb), c); + + comp_editor_set_cal_client (editor, oc->client); + comp_editor_edit_comp (editor, comp); + comp_editor_focus (editor); +} + +/* Creates a component with the appropriate defaults for the specified component + * type. + */ +static CalComponent * +get_default_component (CalComponentVType vtype) +{ + CalComponent *comp; + + comp = cal_component_new (); + cal_component_set_new_vtype (comp, vtype); + + if (vtype == CAL_COMPONENT_EVENT) { + struct icaltimetype itt; + CalComponentDateTime dt; + + itt = icaltime_today (); + + dt.value = &itt; + dt.tzid = calendar_config_get_timezone (); + + cal_component_set_dtstart (comp, &dt); + cal_component_set_dtend (comp, &dt); + + cal_component_commit_sequence (comp); + } + + return comp; +} + +/* Edits a new object in the context of a client */ +static void +edit_new (OpenClient *oc, CalComponentVType vtype) +{ + CalComponent *comp; + Component *c; + CompEditor *editor; + + switch (vtype) { + case CAL_COMPONENT_EVENT: + editor = COMP_EDITOR (event_editor_new ()); + break; + + case CAL_COMPONENT_TODO: + editor = COMP_EDITOR (task_editor_new ()); + break; + + default: + g_assert_not_reached (); + return; + } + + comp = get_default_component (vtype); + + c = g_new (Component, 1); + c->parent = oc; + cal_component_get_uid (comp, &c->uid); + c->comp = comp; + + c->editor = editor; + + g_hash_table_insert (oc->uid_comp_hash, (char *) c->uid, c); + + gtk_signal_connect (GTK_OBJECT (editor), "destroy", + GTK_SIGNAL_FUNC (editor_destroy_cb), c); + + comp_editor_set_cal_client (editor, oc->client); + comp_editor_edit_comp (editor, comp); + comp_editor_focus (editor); +} + +/* Resolves all the pending requests for a client */ +static void +resolve_pending_requests (OpenClient *oc) +{ + CompEditorFactory *factory; + CompEditorFactoryPrivate *priv; + GSList *l; + + factory = oc->factory; + priv = factory->priv; + + g_assert (oc->pending != NULL); + + for (l = oc->pending; l; l = l->next) { + Request *request; + + request = l->data; + + switch (request->type) { + case REQUEST_EXISTING: + edit_existing (oc, request->u.existing.uid); + break; + + case REQUEST_NEW: + edit_new (oc, request->u.new.vtype); + break; + } + + free_request (request); + } + + g_slist_free (oc->pending); + oc->pending = NULL; +} + +/* Callback used when a client is finished opening. We resolve all the pending + * requests. + */ +static void +cal_opened_cb (CalClient *client, CalClientOpenStatus status, gpointer data) +{ + OpenClient *oc; + CompEditorFactory *factory; + CompEditorFactoryPrivate *priv; + + oc = data; + factory = oc->factory; + priv = factory->priv; + + switch (status) { + case CAL_CLIENT_OPEN_SUCCESS: + oc->open = TRUE; + resolve_pending_requests (oc); + return; + + case CAL_CLIENT_OPEN_ERROR: + g_message ("cal_opened_cb(): Error while opening the calendar"); + break; + + case CAL_CLIENT_OPEN_NOT_FOUND: + /* bullshit; we specified only_if_exists = FALSE */ + g_assert_not_reached (); + return; + + case CAL_CLIENT_OPEN_METHOD_NOT_SUPPORTED: + g_message ("cal_opened_cb(): Method not supported when opening the calendar"); + break; + + default: + g_assert_not_reached (); + return; + } + + g_hash_table_remove (priv->uri_client_hash, oc->uri); + free_client (oc); +} + /* Creates a new OpenClient structure and queues the component editing/creation * process until the client is open. Returns NULL if it could not issue the * open request. */ static OpenClient * -open_client (GnomeVFSURI *uri, gboolean only_if_exists) +open_client (CompEditorFactory *factory, GnomeVFSURI *uri) { + CompEditorFactoryPrivate *priv; CalClient *client; + OpenClient *oc; + char *str_uri; + + priv = factory->priv; client = cal_client_new (); if (!client) return NULL; oc = g_new (OpenClient, 1); + oc->factory = factory; gnome_vfs_uri_ref (uri); oc->uri = uri; @@ -234,11 +516,15 @@ open_client (GnomeVFSURI *uri, gboolean only_if_exists) oc->client = client; oc->uid_comp_hash = g_hash_table_new (g_str_hash, g_str_equal); oc->pending = NULL; + oc->open = FALSE; gtk_signal_connect (GTK_OBJECT (oc->client), "cal_opened", GTK_SIGNAL_FUNC (cal_opened_cb), oc); - if (!cal_client_open_calendar (oc->client, uri, only_if_exists)) { + str_uri = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE); + + if (!cal_client_open_calendar (oc->client, str_uri, FALSE)) { + g_free (str_uri); gnome_vfs_uri_unref (oc->uri); gtk_object_unref (GTK_OBJECT (oc->client)); g_hash_table_destroy (oc->uid_comp_hash); @@ -246,24 +532,23 @@ open_client (GnomeVFSURI *uri, gboolean only_if_exists) return NULL; } + g_free (str_uri); + + g_hash_table_insert (priv->uri_client_hash, oc->uri, oc); return oc; } -static void -impl_editExisting (PortableServer_Servant servant, - const CORBA_char *str_uri, - const GNOME_Evolution_Calendar_CalObjUID uid, - CORBA_Environment *ev) +/* Looks up an open client or queues it for being opened. Returns the client or + * NULL on failure; in the latter case it sets the ev exception. + */ +static OpenClient * +lookup_open_client (CompEditorFactory *factory, const char *str_uri, CORBA_Environment *ev) { - CompEditorFactory *factory; CompEditorFactoryPrivate *priv; GnomeVFSURI *uri; OpenClient *oc; - CalClient *client; - Component *c; - factory = COMP_EDITOR_FACTORY (bonobo_object_from_servant (servant)); priv = factory->priv; /* Look up the client */ @@ -273,14 +558,12 @@ impl_editExisting (PortableServer_Servant servant, CORBA_exception_set (ev, CORBA_USER_EXCEPTION, ex_GNOME_Evolution_Calendar_CompEditorFactory_InvalidURI, NULL); - return; + return NULL; } oc = g_hash_table_lookup (priv->uri_client_hash, uri); - if (oc) - client = oc->client; - else { - oc = open_client (uri); + if (!oc) { + oc = open_client (factory, uri); if (!oc) { gnome_vfs_uri_unref (uri); @@ -288,15 +571,132 @@ impl_editExisting (PortableServer_Servant servant, ev, CORBA_USER_EXCEPTION, ex_GNOME_Evolution_Calendar_CompEditorFactory_BackendContactError, NULL); - return; + return NULL; } - - client = oc->client; } gnome_vfs_uri_unref (uri); + return oc; +} + +/* Queues a request for editing an existing object */ +static void +queue_edit_existing (OpenClient *oc, const char *uid) +{ + Request *request; + + g_assert (!oc->open); + + request = g_new (Request, 1); + request->type = REQUEST_EXISTING; + request->u.existing.uid = g_strdup (uid); + + oc->pending = g_slist_append (oc->pending, request); +} + +/* ::editExisting() method implementation */ +static void +impl_editExisting (PortableServer_Servant servant, + const CORBA_char *str_uri, + const GNOME_Evolution_Calendar_CalObjUID uid, + CORBA_Environment *ev) +{ + CompEditorFactory *factory; + CompEditorFactoryPrivate *priv; + OpenClient *oc; + Component *c; + + factory = COMP_EDITOR_FACTORY (bonobo_object_from_servant (servant)); + priv = factory->priv; + + oc = lookup_open_client (factory, str_uri, ev); + if (!oc) + return; + + if (!oc->open) { + queue_edit_existing (oc, uid); + return; + } + /* Look up the component */ - c = g_hash_table_lookup (oc->uid_comp_hash, + c = g_hash_table_lookup (oc->uid_comp_hash, uid); + if (!c) + edit_existing (oc, uid); + else { + g_assert (c->editor != NULL); + comp_editor_focus (c->editor); + } +} + +/* Queues a request for creating a new object */ +static void +queue_edit_new (OpenClient *oc, CalComponentVType vtype) +{ + Request *request; + + g_assert (!oc->open); + + request = g_new (Request, 1); + request->type = REQUEST_NEW; + request->u.new.vtype = vtype; + + oc->pending = g_slist_append (oc->pending, request); +} + +/* ::editNew() method implementation */ +static void +impl_editNew (PortableServer_Servant servant, + const CORBA_char *str_uri, + const GNOME_Evolution_Calendar_CalObjType corba_type, + CORBA_Environment *ev) +{ + CompEditorFactory *factory; + CompEditorFactoryPrivate *priv; + OpenClient *oc; + CalComponentVType vtype; + + factory = COMP_EDITOR_FACTORY (bonobo_object_from_servant (servant)); + priv = factory->priv; + + oc = lookup_open_client (factory, str_uri, ev); + if (!oc) + return; + + switch (corba_type) { + case GNOME_Evolution_Calendar_TYPE_EVENT: + vtype = CAL_COMPONENT_EVENT; + break; + + case GNOME_Evolution_Calendar_TYPE_TODO: + vtype = CAL_COMPONENT_TODO; + break; + + default: + CORBA_exception_set (ev, CORBA_USER_EXCEPTION, + ex_GNOME_Evolution_Calendar_CompEditorFactory_UnsupportedType, + NULL); + return; + } + + if (!oc->open) + queue_edit_new (oc, vtype); + else + edit_new (oc, vtype); +} + + + +/** + * comp_editor_factory_new: + * + * Creates a new calendar component editor factory. + * + * Return value: A newly-created component editor factory. + **/ +CompEditorFactory * +comp_editor_factory_new (void) +{ + return gtk_type_new (TYPE_COMP_EDITOR_FACTORY); } diff --git a/calendar/gui/component-factory.c b/calendar/gui/component-factory.c index 32517d18bd..10d53a54ea 100644 --- a/calendar/gui/component-factory.c +++ b/calendar/gui/component-factory.c @@ -44,6 +44,10 @@ /* OAFIID for the component factory */ #define COMPONENT_FACTORY_ID "OAFIID:GNOME_Evolution_Calendar_ShellComponentFactory" +/* Folder type IDs */ +#define FOLDER_CALENDAR "calendar" +#define FOLDER_TASKS "tasks" + /* IDs for user creatable items */ #define CREATE_EVENT_ID "event" #define CREATE_TASK_ID "task" @@ -52,8 +56,16 @@ static BonoboGenericFactory *factory = NULL; char *evolution_dir; static const EvolutionShellComponentFolderType folder_types[] = { - { "calendar", "evolution-calendar.png", N_("Calendar"), N_("Folder containing appointments and events"), TRUE, NULL, NULL }, - { "tasks", "evolution-tasks.png", N_("Tasks"), N_("Folder containing to-do items"), TRUE, NULL, NULL }, + { FOLDER_CALENDAR, + "evolution-calendar.png", + N_("Calendar"), + N_("Folder containing appointments and events"), + TRUE, NULL, NULL }, + { FOLDER_TASKS, + "evolution-tasks.png", + N_("Tasks"), + N_("Folder containing to-do items"), + TRUE, NULL, NULL }, { NULL, NULL } }; @@ -343,6 +355,93 @@ owner_unset_cb (EvolutionShellComponent *shell_component, gtk_main_quit (); } +/* Computes the final URI for a calendar component */ +static char * +get_data_uri (const char *uri, CalComponentVType vtype) +{ + if (uri) { + if (vtype == CAL_COMPONENT_EVENT) + return g_concat_dir_and_file (uri, "calendar.ics"); + else if (vtype == CAL_COMPONENT_TODO) + return g_concat_dir_and_file (uri, "tasks.ics"); + else + g_assert_not_reached (); + } else { + if (vtype == CAL_COMPONENT_EVENT) + return g_concat_dir_and_file (g_get_home_dir (), + "evolution/local/Calendar/calendar.ics"); + else if (vtype == CAL_COMPONENT_TODO) + return g_concat_dir_and_file (g_get_home_dir (), + "evolution/local/Tasks/tasks.ics"); + else + g_assert_not_reached (); + } + + return NULL; +} + +/* Creates a calendar component at a specified URI. If the URI is NULL then it + * uses the default folder for that type of component. + */ +static void +create_component (const char *uri, CalComponentVType vtype) +{ + char *real_uri; + CORBA_Environment ev; + GNOME_Evolution_Calendar_CalObjType corba_type; + GNOME_Evolution_Calendar_CompEditorFactory factory; + + real_uri = get_data_uri (uri, vtype); + + switch (vtype) { + case CAL_COMPONENT_EVENT: + corba_type = GNOME_Evolution_Calendar_TYPE_EVENT; + break; + + case CAL_COMPONENT_TODO: + corba_type = GNOME_Evolution_Calendar_TYPE_TODO; + break; + + default: + g_assert_not_reached (); + return; + } + + /* Get the factory */ + + CORBA_exception_init (&ev); + factory = oaf_activate_from_id ("OAFIID:GNOME_Evolution_Calendar_CompEditorFactory", + 0, NULL, &ev); + + if (ev._major != CORBA_NO_EXCEPTION) { + g_message ("create_component(): Could not activate the component editor factory"); + CORBA_exception_free (&ev); + g_free (real_uri); + return; + } + CORBA_exception_free (&ev); + + /* Create the item */ + + CORBA_exception_init (&ev); + GNOME_Evolution_Calendar_CompEditorFactory_editNew (factory, real_uri, corba_type, &ev); + + if (ev._major != CORBA_NO_EXCEPTION) + g_message ("create_component(): Exception while creating the component"); + + CORBA_exception_free (&ev); + g_free (real_uri); + + /* Get rid of the factory */ + + CORBA_exception_init (&ev); + bonobo_object_release_unref (factory, &ev); + if (ev._major != CORBA_NO_EXCEPTION) + g_message ("create_component(): Could not unref the calendar component factory"); + + CORBA_exception_free (&ev); +} + /* Callback used when we must create a user-creatable item */ static void sc_user_create_new_item_cb (EvolutionShellComponent *shell_component, @@ -350,7 +449,18 @@ sc_user_create_new_item_cb (EvolutionShellComponent *shell_component, const char *parent_folder_physical_uri, const char *parent_folder_type) { - /* FIXME */ + if (strcmp (id, CREATE_EVENT_ID) == 0) { + if (strcmp (parent_folder_type, FOLDER_CALENDAR) == 0) + create_component (parent_folder_physical_uri, CAL_COMPONENT_EVENT); + else + create_component (NULL, CAL_COMPONENT_EVENT); + } else if (strcmp (id, CREATE_TASK_ID) == 0) { + if (strcmp (parent_folder_type, FOLDER_TASKS) == 0) + create_component (parent_folder_physical_uri, CAL_COMPONENT_TODO); + else + create_component (NULL, CAL_COMPONENT_TODO); + } else + g_assert_not_reached (); } #if 0 diff --git a/calendar/gui/main.c b/calendar/gui/main.c index 318fbfbfa3..e3f16afb4c 100644 --- a/calendar/gui/main.c +++ b/calendar/gui/main.c @@ -34,6 +34,7 @@ #include <liboaf/liboaf.h> #include <bonobo/bonobo-main.h> +#include <bonobo/bonobo-generic-factory.h> #include <gal/widgets/e-cursors.h> @@ -41,10 +42,14 @@ #include "calendar-commands.h" #include "calendar-config.h" #include "component-factory.h" +#include "comp-editor-factory.h" #include "control-factory.h" #include "itip-control-factory.h" #include "tasks-control-factory.h" +/* The component editor factory */ +static CompEditorFactory *comp_editor_factory = NULL; + static void init_bonobo (int argc, char **argv) { @@ -58,6 +63,35 @@ init_bonobo (int argc, char **argv) g_error (_("Could not initialize Bonobo")); } +/* Factory function for the calendar component factory; just creates and + * references a singleton service object. + */ +static BonoboObject * +comp_editor_factory_fn (BonoboGenericFactory *factory, void *data) +{ + if (!comp_editor_factory) { + comp_editor_factory = comp_editor_factory_new (); + if (!comp_editor_factory) + return NULL; + } + + bonobo_object_ref (BONOBO_OBJECT (comp_editor_factory)); + return BONOBO_OBJECT (comp_editor_factory); +} + +/* Creates and registers the component editor factory */ +static void +component_editor_factory_init (void) +{ + BonoboGenericFactory *factory; + + factory = bonobo_generic_factory_new ( + "OAFIID:GNOME_Evolution_Calendar_CompEditorFactory_Factory", + comp_editor_factory_fn, NULL); + if (!factory) + g_error (_("Could not create the component editor factory")); +} + int main (int argc, char **argv) { @@ -86,6 +120,7 @@ main (int argc, char **argv) component_factory_init (); itip_control_factory_init (); tasks_control_factory_init (); + component_editor_factory_init (); bonobo_main (); |