aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--calendar/ChangeLog16
-rw-r--r--calendar/gui/GNOME_Evolution_Calendar.oaf.in16
-rw-r--r--calendar/gui/Makefile.am2
-rw-r--r--calendar/gui/alarm-notify/alarm-queue.c52
-rw-r--r--calendar/gui/calendar-component.c116
-rw-r--r--calendar/gui/comp-editor-factory.c474
-rw-r--r--calendar/gui/component-factory.c116
-rw-r--r--calendar/gui/main.c35
8 files changed, 781 insertions, 46 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog
index 27d8d7a82e..881d010183 100644
--- a/calendar/ChangeLog
+++ b/calendar/ChangeLog
@@ -1,3 +1,19 @@
+2001-09-04 Federico Mena Quintero <federico@ximian.com>
+
+ * gui/component-factory.c (sc_user_create_new_item_cb):
+ Implemented.
+
+ * gui/main.c (component_editor_factory_init): New function to
+ create the factory for the comp_editor_factory.
+
+ * gui/comp-editor-factory.c: Finished implementation.
+
+ * gui/alarm-notify/alarm-queue.c (edit_component): Implemented the
+ Edit command.
+
+ * gui/Makefile.am (evolution_calendar_SOURCES): Added
+ comp-editor-factory.[ch] to the list of sources.
+
2001-09-03 Damon Chaplin <damon@ximian.com>
* gui/calendar-commands.c (calendar_control_activate):
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 ();