aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/gui/comp-editor-factory.c
diff options
context:
space:
mode:
authorFederico Mena Quintero <federico@ximian.com>2001-09-05 10:52:52 +0800
committerFederico Mena Quintero <federico@src.gnome.org>2001-09-05 10:52:52 +0800
commit7f6f7e52113103e38dbb27aef10c1ffc25f269ec (patch)
treef34fb410189e6dedb8a2bcfcf079b85151dcdc84 /calendar/gui/comp-editor-factory.c
parentbc21d949ca1a3a1eb0fc5dd735411030c01c6b79 (diff)
downloadgsoc2013-evolution-7f6f7e52113103e38dbb27aef10c1ffc25f269ec.tar
gsoc2013-evolution-7f6f7e52113103e38dbb27aef10c1ffc25f269ec.tar.gz
gsoc2013-evolution-7f6f7e52113103e38dbb27aef10c1ffc25f269ec.tar.bz2
gsoc2013-evolution-7f6f7e52113103e38dbb27aef10c1ffc25f269ec.tar.lz
gsoc2013-evolution-7f6f7e52113103e38dbb27aef10c1ffc25f269ec.tar.xz
gsoc2013-evolution-7f6f7e52113103e38dbb27aef10c1ffc25f269ec.tar.zst
gsoc2013-evolution-7f6f7e52113103e38dbb27aef10c1ffc25f269ec.zip
Implemented.
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. svn path=/trunk/; revision=12619
Diffstat (limited to 'calendar/gui/comp-editor-factory.c')
-rw-r--r--calendar/gui/comp-editor-factory.c474
1 files changed, 437 insertions, 37 deletions
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);
}