aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/gui/calendar-model.c
diff options
context:
space:
mode:
Diffstat (limited to 'calendar/gui/calendar-model.c')
-rw-r--r--calendar/gui/calendar-model.c1583
1 files changed, 0 insertions, 1583 deletions
diff --git a/calendar/gui/calendar-model.c b/calendar/gui/calendar-model.c
deleted file mode 100644
index 2337d70ffd..0000000000
--- a/calendar/gui/calendar-model.c
+++ /dev/null
@@ -1,1583 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Evolution calendar - Data model for ETable
- *
- * Copyright (C) 2000 Helix Code, Inc.
- *
- * Authors: Federico Mena-Quintero <federico@helixcode.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/* We need this for strptime. */
-#define _XOPEN_SOURCE
-
-#include <config.h>
-#include <ctype.h>
-#undef _XOPEN_SOURCE
-#include <sys/time.h>
-#define _XOPEN_SOURCE
-#include <time.h>
-#include <gtk/gtksignal.h>
-#include <libgnomeui/gnome-messagebox.h>
-#include <libgnomeui/gnome-stock.h>
-#include "calendar-model.h"
-#include "calendar-commands.h"
-
-
-
-/* Private part of the ECalendarModel structure */
-typedef struct {
- /* Calendar client we are using */
- CalClient *client;
-
- /* Types of objects we are dealing with */
- CalObjType type;
-
- /* Array of pointers to calendar objects */
- GArray *objects;
-
- /* UID -> array index hash */
- GHashTable *uid_index_hash;
-
- /* The row currently being added via the 'click-to-add' row. */
- gint row_being_added;
-
- /* Source ID of our idle function to add the new row. */
- guint idle_id;
-} CalendarModelPrivate;
-
-
-
-static void calendar_model_class_init (CalendarModelClass *class);
-static void calendar_model_init (CalendarModel *model);
-static void calendar_model_destroy (GtkObject *object);
-
-static int calendar_model_column_count (ETableModel *etm);
-static int calendar_model_row_count (ETableModel *etm);
-static void *calendar_model_value_at (ETableModel *etm, int col, int row);
-static void calendar_model_set_value_at (ETableModel *etm, int col, int row, const void *value);
-static gboolean calendar_model_is_cell_editable (ETableModel *etm, int col, int row);
-static gint calendar_model_append_row (ETableModel *etm);
-static gboolean calendar_model_commit_new_row (gpointer data);
-static void *calendar_model_duplicate_value (ETableModel *etm, int col, const void *value);
-static void calendar_model_free_value (ETableModel *etm, int col, void *value);
-static void *calendar_model_initialize_value (ETableModel *etm, int col);
-static gboolean calendar_model_value_is_empty (ETableModel *etm, int col, const void *value);
-#if 0
-static char * calendar_model_value_to_string (ETableModel *etm, int col, const void *value);
-#endif
-static void load_objects (CalendarModel *model);
-static int remove_object (CalendarModel *model, const char *uid);
-
-static ETableModelClass *parent_class;
-
-
-
-/**
- * calendar_model_get_type:
- * @void:
- *
- * Registers the #CalendarModel class if necessary, and returns the type ID
- * associated to it.
- *
- * Return value: The type ID of the #CalendarModel class.
- **/
-GtkType
-calendar_model_get_type (void)
-{
- static GtkType calendar_model_type = 0;
-
- if (!calendar_model_type) {
- static GtkTypeInfo calendar_model_info = {
- "CalendarModel",
- sizeof (CalendarModel),
- sizeof (CalendarModelClass),
- (GtkClassInitFunc) calendar_model_class_init,
- (GtkObjectInitFunc) calendar_model_init,
- NULL, /* reserved_1 */
- NULL, /* reserved_2 */
- (GtkClassInitFunc) NULL
- };
-
- calendar_model_type = gtk_type_unique (E_TABLE_MODEL_TYPE, &calendar_model_info);
- }
-
- return calendar_model_type;
-}
-
-/* Class initialization function for the calendar table model */
-static void
-calendar_model_class_init (CalendarModelClass *class)
-{
- GtkObjectClass *object_class;
- ETableModelClass *etm_class;
-
- object_class = (GtkObjectClass *) class;
- etm_class = (ETableModelClass *) class;
-
- parent_class = gtk_type_class (E_TABLE_MODEL_TYPE);
-
- object_class->destroy = calendar_model_destroy;
-
- etm_class->column_count = calendar_model_column_count;
- etm_class->row_count = calendar_model_row_count;
- etm_class->value_at = calendar_model_value_at;
- etm_class->set_value_at = calendar_model_set_value_at;
- etm_class->is_cell_editable = calendar_model_is_cell_editable;
- etm_class->append_row = calendar_model_append_row;
- etm_class->duplicate_value = calendar_model_duplicate_value;
- etm_class->free_value = calendar_model_free_value;
- etm_class->initialize_value = calendar_model_initialize_value;
- etm_class->value_is_empty = calendar_model_value_is_empty;
-#if 0
- etm_class->value_to_string = calendar_model_value_to_string;
-#endif
-}
-
-/* Object initialization function for the calendar table model */
-static void
-calendar_model_init (CalendarModel *model)
-{
- CalendarModelPrivate *priv;
-
- priv = g_new0 (CalendarModelPrivate, 1);
- model->priv = priv;
-
- priv->objects = g_array_new (FALSE, TRUE, sizeof (iCalObject *));
- priv->uid_index_hash = g_hash_table_new (g_str_hash, g_str_equal);
-
- priv->row_being_added = -1;
- priv->idle_id = 0;
-}
-
-/* Called from g_hash_table_foreach_remove(), frees a stored UID->index
- * mapping.
- */
-static gboolean
-free_uid_index (gpointer key, gpointer value, gpointer data)
-{
- int *idx;
-
- idx = value;
- g_free (idx);
-
- return TRUE;
-}
-
-/* Frees the objects stored in the calendar model */
-static void
-free_objects (CalendarModel *model)
-{
- CalendarModelPrivate *priv;
- int i;
-
- priv = model->priv;
-
- g_hash_table_foreach_remove (priv->uid_index_hash, free_uid_index, NULL);
-
- for (i = 0; i < priv->objects->len; i++) {
- iCalObject *ico;
-
- ico = g_array_index (priv->objects, iCalObject *, i);
- g_assert (ico != NULL);
- ical_object_unref (ico);
- }
-
- g_array_set_size (priv->objects, 0);
-}
-
-/* Destroy handler for the calendar table model */
-static void
-calendar_model_destroy (GtkObject *object)
-{
- CalendarModel *model;
- CalendarModelPrivate *priv;
-
- g_return_if_fail (object != NULL);
- g_return_if_fail (IS_CALENDAR_MODEL (object));
-
- model = CALENDAR_MODEL (object);
- priv = model->priv;
-
- /* Remove any idle function. */
- if (priv->idle_id)
- g_source_remove (priv->idle_id);
-
- /* Free the calendar client interface object */
-
- if (priv->client) {
- gtk_signal_disconnect_by_data (GTK_OBJECT (priv->client), model);
- gtk_object_unref (GTK_OBJECT (priv->client));
- priv->client = NULL;
- }
-
- /* Free the uid->index hash data and the array of UIDs */
-
- free_objects (model);
-
- g_hash_table_destroy (priv->uid_index_hash);
- priv->uid_index_hash = NULL;
-
- g_array_free (priv->objects, TRUE);
- priv->objects = NULL;
-
- /* Free the private structure */
-
- g_free (priv);
- model->priv = NULL;
-
- if (GTK_OBJECT_CLASS (parent_class)->destroy)
- (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
-}
-
-
-
-/* ETableModel methods */
-
-/* column_count handler for the calendar table model */
-static int
-calendar_model_column_count (ETableModel *etm)
-{
- return ICAL_OBJECT_FIELD_NUM_FIELDS;
-}
-
-/* row_count handler for the calendar table model */
-static int
-calendar_model_row_count (ETableModel *etm)
-{
- CalendarModel *model;
- CalendarModelPrivate *priv;
-
- model = CALENDAR_MODEL (etm);
- priv = model->priv;
-
- return priv->objects->len;
-}
-
-static char*
-get_time_t (time_t *t, gboolean skip_midnight)
-{
- static char buffer[32];
- struct tm *tmp_tm;
-
- if (*t <= 0) {
- buffer[0] = '\0';
- } else {
- tmp_tm = localtime (t);
-
- if (skip_midnight && tmp_tm->tm_hour == 0
- && tmp_tm->tm_min == 0 && tmp_tm->tm_sec == 0)
- strftime (buffer, 32, "%a %x", tmp_tm);
- else
- strftime (buffer, 32, "%a %x %T", tmp_tm);
- }
-
- return buffer;
-}
-
-static char*
-get_geo (iCalGeo *geo)
-{
- static gchar buffer[32];
-
- if (!geo->valid)
- buffer[0] = '\0';
- else
- g_snprintf (buffer, 32, "%g, %g", geo->latitude,
- geo->longitude);
-
- return buffer;
-}
-
-
-/* value_at handler for the calendar table model */
-static void *
-calendar_model_value_at (ETableModel *etm, int col, int row)
-{
- CalendarModel *model;
- CalendarModelPrivate *priv;
- iCalObject *ico;
- static char buffer[16];
-
- model = CALENDAR_MODEL (etm);
- priv = model->priv;
-
- g_return_val_if_fail (col >= 0 && col < ICAL_OBJECT_FIELD_NUM_FIELDS, NULL);
- g_return_val_if_fail (row >= 0 && row < priv->objects->len, NULL);
-
- ico = g_array_index (priv->objects, iCalObject *, row);
- g_assert (ico != NULL);
-
- switch (col) {
- case ICAL_OBJECT_FIELD_COMMENT:
- return ico->comment ? ico->comment : "";
-
- case ICAL_OBJECT_FIELD_COMPLETED:
- return get_time_t (&ico->completed, FALSE);
-
- case ICAL_OBJECT_FIELD_CREATED:
- return get_time_t (&ico->created, FALSE);
-
- case ICAL_OBJECT_FIELD_DESCRIPTION:
- return ico->desc ? ico->desc : "";
-
- case ICAL_OBJECT_FIELD_DTSTAMP:
- return get_time_t (&ico->dtstamp, FALSE);
-
- case ICAL_OBJECT_FIELD_DTSTART:
- return get_time_t (&ico->dtstart, FALSE);
-
- case ICAL_OBJECT_FIELD_DTEND:
- return get_time_t (&ico->dtend, FALSE);
-
- case ICAL_OBJECT_FIELD_GEO:
- return get_geo (&ico->geo);
-
- case ICAL_OBJECT_FIELD_LAST_MOD:
- return get_time_t (&ico->last_mod, FALSE);
-
- case ICAL_OBJECT_FIELD_LOCATION:
- return ico->location ? ico->location : "";
-
- case ICAL_OBJECT_FIELD_ORGANIZER:
- if (ico->organizer && ico->organizer->name)
- return ico->organizer->name;
- else
- return "";
-
- case ICAL_OBJECT_FIELD_PERCENT:
- g_snprintf (buffer, 16, "%i", ico->percent);
- return buffer;
-
- case ICAL_OBJECT_FIELD_PRIORITY:
- g_snprintf (buffer, 16, "%i", ico->priority);
- return buffer;
-
- case ICAL_OBJECT_FIELD_SUMMARY:
- return ico->summary ? ico->summary : "";
-
- case ICAL_OBJECT_FIELD_URL:
- return ico->url ? ico->url : "";
-
- case ICAL_OBJECT_FIELD_HAS_ALARMS:
- return (gpointer) (ico->dalarm.enabled || ico->aalarm.enabled
- || ico->palarm.enabled || ico->malarm.enabled);
-
- case ICAL_OBJECT_FIELD_ICON:
- /* FIXME: Also support 'Assigned to me' & 'Assigned to someone
- else'. */
- if (ico->recur)
- return GINT_TO_POINTER (1);
- else
- return GINT_TO_POINTER (0);
-
- case ICAL_OBJECT_FIELD_COMPLETE:
- /* FIXME: Should check if the Completed field is set? */
- return GINT_TO_POINTER (ico->completed > 0);
-
- case ICAL_OBJECT_FIELD_RECURRING:
- return GINT_TO_POINTER (ico->recur != NULL);
-
- case ICAL_OBJECT_FIELD_OVERDUE:
- /* I don't think calling time() is too slow. It takes about
- 4 times as long as calling strlen() on a 20-char string
- on my machine. */
- if (ico->percent != 100
- && ico->dtend > 0
- && ico->dtend < time (NULL))
- return GINT_TO_POINTER (TRUE);
- return GINT_TO_POINTER (FALSE);
-
- case ICAL_OBJECT_FIELD_COLOR:
- if (ico->percent != 100
- && ico->dtend > 0
- && ico->dtend < time (NULL))
- return "red";
- return NULL;
-
- default:
- g_message ("calendar_model_value_at(): Requested invalid column %d", col);
- return NULL;
- }
-}
-
-/* Replaces a string */
-static void
-set_string (char **dest, const char *value)
-{
- if (*dest)
- g_free (*dest);
-
- if (value)
- *dest = g_strdup (value);
- else
- *dest = NULL;
-}
-
-
-static gboolean
-string_is_empty (const char *value)
-{
- const char *p;
- gboolean empty = TRUE;
-
- if (value) {
- p = value;
- while (*p) {
- if (!isspace (*p)) {
- empty = FALSE;
- break;
- }
- p++;
- }
- }
- return empty;
-}
-
-
-/* FIXME: We need to set the "transient_for" property for the dialog, but
- the model doesn't know anything about the windows. */
-static void
-show_date_warning ()
-{
- GtkWidget *dialog;
- char buffer[32], message[256];
- time_t t;
- struct tm *tmp_tm;
-
- t = time (NULL);
- tmp_tm = localtime (&t);
- strftime (buffer, 32, "%a %x %T", tmp_tm);
-
- g_snprintf (message, 256,
- _("The date must be entered in the format: \n\n%s"),
- buffer);
-
- dialog = gnome_message_box_new (message,
- GNOME_MESSAGE_BOX_ERROR,
- GNOME_STOCK_BUTTON_OK, NULL);
- gtk_widget_show (dialog);
-}
-
-
-/* Replaces a time_t value */
-static void
-set_time_t (time_t *dest, const char *value)
-{
- struct tm tmp_tm;
- struct tm *today_tm;
- time_t t;
- const char *p;
-
- if (string_is_empty (value)) {
- *dest = 0;
- } else {
- /* Skip any weekday name. */
- p = strptime (value, "%a", &tmp_tm);
- if (!p)
- p = value;
-
- /* Try to match the full date & time, or without the seconds,
- or just the date, or just the time with/without seconds.
- The info pages say we should clear the tm before calling
- strptime. It also means that if we don't match a time we
- get 00:00:00 which is good. */
- memset (&tmp_tm, 0, sizeof (tmp_tm));
- if (!strptime (value, "%x %T", &tmp_tm)) {
- memset (&tmp_tm, 0, sizeof (tmp_tm));
- if (!strptime (value, "%x %H:%M", &tmp_tm)) {
- memset (&tmp_tm, 0, sizeof (tmp_tm));
- if (!strptime (value, "%x", &tmp_tm)) {
- memset (&tmp_tm, 0, sizeof (tmp_tm));
- if (!strptime (value, "%T", &tmp_tm)) {
- memset (&tmp_tm, 0, sizeof (tmp_tm));
- if (!strptime (value, "%H:%M", &tmp_tm)) {
-
- g_warning ("Couldn't parse date string");
- show_date_warning ();
- return;
- }
- }
-
- /* We only got a time, so we use the
- current day. */
- t = time (NULL);
- today_tm = localtime (&t);
- tmp_tm.tm_mday = today_tm->tm_mday;
- tmp_tm.tm_mon = today_tm->tm_mon;
- tmp_tm.tm_year = today_tm->tm_year;
- }
- }
- }
-
- tmp_tm.tm_isdst = -1;
- *dest = mktime (&tmp_tm);
- }
-}
-
-
-/* FIXME: We need to set the "transient_for" property for the dialog, but
- the model doesn't know anything about the windows. */
-static void
-show_geo_warning ()
-{
- GtkWidget *dialog;
-
- dialog = gnome_message_box_new (_("The geographical position must be entered in the format: \n\n45.436845,125.862501"),
- GNOME_MESSAGE_BOX_ERROR,
- GNOME_STOCK_BUTTON_OK, NULL);
- gtk_widget_show (dialog);
-}
-
-
-/* Replaces a geo value */
-static void
-set_geo (iCalGeo *dest, const char *value)
-{
- double latitude, longitude;
- gint matched;
-
- if (!string_is_empty (value)) {
- matched = sscanf (value, "%lg , %lg", &latitude, &longitude);
-
- if (matched != 2) {
- show_geo_warning ();
- } else {
- dest->valid = TRUE;
- dest->latitude = latitude;
- dest->longitude = longitude;
- }
- } else {
- dest->valid = FALSE;
- dest->latitude = 0.0;
- dest->longitude = 0.0;
- }
-}
-
-/* Replaces a person value */
-static void
-set_person (iCalPerson **dest, const iCalPerson *value)
-{
- /* FIXME: This can't be set at present so it shouldn't be called. */
-}
-
-/* FIXME: We need to set the "transient_for" property for the dialog, but
- the model doesn't know anything about the windows. */
-static void
-show_percent_warning ()
-{
- GtkWidget *dialog;
-
- dialog = gnome_message_box_new (_("The percent value must be between 0 and 100"),
- GNOME_MESSAGE_BOX_ERROR,
- GNOME_STOCK_BUTTON_OK, NULL);
- gtk_widget_show (dialog);
-}
-
-
-/* Sets an int value */
-static void
-set_percent (int *dest, const char *value)
-{
- gint matched, percent;
-
- if (!string_is_empty (value)) {
- matched = sscanf (value, "%i", &percent);
-
- if (matched != 1 || percent < 0 || percent > 100) {
- show_percent_warning ();
- } else {
- *dest = percent;
- }
- } else {
- *dest = 0;
- }
-}
-
-/* FIXME: We need to set the "transient_for" property for the dialog, but
- the model doesn't know anything about the windows. */
-static void
-show_priority_warning ()
-{
- GtkWidget *dialog;
-
- dialog = gnome_message_box_new (_("The priority must be between 0 and 10"),
- GNOME_MESSAGE_BOX_ERROR,
- GNOME_STOCK_BUTTON_OK, NULL);
- gtk_widget_show (dialog);
-}
-
-
-/* Sets an int value */
-static void
-set_priority (int *dest, const char *value)
-{
- gint matched, priority;
-
- if (!string_is_empty (value)) {
- matched = sscanf (value, "%i", &priority);
-
- if (matched != 1 || priority < 0 || priority > 10) {
- show_priority_warning ();
- } else {
- *dest = priority;
- }
- } else {
- *dest = 0;
- }
-}
-
-/* set_value_at handler for the calendar table model */
-static void
-calendar_model_set_value_at (ETableModel *etm, int col, int row, const void *value)
-{
- CalendarModel *model;
- CalendarModelPrivate *priv;
- iCalObject *ico;
-
- model = CALENDAR_MODEL (etm);
- priv = model->priv;
-
- g_return_if_fail (col >= 0 && col < ICAL_OBJECT_FIELD_NUM_FIELDS);
- g_return_if_fail (row >= 0 && row < priv->objects->len);
-
- ico = g_array_index (priv->objects, iCalObject *, row);
- g_assert (ico != NULL);
-
- switch (col) {
- case ICAL_OBJECT_FIELD_COMMENT:
- set_string (&ico->comment, value);
- break;
-
- case ICAL_OBJECT_FIELD_COMPLETED:
- /* FIXME: Set status, percent etc. fields as well. */
- set_time_t (&ico->completed, value);
- break;
-
- case ICAL_OBJECT_FIELD_CREATED:
- set_time_t (&ico->created, value);
- break;
-
- case ICAL_OBJECT_FIELD_DESCRIPTION:
- set_string (&ico->desc, value);
- break;
-
- case ICAL_OBJECT_FIELD_DTSTAMP:
- set_time_t (&ico->dtstamp, value);
- break;
-
- case ICAL_OBJECT_FIELD_DTSTART:
- set_time_t (&ico->dtstart, value);
- break;
-
- case ICAL_OBJECT_FIELD_DTEND:
- set_time_t (&ico->dtend, value);
- break;
-
- case ICAL_OBJECT_FIELD_GEO:
- set_geo (&ico->geo, value);
- break;
-
- case ICAL_OBJECT_FIELD_LAST_MOD:
- set_time_t (&ico->last_mod, value);
- break;
-
- case ICAL_OBJECT_FIELD_LOCATION:
- set_string (&ico->location, value);
- break;
-
- case ICAL_OBJECT_FIELD_ORGANIZER:
- set_person (&ico->organizer, value);
- break;
-
- case ICAL_OBJECT_FIELD_PERCENT:
- /* FIXME: If set to 0 or 100 set other fields. */
- set_percent (&ico->percent, value);
- break;
-
- case ICAL_OBJECT_FIELD_PRIORITY:
- set_priority (&ico->priority, value);
- break;
-
- case ICAL_OBJECT_FIELD_SUMMARY:
- set_string (&ico->summary, value);
- break;
-
- case ICAL_OBJECT_FIELD_URL:
- set_string (&ico->url, value);
- break;
-
- case ICAL_OBJECT_FIELD_COMPLETE:
- /* FIXME: Need a ical_object_XXX function to mark an item
- complete, which will also set the 'Completed' time and
- maybe others such as the last modified fields. */
- ico->percent = 100;
- ico->completed = time (NULL);
- break;
-
- case ICAL_OBJECT_FIELD_HAS_ALARMS:
- case ICAL_OBJECT_FIELD_ICON:
- case ICAL_OBJECT_FIELD_RECURRING:
- case ICAL_OBJECT_FIELD_OVERDUE:
- case ICAL_OBJECT_FIELD_COLOR:
- /* These are all computed fields which can't be set, so we
- do nothing. Note that the 'click-to-add' item will set all
- fields when finished, so we don't want to output warnings
- here. */
- break;
-
- default:
- g_message ("calendar_model_set_value_at(): Requested invalid column %d", col);
- break;
- }
-
- if (ico->new)
- g_print ("Skipping update - new iCalObject\n");
- else if (!cal_client_update_object (priv->client, ico))
- g_message ("calendar_model_set_value_at(): Could not update the object!");
-}
-
-/* is_cell_editable handler for the calendar table model */
-static gboolean
-calendar_model_is_cell_editable (ETableModel *etm, int col, int row)
-{
- CalendarModel *model;
- CalendarModelPrivate *priv;
-
- model = CALENDAR_MODEL (etm);
- priv = model->priv;
-
- g_return_val_if_fail (col >= 0 && col < ICAL_OBJECT_FIELD_NUM_FIELDS, FALSE);
- /* We can't check this as 'click-to-add' passes row 0. */
- /*g_return_val_if_fail (row >= 0 && row < priv->objects->len, FALSE);*/
-
- switch (col) {
- case ICAL_OBJECT_FIELD_CREATED:
- case ICAL_OBJECT_FIELD_DTSTAMP:
- case ICAL_OBJECT_FIELD_LAST_MOD:
- case ICAL_OBJECT_FIELD_GEO:
- case ICAL_OBJECT_FIELD_HAS_ALARMS:
- case ICAL_OBJECT_FIELD_ICON:
- case ICAL_OBJECT_FIELD_RECURRING:
- case ICAL_OBJECT_FIELD_OVERDUE:
- case ICAL_OBJECT_FIELD_COLOR:
- return FALSE;
-
- default:
- return TRUE;
- }
-}
-
-static gint
-calendar_model_append_row (ETableModel *etm)
-{
- CalendarModel *model;
- CalendarModelPrivate *priv;
- iCalObject *ico;
- gint *new_idx;
-
- g_print ("In calendar_model_append_row\n");
-
- model = CALENDAR_MODEL (etm);
- priv = model->priv;
-
- if (priv->row_being_added != -1 || priv->idle_id != 0) {
- g_warning ("Already adding row");
- return -1;
- }
-
- ico = ical_new ("", user_name, "");
- ico->type = ICAL_TODO;
- ico->new = TRUE;
-
- g_array_append_val (priv->objects, ico);
- new_idx = g_new (int, 1);
- *new_idx = priv->objects->len - 1;
- g_hash_table_insert (priv->uid_index_hash, ico->uid, new_idx);
-
- /* Notify the views about the new row. */
- e_table_model_row_inserted (etm, *new_idx);
-
- /* We add an idle function to pass the new iCalObject to the server.
- We can't do it here since the values haven't been set yet.
- Maybe we could connect to the "row_inserted" signal, though I'm
- not sure when that is emitted. */
- priv->row_being_added = *new_idx;
- priv->idle_id = g_idle_add_full (G_PRIORITY_HIGH,
- calendar_model_commit_new_row,
- model, NULL);
-
- return *new_idx;
-}
-
-static gboolean
-calendar_model_commit_new_row (gpointer data)
-{
- CalendarModel *model;
- CalendarModelPrivate *priv;
- iCalObject *ico;
-
- g_print ("Committing new row\n");
-
- model = CALENDAR_MODEL (data);
- priv = model->priv;
-
- if (priv->row_being_added == -1) {
- g_warning ("No row to commit");
- priv->idle_id = 0;
- return FALSE;
- }
-
- ico = g_array_index (priv->objects, iCalObject *,
- priv->row_being_added);
-
- if (!cal_client_update_object (priv->client, ico)) {
- /* FIXME: Show error dialog. */
- g_message ("calendar_model_commit_new_row(): Could not add new object!");
- remove_object (model, ico->uid);
- e_table_model_row_deleted (E_TABLE_MODEL (model),
- priv->row_being_added);
- }
-
- priv->row_being_added = -1;
- priv->idle_id = 0;
- return FALSE;
-}
-
-/* Duplicates a string value */
-static char *
-dup_string (const char *value)
-{
- return g_strdup (value);
-}
-
-/* Duplicates a time_t value */
-static char *
-dup_time_t (const char *value)
-{
- return g_strdup (value);
-
-#if 0
- time_t *t;
-
- t = g_new (time_t, 1);
- *t = *value;
- return t;
-#endif
-}
-
-/* Duplicates a geo value */
-static char *
-dup_geo (const char *value)
-{
- return g_strdup (value);
-
-#if 0
- iCalGeo *geo;
-
- geo = g_new (iCalGeo, 1);
- *geo = *value;
- return geo;
-#endif
-}
-
-/* Duplicates a person value */
-static char *
-dup_person (const char *value)
-{
- /* FIXME */
- return g_strdup (value);
-}
-
-/* Duplicates an int value */
-static char *
-dup_int (const char *value)
-{
- return g_strdup (value);
-
-#if 0
- int *v;
-
- v = g_new (int, 1);
- *v = *value;
- return v;
-#endif
-}
-
-/* duplicate_value handler for the calendar table model */
-static void *
-calendar_model_duplicate_value (ETableModel *etm, int col, const void *value)
-{
- g_return_val_if_fail (col >= 0 && col < ICAL_OBJECT_FIELD_NUM_FIELDS, NULL);
-
- switch (col) {
- case ICAL_OBJECT_FIELD_COMMENT:
- return dup_string (value);
-
- case ICAL_OBJECT_FIELD_COMPLETED:
- return dup_time_t (value);
-
- case ICAL_OBJECT_FIELD_CREATED:
- return dup_time_t (value);
-
- case ICAL_OBJECT_FIELD_DESCRIPTION:
- return dup_string (value);
-
- case ICAL_OBJECT_FIELD_DTSTAMP:
- return dup_time_t (value);
-
- case ICAL_OBJECT_FIELD_DTSTART:
- return dup_time_t (value);
-
- case ICAL_OBJECT_FIELD_DTEND:
- return dup_time_t (value);
-
- case ICAL_OBJECT_FIELD_GEO:
- return dup_geo (value);
-
- case ICAL_OBJECT_FIELD_LAST_MOD:
- return dup_time_t (value);
-
- case ICAL_OBJECT_FIELD_LOCATION:
- return dup_string (value);
-
- case ICAL_OBJECT_FIELD_ORGANIZER:
- return dup_person (value);
-
- case ICAL_OBJECT_FIELD_PERCENT:
- return dup_int (value);
-
- case ICAL_OBJECT_FIELD_PRIORITY:
- return dup_int (value);
-
- case ICAL_OBJECT_FIELD_SUMMARY:
- return dup_string (value);
-
- case ICAL_OBJECT_FIELD_URL:
- return dup_string (value);
-
- case ICAL_OBJECT_FIELD_HAS_ALARMS:
- return (void *) value;
-
- case ICAL_OBJECT_FIELD_ICON:
- case ICAL_OBJECT_FIELD_COMPLETE:
- case ICAL_OBJECT_FIELD_RECURRING:
- case ICAL_OBJECT_FIELD_OVERDUE:
- case ICAL_OBJECT_FIELD_COLOR:
- return (void *) value;
-
- default:
- g_message ("calendar_model_duplicate_value(): Requested invalid column %d", col);
- return NULL;
- }
-}
-
-/* free_value handler for the calendar table model */
-static void
-calendar_model_free_value (ETableModel *etm, int col, void *value)
-{
- g_return_if_fail (col >= 0 && col < ICAL_OBJECT_FIELD_NUM_FIELDS);
-
- switch (col) {
- case ICAL_OBJECT_FIELD_ORGANIZER:
- /* FIXME: this requires special handling for iCalPerson */
-
- break;
- case ICAL_OBJECT_FIELD_HAS_ALARMS:
- case ICAL_OBJECT_FIELD_ICON:
- case ICAL_OBJECT_FIELD_COMPLETE:
- case ICAL_OBJECT_FIELD_RECURRING:
- case ICAL_OBJECT_FIELD_OVERDUE:
- case ICAL_OBJECT_FIELD_COLOR:
- /* Do nothing. */
- break;
- default:
- g_free (value);
- }
-}
-
-/* Initializes a string value */
-static char *
-init_string (void)
-{
- return g_strdup ("");
-}
-
-/* Initializes a time_t value */
-static char *
-init_time_t (void)
-{
- return g_strdup ("");
-#if 0
- time_t *t;
-
- t = g_new (time_t, 1);
- *t = -1;
- return t;
-#endif
-}
-
-/* Initializes a geo value */
-static char *
-init_geo (void)
-{
- return g_strdup ("");
-#if 0
- iCalGeo *geo;
-
- geo = g_new (iCalGeo, 1);
- geo->valid = FALSE;
- geo->latitude = 0.0;
- geo->longitude = 0.0;
- return geo;
-#endif
-}
-
-/* Initializes a person value */
-static char *
-init_person (void)
-{
- /* FIXME */
- return g_strdup ("");
-}
-
-/* Initializes an int value */
-static char *
-init_int (void)
-{
- return g_strdup ("");
-
-#if 0
- int *v;
-
- v = g_new (int, 1);
- *v = 0;
- return v;
-#endif
-}
-
-/* initialize_value handler for the calendar table model */
-static void *
-calendar_model_initialize_value (ETableModel *etm, int col)
-{
- g_return_val_if_fail (col >= 0 && col < ICAL_OBJECT_FIELD_NUM_FIELDS, NULL);
-
- switch (col) {
- case ICAL_OBJECT_FIELD_COMMENT:
- return init_string ();
-
- case ICAL_OBJECT_FIELD_COMPLETED:
- return init_time_t ();
-
- case ICAL_OBJECT_FIELD_CREATED:
- return init_time_t ();
-
- case ICAL_OBJECT_FIELD_DESCRIPTION:
- return init_string ();
-
- case ICAL_OBJECT_FIELD_DTSTAMP:
- return init_time_t ();
-
- case ICAL_OBJECT_FIELD_DTSTART:
- return init_time_t ();
-
- case ICAL_OBJECT_FIELD_DTEND:
- return init_time_t ();
-
- case ICAL_OBJECT_FIELD_GEO:
- return init_geo ();
-
- case ICAL_OBJECT_FIELD_LAST_MOD:
- return init_time_t ();
-
- case ICAL_OBJECT_FIELD_LOCATION:
- return init_string ();
-
- case ICAL_OBJECT_FIELD_ORGANIZER:
- return init_person ();
-
- case ICAL_OBJECT_FIELD_PERCENT:
- return init_int ();
-
- case ICAL_OBJECT_FIELD_PRIORITY:
- return init_int ();
-
- case ICAL_OBJECT_FIELD_SUMMARY:
- return init_string ();
-
- case ICAL_OBJECT_FIELD_URL:
- return init_string ();
-
- case ICAL_OBJECT_FIELD_HAS_ALARMS:
- return NULL; /* "false" */
-
- case ICAL_OBJECT_FIELD_ICON:
- case ICAL_OBJECT_FIELD_COMPLETE:
- case ICAL_OBJECT_FIELD_RECURRING:
- case ICAL_OBJECT_FIELD_OVERDUE:
- return GINT_TO_POINTER (0);
-
- case ICAL_OBJECT_FIELD_COLOR:
- return NULL;
-
- default:
- g_message ("calendar_model_initialize_value(): Requested invalid column %d", col);
- return NULL;
- }
-}
-
-
-/* Returns whether a time_t is empty */
-static gboolean
-time_t_is_empty (const char *str)
-{
- return string_is_empty (str);
-#if 0
- return (*t <= 0);
-#endif
-}
-
-/* Returns whether a geo is empty */
-static gboolean
-geo_is_empty (const char *str)
-{
- return string_is_empty (str);
-#if 0
- return !geo->valid;
-#endif
-}
-
-/* Returns whether a person is empty */
-static gboolean
-person_is_empty (const char *str)
-{
- /* FIXME */
- return string_is_empty (str);
-}
-
-/* value_is_empty handler for the calendar model. This should return TRUE
- unless a significant value has been set. The 'click-to-add' feature
- checks all fields to see if any are not empty and if so it adds a new
- row, so we only want to return FALSE if we have a useful object. */
-static gboolean
-calendar_model_value_is_empty (ETableModel *etm, int col, const void *value)
-{
- g_return_val_if_fail (col >= 0 && col < ICAL_OBJECT_FIELD_NUM_FIELDS, TRUE);
-
- switch (col) {
- case ICAL_OBJECT_FIELD_COMMENT:
- return string_is_empty (value);
-
- case ICAL_OBJECT_FIELD_COMPLETED:
- return time_t_is_empty (value);
-
- case ICAL_OBJECT_FIELD_CREATED:
- return time_t_is_empty (value);
-
- case ICAL_OBJECT_FIELD_DESCRIPTION:
- return string_is_empty (value);
-
- case ICAL_OBJECT_FIELD_DTSTAMP:
- return time_t_is_empty (value);
-
- case ICAL_OBJECT_FIELD_DTSTART:
- return time_t_is_empty (value);
-
- case ICAL_OBJECT_FIELD_DTEND:
- return time_t_is_empty (value);
-
- case ICAL_OBJECT_FIELD_GEO:
- return geo_is_empty (value);
-
- case ICAL_OBJECT_FIELD_LAST_MOD:
- return time_t_is_empty (value);
-
- case ICAL_OBJECT_FIELD_LOCATION:
- return string_is_empty (value);
-
- case ICAL_OBJECT_FIELD_ORGANIZER:
- return person_is_empty (value);
-
- case ICAL_OBJECT_FIELD_PERCENT:
- return string_is_empty (value);
-
- case ICAL_OBJECT_FIELD_PRIORITY:
- return string_is_empty (value);
-
- case ICAL_OBJECT_FIELD_SUMMARY:
- return string_is_empty (value);
-
- case ICAL_OBJECT_FIELD_URL:
- return string_is_empty (value);
-
- case ICAL_OBJECT_FIELD_HAS_ALARMS:
- case ICAL_OBJECT_FIELD_ICON:
- case ICAL_OBJECT_FIELD_COMPLETE:
- case ICAL_OBJECT_FIELD_RECURRING:
- case ICAL_OBJECT_FIELD_OVERDUE:
- case ICAL_OBJECT_FIELD_COLOR:
- return TRUE;
-
- default:
- g_message ("calendar_model_value_is_empty(): Requested invalid column %d", col);
- return TRUE;
- }
-}
-
-
-
-/**
- * calendar_model_new:
- *
- * Creates a new calendar model. It must be told about the calendar client
- * interface object it will monitor with calendar_model_set_cal_client().
- *
- * Return value: A newly-created calendar model.
- **/
-CalendarModel *
-calendar_model_new (void)
-{
- return CALENDAR_MODEL (gtk_type_new (TYPE_CALENDAR_MODEL));
-}
-
-
-/* Callback used when a calendar is loaded into the server */
-static void
-cal_loaded_cb (CalClient *client,
- CalClientLoadStatus status,
- CalendarModel *model)
-{
- g_return_if_fail (IS_CALENDAR_MODEL (model));
-
- load_objects (model);
- e_table_model_changed (E_TABLE_MODEL (model));
-}
-
-
-/* Removes an object from the model and updates all the indices that follow.
- * Returns the index of the object that was removed, or -1 if no object with
- * such UID was found.
- */
-static int
-remove_object (CalendarModel *model, const char *uid)
-{
- CalendarModelPrivate *priv;
- int *idx;
- iCalObject *orig_ico;
- int i;
- int n;
-
- priv = model->priv;
-
- /* Find the index of the object to be removed */
-
- idx = g_hash_table_lookup (priv->uid_index_hash, uid);
- if (!idx)
- return -1;
-
- orig_ico = g_array_index (priv->objects, iCalObject *, *idx);
- g_assert (orig_ico != NULL);
-
- /* Decrease the indices of all the objects that follow in the array */
-
- for (i = *idx + 1; i < priv->objects->len; i++) {
- iCalObject *ico;
- int *ico_idx;
-
- ico = g_array_index (priv->objects, iCalObject *, i);
- g_assert (ico != NULL);
-
- ico_idx = g_hash_table_lookup (priv->uid_index_hash, ico->uid);
- g_assert (ico_idx != NULL);
-
- (*ico_idx)--;
- g_assert (*ico_idx >= 0);
- }
-
- /* Remove this object from the array and hash */
-
- g_hash_table_remove (priv->uid_index_hash, uid);
- g_array_remove_index (priv->objects, *idx);
-
- ical_object_unref (orig_ico);
-
- n = *idx;
- g_free (idx);
-
- return n;
-}
-
-/* Callback used when an object is updated in the server */
-static void
-obj_updated_cb (CalClient *client, const char *uid, gpointer data)
-{
- CalendarModel *model;
- CalendarModelPrivate *priv;
- int orig_idx;
- iCalObject *new_ico;
- int *new_idx;
- CalClientGetStatus status;
- gboolean added;
-
- model = CALENDAR_MODEL (data);
- priv = model->priv;
-
- orig_idx = remove_object (model, uid);
-
- status = cal_client_get_object (priv->client, uid, &new_ico);
-
- added = FALSE;
-
- switch (status) {
- case CAL_CLIENT_GET_SUCCESS:
- if (orig_idx == -1) {
- /* The object not in the model originally, so we just append it */
-
- g_array_append_val (priv->objects, new_ico);
-
- new_idx = g_new (int, 1);
- *new_idx = priv->objects->len - 1;
- g_hash_table_insert (priv->uid_index_hash, new_ico->uid, new_idx);
- } else {
- int i;
-
- /* Insert the new version of the object in its old position */
-
- g_array_insert_val (priv->objects, orig_idx, new_ico);
-
- new_idx = g_new (int, 1);
- *new_idx = orig_idx;
- g_hash_table_insert (priv->uid_index_hash, new_ico->uid, new_idx);
-
- /* Increase the indices of all subsequent objects */
-
- for (i = orig_idx + 1; i < priv->objects->len; i++) {
- iCalObject *ico;
- int *ico_idx;
-
- ico = g_array_index (priv->objects, iCalObject *, i);
- g_assert (ico != NULL);
-
- ico_idx = g_hash_table_lookup (priv->uid_index_hash, ico->uid);
- g_assert (ico_idx != NULL);
-
- (*ico_idx)++;
- }
- }
-
- e_table_model_row_changed (E_TABLE_MODEL (model), *new_idx);
- break;
-
- case CAL_CLIENT_GET_NOT_FOUND:
- /* Nothing; the object may have been removed from the server. We just
- * notify that the old object was deleted.
- */
- if (orig_idx != -1)
- e_table_model_row_deleted (E_TABLE_MODEL (model), orig_idx);
-
- break;
-
- case CAL_CLIENT_GET_SYNTAX_ERROR:
- g_message ("obj_updated_cb(): Syntax error when getting object `%s'", uid);
-
- /* Same notification as above */
- if (orig_idx != -1)
- e_table_model_row_deleted (E_TABLE_MODEL (model), orig_idx);
-
- break;
-
- default:
- g_assert_not_reached ();
- }
-}
-
-/* Callback used when an object is removed in the server */
-static void
-obj_removed_cb (CalClient *client, const char *uid, gpointer data)
-{
- CalendarModel *model;
- int idx;
-
- model = CALENDAR_MODEL (data);
-
- idx = remove_object (model, uid);
-
- if (idx != -1)
- e_table_model_row_deleted (E_TABLE_MODEL (model), idx);
-}
-
-/* Loads the required objects from the calendar client */
-static void
-load_objects (CalendarModel *model)
-{
- CalendarModelPrivate *priv;
- GList *uids;
- GList *l;
-
- priv = model->priv;
-
- uids = cal_client_get_uids (priv->client, priv->type);
-
- for (l = uids; l; l = l->next) {
- char *uid;
- iCalObject *ico;
- CalClientGetStatus status;
- int *idx;
-
- uid = l->data;
- status = cal_client_get_object (priv->client, uid, &ico);
-
- switch (status) {
- case CAL_CLIENT_GET_SUCCESS:
- break;
-
- case CAL_CLIENT_GET_NOT_FOUND:
- /* Nothing; the object may have been removed from the server */
- continue;
-
- case CAL_CLIENT_GET_SYNTAX_ERROR:
- g_message ("load_objects(): Syntax error when getting object `%s'", uid);
- continue;
-
- default:
- g_assert_not_reached ();
- }
-
- g_assert (ico->uid != NULL);
-
- /* FIXME: Why doesn't it just store the index in the hash
- table as a GINT_TO_POINTER? - Damon. */
- idx = g_new (int, 1);
-
- g_array_append_val (priv->objects, ico);
- *idx = priv->objects->len - 1;
-
- g_hash_table_insert (priv->uid_index_hash, ico->uid, idx);
- }
-
- cal_obj_uid_list_free (uids);
-}
-
-CalClient*
-calendar_model_get_cal_client (CalendarModel *model)
-{
- CalendarModelPrivate *priv;
-
- priv = model->priv;
-
- return priv->client;
-}
-
-
-/**
- * calendar_model_set_cal_client:
- * @model: A calendar model.
- * @client: A calendar client interface object.
- * @type: Type of objects to present.
- *
- * Sets the calendar client interface object that a calendar model will monitor.
- * It also sets the types of objects this model will present to an #ETable.
- **/
-void
-calendar_model_set_cal_client (CalendarModel *model, CalClient *client, CalObjType type)
-{
- CalendarModelPrivate *priv;
-
- g_return_if_fail (model != NULL);
- g_return_if_fail (IS_CALENDAR_MODEL (model));
-
- if (client)
- g_return_if_fail (IS_CAL_CLIENT (client));
-
- priv = model->priv;
-
- if (priv->client == client && priv->type == type)
- return;
-
- if (client)
- gtk_object_ref (GTK_OBJECT (client));
-
- if (priv->client) {
- gtk_signal_disconnect_by_data (GTK_OBJECT (priv->client), model);
- gtk_object_unref (GTK_OBJECT (priv->client));
- }
-
- free_objects (model);
-
- priv->client = client;
- priv->type = type;
-
- if (priv->client) {
- gtk_signal_connect (GTK_OBJECT (priv->client), "cal_loaded",
- GTK_SIGNAL_FUNC (cal_loaded_cb), model);
- gtk_signal_connect (GTK_OBJECT (priv->client), "obj_updated",
- GTK_SIGNAL_FUNC (obj_updated_cb), model);
- gtk_signal_connect (GTK_OBJECT (priv->client), "obj_removed",
- GTK_SIGNAL_FUNC (obj_removed_cb), model);
-
- load_objects (model);
- }
-
- e_table_model_changed (E_TABLE_MODEL (model));
-}
-
-
-void
-calendar_model_delete_task (CalendarModel *model,
- gint row)
-{
- CalendarModelPrivate *priv;
- iCalObject *ico;
-
- priv = model->priv;
- ico = g_array_index (priv->objects, iCalObject *, row);
-
- if (!cal_client_remove_object (priv->client, ico->uid))
- g_message ("calendar_model_mark_task_complete(): Could not update the object!");
-}
-
-
-void
-calendar_model_mark_task_complete (CalendarModel *model,
- gint row)
-{
- CalendarModelPrivate *priv;
- iCalObject *ico;
-
- priv = model->priv;
- ico = g_array_index (priv->objects, iCalObject *, row);
-
- /* FIXME: Need a function to do all this. */
- ico->percent = 100;
- ico->completed = time (NULL);
-
- if (!cal_client_update_object (priv->client, ico))
- g_message ("calendar_model_mark_task_complete(): Could not update the object!");
-}
-
-
-/* Frees the objects stored in the calendar model */
-iCalObject*
-calendar_model_get_cal_object (CalendarModel *model,
- gint row)
-{
- CalendarModelPrivate *priv;
-
- priv = model->priv;
-
- return g_array_index (priv->objects, iCalObject *, row);
-}
-