aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/gui/e-cal-model-tasks.c
diff options
context:
space:
mode:
authorRodrigo Moya <rodrigo@src.gnome.org>2003-08-08 00:38:20 +0800
committerRodrigo Moya <rodrigo@src.gnome.org>2003-08-08 00:38:20 +0800
commitdc84df9871b3171a21d62feec988160f3c608103 (patch)
tree29f8dfbfa57dc43ae07fe645a1664fc5b1222086 /calendar/gui/e-cal-model-tasks.c
parent64222beb23056f789551b79e78fa721d32408e9e (diff)
downloadgsoc2013-evolution-dc84df9871b3171a21d62feec988160f3c608103.tar.gz
gsoc2013-evolution-dc84df9871b3171a21d62feec988160f3c608103.tar.zst
gsoc2013-evolution-dc84df9871b3171a21d62feec988160f3c608103.zip
Merge new-calendar-branch into HEAD
svn path=/trunk/; revision=22129
Diffstat (limited to 'calendar/gui/e-cal-model-tasks.c')
-rw-r--r--calendar/gui/e-cal-model-tasks.c904
1 files changed, 904 insertions, 0 deletions
diff --git a/calendar/gui/e-cal-model-tasks.c b/calendar/gui/e-cal-model-tasks.c
new file mode 100644
index 0000000000..7c97f5ba01
--- /dev/null
+++ b/calendar/gui/e-cal-model-tasks.c
@@ -0,0 +1,904 @@
+/* Evolution calendar - Data model for ETable
+ *
+ * Copyright (C) 2000 Ximian, Inc.
+ * Copyright (C) 2000 Ximian, Inc.
+ *
+ * Authors: Rodrigo Moya <rodrigo@ximian.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <math.h>
+#include <gtk/gtkmessagedialog.h>
+#include <libgnome/gnome-i18n.h>
+#include <gal/util/e-util.h>
+#include "e-cal-model-tasks.h"
+#include "e-cell-date-edit-text.h"
+#include "misc.h"
+
+struct _ECalModelTasksPrivate {
+};
+
+static void ecmt_class_init (ECalModelTasksClass *klass);
+static void ecmt_init (ECalModelTasks *model, ECalModelTasksClass *klass);
+static void ecmt_finalize (GObject *object);
+
+static int ecmt_column_count (ETableModel *etm);
+static void *ecmt_value_at (ETableModel *etm, int col, int row);
+static void ecmt_set_value_at (ETableModel *etm, int col, int row, const void *value);
+static gboolean ecmt_is_cell_editable (ETableModel *etm, int col, int row);
+static void ecmt_append_row (ETableModel *etm, ETableModel *source, int row);
+static void *ecmt_duplicate_value (ETableModel *etm, int col, const void *value);
+static void ecmt_free_value (ETableModel *etm, int col, void *value);
+static void *ecmt_initialize_value (ETableModel *etm, int col);
+static gboolean ecmt_value_is_empty (ETableModel *etm, int col, const void *value);
+static char *ecmt_value_to_string (ETableModel *etm, int col, const void *value);
+static const char *ecmt_get_color_for_component (ECalModel *model, ECalModelComponent *comp_data);
+
+static GObjectClass *parent_class = NULL;
+
+E_MAKE_TYPE (e_cal_model_tasks, "ECalModelTasks", ECalModelTasks, ecmt_class_init,
+ ecmt_init, E_TYPE_CAL_MODEL);
+
+static void
+ecmt_class_init (ECalModelTasksClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ ETableModelClass *etm_class = E_TABLE_MODEL_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->finalize = ecmt_finalize;
+
+ etm_class->column_count = ecmt_column_count;
+ etm_class->value_at = ecmt_value_at;
+ etm_class->set_value_at = ecmt_set_value_at;
+ etm_class->is_cell_editable = ecmt_is_cell_editable;
+ etm_class->append_row = ecmt_append_row;
+ etm_class->duplicate_value = ecmt_duplicate_value;
+ etm_class->free_value = ecmt_free_value;
+ etm_class->initialize_value = ecmt_initialize_value;
+ etm_class->value_is_empty = ecmt_value_is_empty;
+ etm_class->value_to_string = ecmt_value_to_string;
+}
+
+static void
+ecmt_init (ECalModelTasks *model, ECalModelTasksClass *klass)
+{
+ ECalModelTasksPrivate *priv;
+
+ priv = g_new0 (ECalModelTasksPrivate, 1);
+ model->priv = priv;
+
+ e_cal_model_set_component_kind (E_CAL_MODEL (model), ICAL_VTODO_COMPONENT);
+}
+
+static void
+ecmt_finalize (GObject *object)
+{
+ ECalModelTasksPrivate *priv;
+ ECalModelTasks *model = (ECalModelTasks *) object;
+
+ g_return_if_fail (E_IS_CAL_MODEL_TASKS (model));
+
+ priv = model->priv;
+ if (priv) {
+ g_free (priv);
+ model->priv = NULL;
+ }
+
+ if (parent_class->finalize)
+ parent_class->finalize (object);
+}
+
+/* ETableModel methods */
+static int
+ecmt_column_count (ETableModel *etm)
+{
+ return E_CAL_MODEL_TASKS_FIELD_LAST;
+}
+
+/* This makes sure a task is marked as complete.
+ It makes sure the "Date Completed" property is set. If the completed_date
+ is not -1, then that is used, otherwise if the "Date Completed" property
+ is not already set it is set to the current time.
+ It makes sure the percent is set to 100, and that the status is "Completed".
+ Note that this doesn't update the component on the server. */
+static void
+ensure_task_complete (ECalModelComponent *comp_data, time_t completed_date)
+{
+ icalproperty *prop;
+ gboolean set_completed = TRUE;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_COMPLETED_PROPERTY);
+
+ /* Date Completed. */
+ if (completed_date == -1) {
+ if (prop)
+ set_completed = FALSE;
+ else
+ completed_date = time (NULL);
+ }
+
+ if (set_completed) {
+ icaltimezone *utc_zone;
+ struct icaltimetype new_completed;
+
+ /* COMPLETED is stored in UTC. */
+ utc_zone = icaltimezone_get_utc_timezone ();
+ new_completed = icaltime_from_timet_with_zone (completed_date,
+ FALSE,
+ utc_zone);
+ if (prop)
+ icalproperty_set_completed (prop, new_completed);
+ else {
+ prop = icalproperty_new_completed (new_completed);
+ icalcomponent_add_property (comp_data->icalcomp, prop);
+ }
+ }
+
+ /* Percent. */
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
+ if (!prop)
+ icalcomponent_add_property (comp_data->icalcomp, icalproperty_new_percentcomplete (100));
+ else
+ icalproperty_set_percentcomplete (prop, 100);
+
+ /* Status. */
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_STATUS_PROPERTY);
+ if (prop)
+ icalproperty_set_status (prop, ICAL_STATUS_COMPLETED);
+ else
+ icalcomponent_add_property (comp_data->icalcomp, icalproperty_new_status (ICAL_STATUS_COMPLETED));
+}
+
+
+/* This makes sure a task is marked as incomplete. It clears the
+ "Date Completed" property. If the percent is set to 100 it removes it,
+ and if the status is "Completed" it sets it to "Needs Action".
+ Note that this doesn't update the component on the client. */
+static void
+ensure_task_not_complete (ECalModelComponent *comp_data)
+{
+ icalproperty *prop;
+
+ /* Date Completed. */
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_COMPLETED_PROPERTY);
+ if (prop) {
+ icalcomponent_remove_property (comp_data->icalcomp, prop);
+ icalproperty_free (prop);
+ }
+
+ /* Percent. */
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
+ if (prop) {
+ icalcomponent_remove_property (comp_data->icalcomp, prop);
+ icalproperty_free (prop);
+ }
+
+ /* Status. */
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
+ if (prop)
+ icalproperty_set_status (prop, ICAL_STATUS_NEEDSACTION);
+}
+
+static ECellDateEditValue *
+get_completed (ECalModelComponent *comp_data)
+{
+ /* FIXME */
+
+ return NULL;
+}
+
+static char *
+get_geo (ECalModelComponent *comp_data)
+{
+ icalproperty *prop;
+ struct icalgeotype geo;
+ static gchar buf[32];
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_GEO_PROPERTY);
+ if (prop) {
+ geo = icalproperty_get_geo (prop);
+ g_snprintf (buf, sizeof (buf), "%g %s, %g %s",
+ fabs (geo.lat),
+ geo.lat >= 0.0 ? _("N") : _("S"),
+ fabs (geo.lon),
+ geo.lon >= 0.0 ? _("E") : _("W"));
+ return buf;
+ }
+
+ return "";
+}
+
+static int
+get_percent (ECalModelComponent *comp_data)
+{
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
+ if (prop)
+ return icalproperty_get_percentcomplete (prop);
+
+ return 0;
+}
+
+static char *
+get_priority (ECalModelComponent *comp_data)
+{
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PRIORITY_PROPERTY);
+ if (prop)
+ return cal_util_priority_to_string (icalproperty_get_priority (prop));
+
+ return "";
+}
+
+static char *
+get_status (ECalModelComponent *comp_data)
+{
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_STATUS_PROPERTY);
+ if (prop) {
+ switch (icalproperty_get_status (prop)) {
+ case ICAL_STATUS_NONE:
+ return "";
+ case ICAL_STATUS_NEEDSACTION:
+ return _("Not Started");
+ case ICAL_STATUS_INPROCESS:
+ return _("In Progress");
+ case ICAL_STATUS_COMPLETED:
+ return _("Completed");
+ case ICAL_STATUS_CANCELLED:
+ return _("Cancelled");
+ default:
+ g_assert_not_reached ();
+ return NULL;
+ }
+ }
+
+ return "";
+}
+
+static char *
+get_url (ECalModelComponent *comp_data)
+{
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_URL_PROPERTY);
+ if (prop)
+ return (char *) icalproperty_get_url (prop);
+
+ return "";
+}
+
+static gboolean
+is_complete (ECalModelComponent *comp_data)
+{
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_COMPLETED_PROPERTY);
+
+ return prop ? TRUE : FALSE;
+}
+
+typedef enum {
+ E_CAL_MODEL_TASKS_DUE_NEVER,
+ E_CAL_MODEL_TASKS_DUE_FUTURE,
+ E_CAL_MODEL_TASKS_DUE_TODAY,
+ E_CAL_MODEL_TASKS_DUE_OVERDUE,
+ E_CAL_MODEL_TASKS_DUE_COMPLETE
+} ECalModelTasksDueStatus;
+
+
+static ECalModelTasksDueStatus
+get_due_status (ECalModelTasks *model, ECalModelComponent *comp_data)
+{
+ icalproperty *prop;
+
+ /* First, do we have a due date? */
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_DUE_PROPERTY);
+ if (!prop)
+ return E_CAL_MODEL_TASKS_DUE_NEVER;
+ else {
+ struct icaltimetype now_tt, due_tt;
+ CalClientGetStatus status;
+ icaltimezone *zone;
+
+ /* Second, is it already completed? */
+ if (is_complete (comp_data))
+ return E_CAL_MODEL_TASKS_DUE_COMPLETE;
+
+ /* Third, are we overdue as of right now? */
+ due_tt = icalproperty_get_due (prop);
+ if (due_tt.is_date) {
+ int cmp;
+
+ now_tt = icaltime_current_time_with_zone (e_cal_model_get_timezone (E_CAL_MODEL (model)));
+ cmp = icaltime_compare_date_only (due_tt, now_tt);
+
+ if (cmp < 0)
+ return E_CAL_MODEL_TASKS_DUE_OVERDUE;
+ else if (cmp == 0)
+ return E_CAL_MODEL_TASKS_DUE_TODAY;
+ else
+ return E_CAL_MODEL_TASKS_DUE_FUTURE;
+ } else {
+ /* Get the current time in the same timezone as the DUE date.*/
+ status = cal_client_get_timezone (comp_data->client,
+ icaltimezone_get_tzid (icaltimezone_get_builtin_timezone (due_tt.zone)),
+ &zone);
+ if (status != CAL_CLIENT_GET_SUCCESS)
+ return E_CAL_MODEL_TASKS_DUE_FUTURE;
+
+ now_tt = icaltime_current_time_with_zone (zone);
+
+ if (icaltime_compare (due_tt, now_tt) <= 0)
+ return E_CAL_MODEL_TASKS_DUE_OVERDUE;
+ else
+ if (icaltime_compare_date_only (due_tt, now_tt) == 0)
+ return E_CAL_MODEL_TASKS_DUE_TODAY;
+ else
+ return E_CAL_MODEL_TASKS_DUE_FUTURE;
+ }
+ }
+
+ return E_CAL_MODEL_TASKS_DUE_NEVER;
+}
+
+static gboolean
+is_overdue (ECalModelTasks *model, ECalModelComponent *comp_data)
+{
+ switch (get_due_status (model, comp_data)) {
+ case E_CAL_MODEL_TASKS_DUE_NEVER:
+ case E_CAL_MODEL_TASKS_DUE_FUTURE:
+ case E_CAL_MODEL_TASKS_DUE_COMPLETE:
+ return FALSE;
+ case E_CAL_MODEL_TASKS_DUE_TODAY:
+ case E_CAL_MODEL_TASKS_DUE_OVERDUE:
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void *
+ecmt_value_at (ETableModel *etm, int col, int row)
+{
+ ECalModelTasksPrivate *priv;
+ ECalModelComponent *comp_data;
+ ECalModelTasks *model = (ECalModelTasks *) etm;
+
+ g_return_val_if_fail (E_IS_CAL_MODEL_TASKS (model), NULL);
+
+ priv = model->priv;
+
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST, NULL);
+ g_return_val_if_fail (row >= 0 && row < e_table_model_row_count (etm), NULL);
+
+ if (col < E_CAL_MODEL_FIELD_LAST)
+ return E_TABLE_MODEL_CLASS (parent_class)->value_at (etm, col, row);
+
+ comp_data = e_cal_model_get_component_at (E_CAL_MODEL (model), row);
+ if (!comp_data)
+ return "";
+
+ switch (col) {
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
+ return get_completed (comp_data);
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
+ return GINT_TO_POINTER (is_complete (comp_data));
+ case E_CAL_MODEL_TASKS_FIELD_DUE :
+ /* FIXME */
+ break;
+ case E_CAL_MODEL_TASKS_FIELD_GEO :
+ return get_geo (comp_data);
+ case E_CAL_MODEL_TASKS_FIELD_OVERDUE :
+ return GINT_TO_POINTER (is_overdue (model, comp_data));
+ case E_CAL_MODEL_TASKS_FIELD_PERCENT :
+ return GINT_TO_POINTER (get_percent (comp_data));
+ case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
+ return get_priority (comp_data);
+ case E_CAL_MODEL_TASKS_FIELD_STATUS :
+ return get_status (comp_data);
+ case E_CAL_MODEL_TASKS_FIELD_URL :
+ return get_url (comp_data);
+ }
+
+ return "";
+}
+
+static void
+set_completed (ECalModelTasks *model, ECalModelComponent *comp_data, const void *value)
+{
+ ECellDateEditValue *dv = (ECellDateEditValue *) value;
+
+ if (!dv)
+ ensure_task_not_complete (comp_data);
+ else {
+ time_t t;
+
+ if (dv->tt.is_date) {
+ /* if it's a date, it will be floating,
+ but completed needs a date time value */
+ dv->tt.is_date = FALSE;
+ t = icaltime_as_timet_with_zone (dv->tt, e_cal_model_get_timezone (E_CAL_MODEL (model)));
+ } else {
+ /* we assume that COMPLETED is entered in the current timezone,
+ even though it gets stored in UTC */
+ t = icaltime_as_timet_with_zone (dv->tt, dv->zone);
+ }
+
+ ensure_task_complete (comp_data, t);
+ }
+}
+
+static void
+set_complete (ECalModelComponent *comp_data, const void *value)
+{
+ gint state = GPOINTER_TO_INT (value);
+
+ if (state)
+ ensure_task_complete (comp_data, -1);
+ else
+ ensure_task_not_complete (comp_data);
+}
+
+/* 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 (void)
+{
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+ _("The geographical position must be entered "
+ "in the format: \n\n45.436845,125.862501"));
+ gtk_widget_show (dialog);
+}
+
+static void
+set_geo (ECalModelComponent *comp_data, const char *value)
+{
+ double latitude, longitude;
+ int matched;
+ struct icalgeotype geo;
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_GEO_PROPERTY);
+
+ if (string_is_empty (value)) {
+ if (prop) {
+ icalcomponent_remove_property (comp_data->icalcomp, prop);
+ icalproperty_free (prop);
+ }
+ } else {
+ matched = sscanf (value, "%lg , %lg", &latitude, &longitude);
+ if (matched != 2)
+ show_geo_warning ();
+
+ geo.lat = latitude;
+ geo.lon = longitude;
+ if (prop)
+ icalproperty_set_geo (prop, geo);
+ else {
+ prop = icalproperty_new_geo (geo);
+ icalcomponent_add_property (comp_data->icalcomp, prop);
+ }
+
+ }
+}
+
+static void
+set_status (ECalModelComponent *comp_data, const char *value)
+{
+ icalproperty_status status;
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_STATUS_PROPERTY);
+
+ /* an empty string is the same as 'None' */
+ if (!value[0] || !g_strcasecmp (value, _("None")))
+ status = ICAL_STATUS_NONE;
+ else if (!g_strcasecmp (value, _("Not Started")))
+ status = ICAL_STATUS_NEEDSACTION;
+ else if (!g_strcasecmp (value, _("In Progress")))
+ status = ICAL_STATUS_INPROCESS;
+ else if (!g_strcasecmp (value, _("Completed")))
+ status = ICAL_STATUS_COMPLETED;
+ else if (!g_strcasecmp (value, _("Cancelled")))
+ status = ICAL_STATUS_CANCELLED;
+ else {
+ g_warning ("Invalid status: %s\n", value);
+ return;
+ }
+
+ if (prop)
+ icalproperty_set_status (prop, status);
+ else {
+ prop = icalproperty_new_status (status);
+ icalcomponent_add_property (comp_data->icalcomp, prop);
+ }
+
+/* if (status == ICAL_STATUS_NEEDSACTION) { */
+/* percent = 0; */
+/* cal_component_set_percent (comp, &percent); */
+/* cal_component_set_completed (comp, NULL); */
+/* } else if (status == ICAL_STATUS_INPROCESS) { */
+/* ensure_task_not_complete (comp); */
+/* percent = 50; */
+/* cal_component_set_percent (comp, &percent); */
+/* } else if (status == ICAL_STATUS_COMPLETED) { */
+/* ensure_task_complete (comp, -1); */
+/* } */
+}
+
+static void
+set_percent (ECalModelComponent *comp_data, const void *value)
+{
+ icalproperty *prop;
+ gint percent = GPOINTER_TO_INT (value);
+
+ g_return_if_fail (percent >= -1);
+ g_return_if_fail (percent <= 100);
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
+
+ /* A value of -1 means it isn't set */
+ if (percent == -1) {
+ if (prop) {
+ icalcomponent_remove_property (comp_data->icalcomp, prop);
+ icalproperty_free (prop);
+ }
+ ensure_task_not_complete (comp_data);
+ } else {
+ if (prop)
+ icalproperty_set_percentcomplete (prop, percent);
+ else {
+ prop = icalproperty_new_percentcomplete (percent);
+ icalcomponent_add_property (comp_data->icalcomp, prop);
+ }
+
+ if (percent == 100)
+ ensure_task_complete (comp_data, -1);
+ else {
+ ensure_task_not_complete (comp_data);
+ if (percent > 0)
+ set_status (comp_data, _("In Progress"));
+ }
+ }
+
+}
+
+static void
+set_priority (ECalModelComponent *comp_data, const char *value)
+{
+ icalproperty *prop;
+ int priority;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PRIORITY_PROPERTY);
+
+ priority = cal_util_priority_from_string (value);
+ if (priority == -1) {
+ g_warning ("Invalid priority");
+ priority = 0;
+ }
+
+ if (prop)
+ icalproperty_set_priority (prop, priority);
+ else {
+ prop = icalproperty_new_priority (priority);
+ icalcomponent_add_property (comp_data->icalcomp, prop);
+ }
+}
+
+static void
+set_url (ECalModelComponent *comp_data, const char *value)
+{
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_URL_PROPERTY);
+
+ if (string_is_empty (value)) {
+ if (prop) {
+ icalcomponent_remove_property (comp_data->icalcomp, prop);
+ icalproperty_free (prop);
+ }
+ } else {
+ if (prop)
+ icalproperty_set_url (prop, value);
+ else {
+ prop = icalproperty_new_url (value);
+ icalcomponent_add_property (comp_data->icalcomp, prop);
+ }
+ }
+}
+
+static void
+ecmt_set_value_at (ETableModel *etm, int col, int row, const void *value)
+{
+ ECalModelTasksPrivate *priv;
+ ECalModelComponent *comp_data;
+ ECalModelTasks *model = (ECalModelTasks *) etm;
+
+ g_return_if_fail (E_IS_CAL_MODEL_TASKS (model));
+
+ priv = model->priv;
+
+ g_return_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST);
+ g_return_if_fail (row >= 0 && row < e_table_model_row_count (etm));
+
+ if (col < E_CAL_MODEL_FIELD_LAST) {
+ E_TABLE_MODEL_CLASS (parent_class)->set_value_at (etm, col, row, value);
+ return;
+ }
+
+ comp_data = e_cal_model_get_component_at (E_CAL_MODEL (model), row);
+ if (!comp_data)
+ return;
+
+ switch (col) {
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
+ set_completed (model, comp_data, value);
+ break;
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
+ set_complete (comp_data, value);
+ break;
+ case E_CAL_MODEL_TASKS_FIELD_DUE :
+ /* FIXME */
+ break;
+ case E_CAL_MODEL_TASKS_FIELD_GEO :
+ set_geo (comp_data, value);
+ break;
+ case E_CAL_MODEL_TASKS_FIELD_PERCENT :
+ set_percent (comp_data, value);
+ break;
+ case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
+ set_priority (comp_data, value);
+ break;
+ case E_CAL_MODEL_TASKS_FIELD_URL :
+ set_url (comp_data, value);
+ break;
+ }
+
+ if (cal_client_update_objects (comp_data->client, comp_data->icalcomp) != CAL_CLIENT_RESULT_SUCCESS)
+ g_message ("ecmt_set_value_at(): Could not update the object!");
+}
+
+static gboolean
+ecmt_is_cell_editable (ETableModel *etm, int col, int row)
+{
+ ECalModelTasksPrivate *priv;
+ ECalModelTasks *model = (ECalModelTasks *) etm;
+
+ g_return_val_if_fail (E_IS_CAL_MODEL_TASKS (model), FALSE);
+
+ priv = model->priv;
+
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST, FALSE);
+
+ /* FIXME: We can't check this as 'click-to-add' passes row 0. */
+ /* g_return_val_if_fail (row >= 0 && row < e_table_model_get_row_count (etm), FALSE); */
+
+ if (col < E_CAL_MODEL_FIELD_LAST)
+ return E_TABLE_MODEL_CLASS (parent_class)->is_cell_editable (etm, col, row);
+
+ switch (col) {
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
+ case E_CAL_MODEL_TASKS_FIELD_DUE :
+ case E_CAL_MODEL_TASKS_FIELD_GEO :
+ case E_CAL_MODEL_TASKS_FIELD_PERCENT :
+ case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
+ case E_CAL_MODEL_TASKS_FIELD_URL :
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+ecmt_append_row (ETableModel *etm, ETableModel *source, gint row)
+{
+ ECalModelTasksPrivate *priv;
+ ECalModelTasks *model = (ECalModelTasks *) etm;
+
+ g_return_if_fail (E_IS_CAL_MODEL_TASKS (model));
+
+ priv = model->priv;
+
+ /* FIXME: how to chain to ecm_append_row? */
+}
+
+static void *
+ecmt_duplicate_value (ETableModel *etm, int col, const void *value)
+{
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST, NULL);
+
+ if (col < E_CAL_MODEL_FIELD_LAST)
+ return E_TABLE_MODEL_CLASS (parent_class)->duplicate_value (etm, col, value);
+
+ switch (col) {
+ case E_CAL_MODEL_TASKS_FIELD_GEO :
+ case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
+ case E_CAL_MODEL_TASKS_FIELD_STATUS :
+ case E_CAL_MODEL_TASKS_FIELD_URL :
+ return g_strdup (value);
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
+ case E_CAL_MODEL_TASKS_FIELD_DUE :
+ /* FIXME */
+ break;
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
+ case E_CAL_MODEL_TASKS_FIELD_PERCENT :
+ case E_CAL_MODEL_TASKS_FIELD_OVERDUE :
+ return (void *) value;
+ }
+
+ return NULL;
+}
+
+static void
+ecmt_free_value (ETableModel *etm, int col, void *value)
+{
+ g_return_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST);
+
+ if (col < E_CAL_MODEL_FIELD_LAST) {
+ E_TABLE_MODEL_CLASS (parent_class)->free_value (etm, col, value);
+ return;
+ }
+
+ switch (col) {
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
+ case E_CAL_MODEL_TASKS_FIELD_DUE :
+ case E_CAL_MODEL_TASKS_FIELD_GEO :
+ case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
+ case E_CAL_MODEL_TASKS_FIELD_STATUS :
+ case E_CAL_MODEL_TASKS_FIELD_URL :
+ if (value)
+ g_free (value);
+ break;
+ case E_CAL_MODEL_TASKS_FIELD_PERCENT :
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
+ case E_CAL_MODEL_TASKS_FIELD_OVERDUE :
+ break;
+ }
+}
+
+static void *
+ecmt_initialize_value (ETableModel *etm, int col)
+{
+ ECalModelTasks *model = (ECalModelTasks *) etm;
+
+ g_return_val_if_fail (E_IS_CAL_MODEL_TASKS (model), NULL);
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST, NULL);
+
+ if (col < E_CAL_MODEL_FIELD_LAST)
+ return E_TABLE_MODEL_CLASS (parent_class)->initialize_value (etm, col);
+
+ switch (col) {
+ case E_CAL_MODEL_TASKS_FIELD_GEO :
+ case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
+ case E_CAL_MODEL_TASKS_FIELD_STATUS :
+ case E_CAL_MODEL_TASKS_FIELD_URL :
+ return g_strdup ("");
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
+ case E_CAL_MODEL_TASKS_FIELD_DUE :
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
+ case E_CAL_MODEL_TASKS_FIELD_OVERDUE :
+ return NULL;
+ case E_CAL_MODEL_TASKS_FIELD_PERCENT :
+ return GINT_TO_POINTER (-1);
+ }
+
+ return NULL;
+}
+
+static gboolean
+ecmt_value_is_empty (ETableModel *etm, int col, const void *value)
+{
+ ECalModelTasksPrivate *priv;
+ ECalModelTasks *model = (ECalModelTasks *) etm;
+
+ g_return_val_if_fail (E_IS_CAL_MODEL_TASKS (model), TRUE);
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST, TRUE);
+
+ priv = model->priv;
+
+ if (col < E_CAL_MODEL_FIELD_LAST)
+ return E_TABLE_MODEL_CLASS (parent_class)->value_is_empty (etm, col, value);
+
+ switch (col) {
+ case E_CAL_MODEL_TASKS_FIELD_GEO :
+ case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
+ case E_CAL_MODEL_TASKS_FIELD_STATUS :
+ case E_CAL_MODEL_TASKS_FIELD_URL :
+ return string_is_empty (value);
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
+ case E_CAL_MODEL_TASKS_FIELD_DUE :
+ return value ? FALSE : TRUE;
+ case E_CAL_MODEL_TASKS_FIELD_PERCENT :
+ return (GPOINTER_TO_INT (value) < 0) ? TRUE : FALSE;
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
+ case E_CAL_MODEL_TASKS_FIELD_OVERDUE :
+ return TRUE;
+ }
+
+ return TRUE;
+}
+
+static char *
+ecmt_value_to_string (ETableModel *etm, int col, const void *value)
+{
+ ECalModelTasks *model = (ECalModelTasks *) etm;
+
+ g_return_val_if_fail (E_IS_CAL_MODEL_TASKS (model), NULL);
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST, NULL);
+
+ if (col < E_CAL_MODEL_FIELD_LAST)
+ return E_TABLE_MODEL_CLASS (parent_class)->value_to_string (etm, col, value);
+
+ switch (col) {
+ case E_CAL_MODEL_TASKS_FIELD_GEO :
+ case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
+ case E_CAL_MODEL_TASKS_FIELD_STATUS :
+ case E_CAL_MODEL_TASKS_FIELD_URL :
+ return g_strdup (value);
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
+ case E_CAL_MODEL_TASKS_FIELD_DUE :
+ return e_cal_model_date_value_to_string (E_CAL_MODEL (model), value);
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
+ case E_CAL_MODEL_TASKS_FIELD_OVERDUE :
+ return value ? _("Yes") : _("No");
+ case E_CAL_MODEL_TASKS_FIELD_PERCENT :
+ if (GPOINTER_TO_INT (value) < 0)
+ return g_strdup ("N/A");
+ else
+ return g_strdup_printf ("%i%%", GPOINTER_TO_INT (value));
+ }
+
+ return NULL;
+}
+
+static const char *
+ecmt_get_color_for_component (ECalModel *model, ECalModelComponent *comp_data)
+{
+ g_return_val_if_fail (E_IS_CAL_MODEL_TASKS (model), NULL);
+ g_return_val_if_fail (comp_data != NULL, NULL);
+
+ switch (get_due_status ((ECalModelTasks *) model, comp_data)) {
+ case E_CAL_MODEL_TASKS_DUE_NEVER:
+ case E_CAL_MODEL_TASKS_DUE_FUTURE:
+ case E_CAL_MODEL_TASKS_DUE_COMPLETE:
+ return NULL;
+ case E_CAL_MODEL_TASKS_DUE_TODAY:
+ return calendar_config_get_tasks_due_today_color ();
+ case E_CAL_MODEL_TASKS_DUE_OVERDUE:
+ return calendar_config_get_tasks_overdue_color ();
+ }
+
+ return NULL;
+}
+
+/**
+ * e_cal_model_tasks_new
+ */
+ECalModelTasks *
+e_cal_model_tasks_new (void)
+{
+ return g_object_new (E_TYPE_CAL_MODEL_TASKS, NULL);
+}