No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | e-cal-model-tasks.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None | |
clang-analyzer | no-output-found | e-cal-model-tasks.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /*
2 * Evolution calendar - Data model for ETable
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with the program; if not, see <http://www.gnu.org/licenses/>
16 *
17 *
18 * Authors:
19 * Rodrigo Moya <rodrigo@ximian.com>
20 *
21 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
22 *
23 */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <math.h>
30 #include <string.h>
31 #include <gtk/gtk.h>
32 #include <glib/gi18n.h>
33
34 #include "calendar-config.h"
35 #include "e-cal-model-tasks.h"
36 #include "e-cell-date-edit-text.h"
37 #include "misc.h"
38
39 #define E_CAL_MODEL_TASKS_GET_PRIVATE(obj) \
40 (G_TYPE_INSTANCE_GET_PRIVATE \
41 ((obj), E_TYPE_CAL_MODEL_TASKS, ECalModelTasksPrivate))
42
43 struct _ECalModelTasksPrivate {
44 gboolean highlight_due_today;
45 gchar *color_due_today;
46 gboolean highlight_overdue;
47 gchar *color_overdue;
48 };
49
50 static gint ecmt_column_count (ETableModel *etm);
51 static gpointer ecmt_value_at (ETableModel *etm, gint col, gint row);
52 static void ecmt_set_value_at (ETableModel *etm, gint col, gint row, gconstpointer value);
53 static gboolean ecmt_is_cell_editable (ETableModel *etm, gint col, gint row);
54 static gpointer ecmt_duplicate_value (ETableModel *etm, gint col, gconstpointer value);
55 static void ecmt_free_value (ETableModel *etm, gint col, gpointer value);
56 static gpointer ecmt_initialize_value (ETableModel *etm, gint col);
57 static gboolean ecmt_value_is_empty (ETableModel *etm, gint col, gconstpointer value);
58 static gchar *ecmt_value_to_string (ETableModel *etm, gint col, gconstpointer value);
59
60 static const gchar *ecmt_get_color_for_component (ECalModel *model, ECalModelComponent *comp_data);
61 static void ecmt_fill_component_from_model (ECalModel *model, ECalModelComponent *comp_data,
62 ETableModel *source_model, gint row);
63 static void commit_component_changes (ECalModelComponent *comp_data);
64
65 G_DEFINE_TYPE (ECalModelTasks, e_cal_model_tasks, E_TYPE_CAL_MODEL)
66
67 enum {
68 PROP_0,
69 PROP_HIGHLIGHT_DUE_TODAY,
70 PROP_COLOR_DUE_TODAY,
71 PROP_HIGHLIGHT_OVERDUE,
72 PROP_COLOR_OVERDUE
73 };
74
75 static void
76 cal_model_tasks_set_property (GObject *object,
77 guint property_id,
78 const GValue *value,
79 GParamSpec *pspec)
80 {
81 switch (property_id) {
82 case PROP_HIGHLIGHT_DUE_TODAY:
83 e_cal_model_tasks_set_highlight_due_today (
84 E_CAL_MODEL_TASKS (object),
85 g_value_get_boolean (value));
86 return;
87
88 case PROP_COLOR_DUE_TODAY:
89 e_cal_model_tasks_set_color_due_today (
90 E_CAL_MODEL_TASKS (object),
91 g_value_get_string (value));
92 return;
93
94 case PROP_HIGHLIGHT_OVERDUE:
95 e_cal_model_tasks_set_highlight_overdue (
96 E_CAL_MODEL_TASKS (object),
97 g_value_get_boolean (value));
98 return;
99
100 case PROP_COLOR_OVERDUE:
101 e_cal_model_tasks_set_color_overdue (
102 E_CAL_MODEL_TASKS (object),
103 g_value_get_string (value));
104 return;
105 }
106
107 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
108 }
109
110 static void
111 cal_model_tasks_get_property (GObject *object,
112 guint property_id,
113 GValue *value,
114 GParamSpec *pspec)
115 {
116 switch (property_id) {
117 case PROP_HIGHLIGHT_DUE_TODAY:
118 g_value_set_boolean (
119 value,
120 e_cal_model_tasks_get_highlight_due_today (
121 E_CAL_MODEL_TASKS (object)));
122 return;
123
124 case PROP_COLOR_DUE_TODAY:
125 g_value_set_string (
126 value,
127 e_cal_model_tasks_get_color_due_today (
128 E_CAL_MODEL_TASKS (object)));
129 return;
130
131 case PROP_HIGHLIGHT_OVERDUE:
132 g_value_set_boolean (
133 value,
134 e_cal_model_tasks_get_highlight_overdue (
135 E_CAL_MODEL_TASKS (object)));
136 return;
137
138 case PROP_COLOR_OVERDUE:
139 g_value_set_string (
140 value,
141 e_cal_model_tasks_get_color_overdue (
142 E_CAL_MODEL_TASKS (object)));
143 return;
144 }
145
146 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
147 }
148
149 static void
150 cal_model_tasks_finalize (GObject *object)
151 {
152 ECalModelTasksPrivate *priv;
153
154 priv = E_CAL_MODEL_TASKS_GET_PRIVATE (object);
155
156 g_free (priv->color_due_today);
157 g_free (priv->color_overdue);
158
159 /* Chain up to parent's finalize() method. */
160 G_OBJECT_CLASS (e_cal_model_tasks_parent_class)->finalize (object);
161 }
162
163 static void
164 e_cal_model_tasks_class_init (ECalModelTasksClass *class)
165 {
166 GObjectClass *object_class;
167 ETableModelClass *table_model_class;
168 ECalModelClass *cal_model_class;
169
170 g_type_class_add_private (class, sizeof (ECalModelTasksPrivate));
171
172 object_class = G_OBJECT_CLASS (class);
173 object_class->set_property = cal_model_tasks_set_property;
174 object_class->get_property = cal_model_tasks_get_property;
175 object_class->finalize = cal_model_tasks_finalize;
176
177 table_model_class = E_TABLE_MODEL_CLASS (class);
178 table_model_class->column_count = ecmt_column_count;
179 table_model_class->value_at = ecmt_value_at;
180 table_model_class->set_value_at = ecmt_set_value_at;
181 table_model_class->is_cell_editable = ecmt_is_cell_editable;
182 table_model_class->duplicate_value = ecmt_duplicate_value;
183 table_model_class->free_value = ecmt_free_value;
184 table_model_class->initialize_value = ecmt_initialize_value;
185 table_model_class->value_is_empty = ecmt_value_is_empty;
186 table_model_class->value_to_string = ecmt_value_to_string;
187
188 cal_model_class = E_CAL_MODEL_CLASS (class);
189 cal_model_class->get_color_for_component = ecmt_get_color_for_component;
190 cal_model_class->fill_component_from_model = ecmt_fill_component_from_model;
191
192 g_object_class_install_property (
193 object_class,
194 PROP_HIGHLIGHT_DUE_TODAY,
195 g_param_spec_boolean (
196 "highlight-due-today",
197 "Highlight Due Today",
198 NULL,
199 TRUE,
200 G_PARAM_READWRITE));
201
202 g_object_class_install_property (
203 object_class,
204 PROP_COLOR_DUE_TODAY,
205 g_param_spec_string (
206 "color-due-today",
207 "Color Due Today",
208 NULL,
209 "#1e90ff",
210 G_PARAM_READWRITE));
211
212 g_object_class_install_property (
213 object_class,
214 PROP_HIGHLIGHT_OVERDUE,
215 g_param_spec_boolean (
216 "highlight-overdue",
217 "Highlight Overdue",
218 NULL,
219 TRUE,
220 G_PARAM_READWRITE));
221
222 g_object_class_install_property (
223 object_class,
224 PROP_COLOR_OVERDUE,
225 g_param_spec_string (
226 "color-overdue",
227 "Color Overdue",
228 NULL,
229 "#ff0000",
230 G_PARAM_READWRITE));
231 }
232
233 static void
234 e_cal_model_tasks_init (ECalModelTasks *model)
235 {
236 model->priv = E_CAL_MODEL_TASKS_GET_PRIVATE (model);
237
238 model->priv->highlight_due_today = TRUE;
239 model->priv->highlight_overdue = TRUE;
240
241 e_cal_model_set_component_kind (
242 E_CAL_MODEL (model), ICAL_VTODO_COMPONENT);
243 }
244
245 /* ETableModel methods */
246 static gint
247 ecmt_column_count (ETableModel *etm)
248 {
249 return E_CAL_MODEL_TASKS_FIELD_LAST;
250 }
251
252 /* This makes sure a task is marked as complete.
253 * It makes sure the "Date Completed" property is set. If the completed_date
254 * is not -1, then that is used, otherwise if the "Date Completed" property
255 * is not already set it is set to the current time.
256 * It makes sure the percent is set to 100, and that the status is "Completed".
257 * Note that this doesn't update the component on the server. */
258 static void
259 ensure_task_complete (ECalModelComponent *comp_data,
260 time_t completed_date)
261 {
262 icalproperty *prop;
263 gboolean set_completed = TRUE;
264
265 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_COMPLETED_PROPERTY);
266
267 /* Date Completed. */
268 if (completed_date == -1) {
269 if (prop)
270 set_completed = FALSE;
271 else
272 completed_date = time (NULL);
273 }
274
275 if (set_completed) {
276 icaltimezone *utc_zone;
277 struct icaltimetype new_completed;
278
279 /* COMPLETED is stored in UTC. */
280 utc_zone = icaltimezone_get_utc_timezone ();
281 new_completed = icaltime_from_timet_with_zone (
282 completed_date,
283 FALSE,
284 utc_zone);
285 if (prop)
286 icalproperty_set_completed (prop, new_completed);
287 else {
288 prop = icalproperty_new_completed (new_completed);
289 icalcomponent_add_property (comp_data->icalcomp, prop);
290 }
291 }
292
293 /* Percent. */
294 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
295 if (!prop)
296 icalcomponent_add_property (comp_data->icalcomp, icalproperty_new_percentcomplete (100));
297 else
298 icalproperty_set_percentcomplete (prop, 100);
299
300 /* Status. */
301 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_STATUS_PROPERTY);
302 if (prop)
303 icalproperty_set_status (prop, ICAL_STATUS_COMPLETED);
304 else
305 icalcomponent_add_property (comp_data->icalcomp, icalproperty_new_status (ICAL_STATUS_COMPLETED));
306 }
307
308 static void
309 ensure_task_partially_complete (ECalModelComponent *comp_data)
310 {
311 icalproperty *prop;
312
313 /* Date Completed. */
314 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_COMPLETED_PROPERTY);
315 if (prop) {
316 icalcomponent_remove_property (comp_data->icalcomp, prop);
317 icalproperty_free (prop);
318 }
319
320 /* Percent. */
321 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
322 if (!prop)
323 icalcomponent_add_property (comp_data->icalcomp, icalproperty_new_percentcomplete (50));
324 else if (icalproperty_get_percentcomplete (prop) == 0 || icalproperty_get_percentcomplete (prop) == 100)
325 icalproperty_set_percentcomplete (prop, 50);
326
327 /* Status. */
328 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_STATUS_PROPERTY);
329 if (prop)
330 icalproperty_set_status (prop, ICAL_STATUS_INPROCESS);
331 else
332 icalcomponent_add_property (comp_data->icalcomp, icalproperty_new_status (ICAL_STATUS_INPROCESS));
333 }
334
335 /* This makes sure a task is marked as incomplete. It clears the
336 * "Date Completed" property. If the percent is set to 100 it removes it,
337 * and if the status is "Completed" it sets it to "Needs Action".
338 * Note that this doesn't update the component on the client. */
339 static void
340 ensure_task_not_complete (ECalModelComponent *comp_data)
341 {
342 icalproperty *prop;
343
344 /* Date Completed. */
345 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_COMPLETED_PROPERTY);
346 if (prop) {
347 icalcomponent_remove_property (comp_data->icalcomp, prop);
348 icalproperty_free (prop);
349 }
350
351 /* Percent. */
352 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
353 if (prop) {
354 icalcomponent_remove_property (comp_data->icalcomp, prop);
355 icalproperty_free (prop);
356 }
357
358 /* Status. */
359 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_STATUS_PROPERTY);
360 if (prop)
361 icalproperty_set_status (prop, ICAL_STATUS_NEEDSACTION);
362 }
363
364 static ECellDateEditValue *
365 get_completed (ECalModelComponent *comp_data)
366 {
367 struct icaltimetype tt_completed;
368
369 if (!comp_data->completed) {
370 icaltimezone *zone;
371 icalproperty *prop;
372
373 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_COMPLETED_PROPERTY);
374 if (!prop)
375 return NULL;
376
377 tt_completed = icalproperty_get_completed (prop);
378 if (!icaltime_is_valid_time (tt_completed) || icaltime_is_null_time (tt_completed))
379 return NULL;
380
381 comp_data->completed = g_new0 (ECellDateEditValue, 1);
382 comp_data->completed->tt = tt_completed;
383
384 if (icaltime_get_tzid (tt_completed)
385 && e_cal_client_get_timezone_sync (comp_data->client, icaltime_get_tzid (tt_completed), &zone, NULL, NULL))
386 comp_data->completed->zone = zone;
387 else
388 comp_data->completed->zone = NULL;
389 }
390
391 return comp_data->completed;
392 }
393
394 static ECellDateEditValue *
395 get_due (ECalModelComponent *comp_data)
396 {
397 struct icaltimetype tt_due;
398
399 if (!comp_data->due) {
400 icaltimezone *zone;
401 icalproperty *prop;
402
403 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_DUE_PROPERTY);
404 if (!prop)
405 return NULL;
406
407 tt_due = icalproperty_get_due (prop);
408 if (!icaltime_is_valid_time (tt_due) || icaltime_is_null_time (tt_due))
409 return NULL;
410
411 comp_data->due = g_new0 (ECellDateEditValue, 1);
412 comp_data->due->tt = tt_due;
413
414 if (icaltime_get_tzid (tt_due)
415 && e_cal_client_get_timezone_sync (comp_data->client, icaltime_get_tzid (tt_due), &zone, NULL, NULL))
416 comp_data->due->zone = zone;
417 else
418 comp_data->due->zone = NULL;
419 }
420
421 return comp_data->due;
422 }
423
424 static gpointer
425 get_geo (ECalModelComponent *comp_data)
426 {
427 icalproperty *prop;
428 struct icalgeotype geo;
429 static gchar buf[32];
430
431 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_GEO_PROPERTY);
432 if (prop) {
433 geo = icalproperty_get_geo (prop);
434 g_snprintf (
435 buf, sizeof (buf), "%g %s, %g %s",
436 fabs (geo.lat),
437 geo.lat >= 0.0 ? "N" : "S",
438 fabs (geo.lon),
439 geo.lon >= 0.0 ? "E" : "W");
440 return buf;
441 }
442
443 return (gpointer) "";
444 }
445
446 static gint
447 get_percent (ECalModelComponent *comp_data)
448 {
449 icalproperty *prop;
450
451 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
452 if (prop)
453 return icalproperty_get_percentcomplete (prop);
454
455 return 0;
456 }
457
458 static gpointer
459 get_priority (ECalModelComponent *comp_data)
460 {
461 icalproperty *prop;
462
463 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PRIORITY_PROPERTY);
464 if (prop)
465 return (gpointer) e_cal_util_priority_to_string (icalproperty_get_priority (prop));
466
467 return (gpointer) "";
468 }
469
470 static gboolean
471 is_status_canceled (ECalModelComponent *comp_data)
472 {
473 icalproperty *prop;
474
475 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_STATUS_PROPERTY);
476
477 return prop && icalproperty_get_status (prop) == ICAL_STATUS_CANCELLED;
478 }
479
480 static gpointer
481 get_status (ECalModelComponent *comp_data)
482 {
483 icalproperty *prop;
484
485 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_STATUS_PROPERTY);
486 if (prop) {
487 switch (icalproperty_get_status (prop)) {
488 case ICAL_STATUS_NONE:
489 return (gpointer) "";
490 case ICAL_STATUS_NEEDSACTION:
491 return (gpointer) _("Not Started");
492 case ICAL_STATUS_INPROCESS:
493 return (gpointer) _("In Progress");
494 case ICAL_STATUS_COMPLETED:
495 return (gpointer) _("Completed");
496 case ICAL_STATUS_CANCELLED:
497 return (gpointer) _("Canceled");
498 default:
499 return (gpointer) "";
500 }
501 }
502
503 return (gpointer) "";
504 }
505
506 static gpointer
507 get_url (ECalModelComponent *comp_data)
508 {
509 icalproperty *prop;
510
511 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_URL_PROPERTY);
512 if (prop)
513 return (gpointer) icalproperty_get_url (prop);
514
515 return (gpointer) "";
516 }
517
518 static gboolean
519 is_complete (ECalModelComponent *comp_data)
520 {
521 icalproperty *prop;
522
523 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_COMPLETED_PROPERTY);
524 if (prop)
525 return TRUE;
526
527 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
528 if (prop && icalproperty_get_percentcomplete (prop) == 100)
529 return TRUE;
530
531 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_STATUS_PROPERTY);
532 if (prop && icalproperty_get_status (prop) == ICAL_STATUS_COMPLETED)
533 return TRUE;
534
535 return FALSE;
536 }
537
538 typedef enum {
539 E_CAL_MODEL_TASKS_DUE_NEVER,
540 E_CAL_MODEL_TASKS_DUE_FUTURE,
541 E_CAL_MODEL_TASKS_DUE_TODAY,
542 E_CAL_MODEL_TASKS_DUE_OVERDUE,
543 E_CAL_MODEL_TASKS_DUE_COMPLETE
544 } ECalModelTasksDueStatus;
545
546 static ECalModelTasksDueStatus
547 get_due_status (ECalModelTasks *model,
548 ECalModelComponent *comp_data)
549 {
550 icalproperty *prop;
551
552 /* First, do we have a due date? */
553 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_DUE_PROPERTY);
554 if (!prop)
555 return E_CAL_MODEL_TASKS_DUE_NEVER;
556 else {
557 struct icaltimetype now_tt, due_tt;
558 icaltimezone *zone;
559
560 /* Second, is it already completed? */
561 if (is_complete (comp_data))
562 return E_CAL_MODEL_TASKS_DUE_COMPLETE;
563
564 /* Third, are we overdue as of right now? */
565 due_tt = icalproperty_get_due (prop);
566 if (due_tt.is_date) {
567 gint cmp;
568
569 now_tt = icaltime_current_time_with_zone (e_cal_model_get_timezone (E_CAL_MODEL (model)));
570 cmp = icaltime_compare_date_only (due_tt, now_tt);
571
572 if (cmp < 0)
573 return E_CAL_MODEL_TASKS_DUE_OVERDUE;
574 else if (cmp == 0)
575 return E_CAL_MODEL_TASKS_DUE_TODAY;
576 else
577 return E_CAL_MODEL_TASKS_DUE_FUTURE;
578 } else {
579 icalparameter *param;
580 const gchar *tzid;
581
582 if (!(param = icalproperty_get_first_parameter (prop, ICAL_TZID_PARAMETER)))
583 return E_CAL_MODEL_TASKS_DUE_FUTURE;
584
585 /* Get the current time in the same timezone as the DUE date.*/
586 tzid = icalparameter_get_tzid (param);
587 if (!e_cal_client_get_timezone_sync (comp_data->client, tzid, &zone, NULL, NULL))
588 return E_CAL_MODEL_TASKS_DUE_FUTURE;
589
590 now_tt = icaltime_current_time_with_zone (zone);
591
592 if (icaltime_compare (due_tt, now_tt) <= 0)
593 return E_CAL_MODEL_TASKS_DUE_OVERDUE;
594 else
595 if (icaltime_compare_date_only (due_tt, now_tt) == 0)
596 return E_CAL_MODEL_TASKS_DUE_TODAY;
597 else
598 return E_CAL_MODEL_TASKS_DUE_FUTURE;
599 }
600 }
601 }
602
603 static gboolean
604 is_overdue (ECalModelTasks *model,
605 ECalModelComponent *comp_data)
606 {
607 switch (get_due_status (model, comp_data)) {
608 case E_CAL_MODEL_TASKS_DUE_NEVER:
609 case E_CAL_MODEL_TASKS_DUE_FUTURE:
610 case E_CAL_MODEL_TASKS_DUE_COMPLETE:
611 return FALSE;
612 case E_CAL_MODEL_TASKS_DUE_TODAY:
613 case E_CAL_MODEL_TASKS_DUE_OVERDUE:
614 return TRUE;
615 }
616
617 return FALSE;
618 }
619
620 static gpointer
621 ecmt_value_at (ETableModel *etm,
622 gint col,
623 gint row)
624 {
625 ECalModelComponent *comp_data;
626 ECalModelTasks *model = (ECalModelTasks *) etm;
627
628 g_return_val_if_fail (E_IS_CAL_MODEL_TASKS (model), NULL);
629
630 g_return_val_if_fail (col >= 0 && (col < E_CAL_MODEL_TASKS_FIELD_LAST || col == E_CAL_MODEL_TASKS_FIELD_STRIKEOUT), NULL);
631 g_return_val_if_fail (row >= 0 && row < e_table_model_row_count (etm), NULL);
632
633 if (col < E_CAL_MODEL_FIELD_LAST)
634 return E_TABLE_MODEL_CLASS (e_cal_model_tasks_parent_class)->value_at (etm, col, row);
635
636 comp_data = e_cal_model_get_component_at (E_CAL_MODEL (model), row);
637 if (!comp_data)
638 return (gpointer) "";
639
640 switch (col) {
641 case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
642 return get_completed (comp_data);
643 case E_CAL_MODEL_TASKS_FIELD_STRIKEOUT :
644 return GINT_TO_POINTER (is_status_canceled (comp_data) || is_complete (comp_data));
645 case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
646 return GINT_TO_POINTER (is_complete (comp_data));
647 case E_CAL_MODEL_TASKS_FIELD_DUE :
648 return get_due (comp_data);
649 case E_CAL_MODEL_TASKS_FIELD_GEO :
650 return get_geo (comp_data);
651 case E_CAL_MODEL_TASKS_FIELD_OVERDUE :
652 return GINT_TO_POINTER (is_overdue (model, comp_data));
653 case E_CAL_MODEL_TASKS_FIELD_PERCENT :
654 return GINT_TO_POINTER (get_percent (comp_data));
655 case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
656 return get_priority (comp_data);
657 case E_CAL_MODEL_TASKS_FIELD_STATUS :
658 return get_status (comp_data);
659 case E_CAL_MODEL_TASKS_FIELD_URL :
660 return get_url (comp_data);
661 }
662
663 return (gpointer) "";
664 }
665
666 static void
667 set_completed (ECalModelTasks *model,
668 ECalModelComponent *comp_data,
669 gconstpointer value)
670 {
671 ECellDateEditValue *dv = (ECellDateEditValue *) value;
672
673 if (!dv)
674 ensure_task_not_complete (comp_data);
675 else {
676 time_t t;
677
678 if (dv->tt.is_date) {
679 /* if it's a date, it will be floating,
680 * but completed needs a date time value */
681 dv->tt.is_date = FALSE;
682 t = icaltime_as_timet_with_zone (dv->tt, e_cal_model_get_timezone (E_CAL_MODEL (model)));
683 } else {
684 /* we assume that COMPLETED is entered in the current timezone,
685 * even though it gets stored in UTC */
686 t = icaltime_as_timet_with_zone (dv->tt, dv->zone);
687 }
688
689 ensure_task_complete (comp_data, t);
690 }
691 }
692
693 static void
694 set_complete (ECalModelComponent *comp_data,
695 gconstpointer value)
696 {
697 gint state = GPOINTER_TO_INT (value);
698
699 if (state)
700 ensure_task_complete (comp_data, -1);
701 else
702 ensure_task_not_complete (comp_data);
703 }
704
705 static void
706 set_due (ECalModel *model,
707 ECalModelComponent *comp_data,
708 gconstpointer value)
709 {
710 e_cal_model_update_comp_time (model, comp_data, value, ICAL_DUE_PROPERTY, icalproperty_set_due, icalproperty_new_due);
711 }
712
713 /* FIXME: We need to set the "transient_for" property for the dialog, but the
714 * model doesn't know anything about the windows.
715 */
716 static void
717 show_geo_warning (void)
718 {
719 GtkWidget *dialog;
720
721 dialog = gtk_message_dialog_new (
722 NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
723 "%s", _("The geographical position must be entered "
724 "in the format: \n\n45.436845,125.862501"));
725 gtk_widget_show (dialog);
726 }
727
728 static void
729 set_geo (ECalModelComponent *comp_data,
730 const gchar *value)
731 {
732 gdouble latitude, longitude;
733 gint matched;
734 struct icalgeotype geo;
735 icalproperty *prop;
736
737 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_GEO_PROPERTY);
738
739 if (string_is_empty (value)) {
740 if (prop) {
741 icalcomponent_remove_property (comp_data->icalcomp, prop);
742 icalproperty_free (prop);
743 }
744 } else {
745 matched = sscanf (value, "%lg , %lg", &latitude, &longitude);
746 if (matched != 2)
747 show_geo_warning ();
748
749 geo.lat = latitude;
750 geo.lon = longitude;
751 if (prop)
752 icalproperty_set_geo (prop, geo);
753 else {
754 prop = icalproperty_new_geo (geo);
755 icalcomponent_add_property (comp_data->icalcomp, prop);
756 }
757
758 }
759 }
760
761 static void
762 set_status (ECalModelComponent *comp_data,
763 const gchar *value)
764 {
765 icalproperty_status status;
766 icalproperty *prop;
767
768 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_STATUS_PROPERTY);
769
770 /* an empty string is the same as 'None' */
771 if (!value[0])
772 return;
773
774 /* Translators: "None" for task's status */
775 if (!e_util_utf8_strcasecmp (value, C_("cal-task-status", "None")))
776 return;
777 else if (!e_util_utf8_strcasecmp (value, _("Not Started")))
778 status = ICAL_STATUS_NEEDSACTION;
779 else if (!e_util_utf8_strcasecmp (value, _("In Progress")))
780 status = ICAL_STATUS_INPROCESS;
781 else if (!e_util_utf8_strcasecmp (value, _("Completed")))
782 status = ICAL_STATUS_COMPLETED;
783 else if (!e_util_utf8_strcasecmp (value, _("Canceled")))
784 status = ICAL_STATUS_CANCELLED;
785 else {
786 g_warning ("Invalid status: %s\n", value);
787 return;
788 }
789
790 if (prop)
791 icalproperty_set_status (prop, status);
792 else {
793 prop = icalproperty_new_status (status);
794 icalcomponent_add_property (comp_data->icalcomp, prop);
795 }
796
797 switch (status) {
798 case ICAL_STATUS_NEEDSACTION:
799 ensure_task_not_complete (comp_data);
800 break;
801
802 case ICAL_STATUS_INPROCESS:
803 ensure_task_partially_complete (comp_data);
804 break;
805
806 case ICAL_STATUS_CANCELLED:
807 ensure_task_not_complete (comp_data);
808 /* do this again, because the previous function changed status to NEEDSACTION */
809 icalproperty_set_status (prop, status);
810 break;
811
812 case ICAL_STATUS_COMPLETED:
813 ensure_task_complete (comp_data, -1);
814 break;
815 default:
816 break;
817 }
818 }
819
820 static void
821 set_percent (ECalModelComponent *comp_data,
822 gconstpointer value)
823 {
824 icalproperty *prop;
825 gint percent = GPOINTER_TO_INT (value);
826
827 g_return_if_fail (percent >= -1);
828 g_return_if_fail (percent <= 100);
829
830 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
831
832 /* A value of -1 means it isn't set */
833 if (percent == -1) {
834 if (prop) {
835 icalcomponent_remove_property (comp_data->icalcomp, prop);
836 icalproperty_free (prop);
837 }
838 ensure_task_not_complete (comp_data);
839 } else {
840 if (prop)
841 icalproperty_set_percentcomplete (prop, percent);
842 else {
843 prop = icalproperty_new_percentcomplete (percent);
844 icalcomponent_add_property (comp_data->icalcomp, prop);
845 }
846
847 if (percent == 100)
848 ensure_task_complete (comp_data, -1);
849 else {
850 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_COMPLETED_PROPERTY);
851 if (prop) {
852 icalcomponent_remove_property (comp_data->icalcomp, prop);
853 icalproperty_free (prop);
854 }
855
856 if (percent > 0)
857 set_status (comp_data, _("In Progress"));
858 }
859 }
860
861 }
862
863 static void
864 set_priority (ECalModelComponent *comp_data,
865 const gchar *value)
866 {
867 icalproperty *prop;
868 gint priority;
869
870 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PRIORITY_PROPERTY);
871
872 priority = e_cal_util_priority_from_string (value);
873 if (priority == -1) {
874 g_warning ("Invalid priority");
875 priority = 0;
876 }
877
878 if (prop)
879 icalproperty_set_priority (prop, priority);
880 else {
881 prop = icalproperty_new_priority (priority);
882 icalcomponent_add_property (comp_data->icalcomp, prop);
883 }
884 }
885
886 static void
887 set_url (ECalModelComponent *comp_data,
888 const gchar *value)
889 {
890 icalproperty *prop;
891
892 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_URL_PROPERTY);
893
894 if (string_is_empty (value)) {
895 if (prop) {
896 icalcomponent_remove_property (comp_data->icalcomp, prop);
897 icalproperty_free (prop);
898 }
899 } else {
900 if (prop)
901 icalproperty_set_url (prop, value);
902 else {
903 prop = icalproperty_new_url (value);
904 icalcomponent_add_property (comp_data->icalcomp, prop);
905 }
906 }
907 }
908
909 static void
910 ecmt_set_value_at (ETableModel *etm,
911 gint col,
912 gint row,
913 gconstpointer value)
914 {
915 ECalModelComponent *comp_data;
916 ECalModelTasks *model = (ECalModelTasks *) etm;
917
918 g_return_if_fail (E_IS_CAL_MODEL_TASKS (model));
919
920 g_return_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST);
921 g_return_if_fail (row >= 0 && row < e_table_model_row_count (etm));
922
923 if (col < E_CAL_MODEL_FIELD_LAST) {
924 E_TABLE_MODEL_CLASS (e_cal_model_tasks_parent_class)->set_value_at (etm, col, row, value);
925 return;
926 }
927
928 comp_data = e_cal_model_get_component_at (E_CAL_MODEL (model), row);
929 if (!comp_data)
930 return;
931
932 switch (col) {
933 case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
934 set_completed (model, comp_data, value);
935 break;
936 case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
937 set_complete (comp_data, value);
938 break;
939 case E_CAL_MODEL_TASKS_FIELD_DUE :
940 set_due ((ECalModel *) model, comp_data, value);
941 break;
942 case E_CAL_MODEL_TASKS_FIELD_GEO :
943 set_geo (comp_data, value);
944 break;
945 case E_CAL_MODEL_TASKS_FIELD_PERCENT :
946 set_percent (comp_data, value);
947 break;
948 case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
949 set_priority (comp_data, value);
950 break;
951 case E_CAL_MODEL_TASKS_FIELD_STATUS :
952 set_status (comp_data, value);
953 break;
954 case E_CAL_MODEL_TASKS_FIELD_URL :
955 set_url (comp_data, value);
956 break;
957 }
958
959 commit_component_changes (comp_data);
960 }
961
962 static gboolean
963 ecmt_is_cell_editable (ETableModel *etm,
964 gint col,
965 gint row)
966 {
967 ECalModelTasks *model = (ECalModelTasks *) etm;
968
969 g_return_val_if_fail (E_IS_CAL_MODEL_TASKS (model), FALSE);
970
971 g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST, FALSE);
972 g_return_val_if_fail (row >= -1 || (row >= 0 && row < e_table_model_row_count (etm)), FALSE);
973
974 if (col < E_CAL_MODEL_FIELD_LAST)
975 return E_TABLE_MODEL_CLASS (e_cal_model_tasks_parent_class)->is_cell_editable (etm, col, row);
976
977 if (!e_cal_model_test_row_editable (E_CAL_MODEL (etm), row))
978 return FALSE;
979
980 switch (col) {
981 case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
982 case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
983 case E_CAL_MODEL_TASKS_FIELD_DUE :
984 case E_CAL_MODEL_TASKS_FIELD_GEO :
985 case E_CAL_MODEL_TASKS_FIELD_PERCENT :
986 case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
987 case E_CAL_MODEL_TASKS_FIELD_STATUS :
988 case E_CAL_MODEL_TASKS_FIELD_URL :
989 return TRUE;
990 }
991
992 return FALSE;
993 }
994
995 static gpointer
996 ecmt_duplicate_value (ETableModel *etm,
997 gint col,
998 gconstpointer value)
999 {
1000 g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST, NULL);
1001
1002 if (col < E_CAL_MODEL_FIELD_LAST)
1003 return E_TABLE_MODEL_CLASS (e_cal_model_tasks_parent_class)->duplicate_value (etm, col, value);
1004
1005 switch (col) {
1006 case E_CAL_MODEL_TASKS_FIELD_GEO :
1007 case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
1008 case E_CAL_MODEL_TASKS_FIELD_STATUS :
1009 case E_CAL_MODEL_TASKS_FIELD_URL :
1010 return g_strdup (value);
1011 case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
1012 case E_CAL_MODEL_TASKS_FIELD_DUE :
1013 if (value) {
1014 ECellDateEditValue *dv, *orig_dv;
1015
1016 orig_dv = (ECellDateEditValue *) value;
1017 dv = g_new0 (ECellDateEditValue, 1);
1018 *dv = *orig_dv;
1019
1020 return dv;
1021 }
1022 break;
1023
1024 case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
1025 case E_CAL_MODEL_TASKS_FIELD_PERCENT :
1026 case E_CAL_MODEL_TASKS_FIELD_OVERDUE :
1027 return (gpointer) value;
1028 }
1029
1030 return NULL;
1031 }
1032
1033 static void
1034 ecmt_free_value (ETableModel *etm,
1035 gint col,
1036 gpointer value)
1037 {
1038 g_return_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST);
1039
1040 if (col < E_CAL_MODEL_FIELD_LAST) {
1041 E_TABLE_MODEL_CLASS (e_cal_model_tasks_parent_class)->free_value (etm, col, value);
1042 return;
1043 }
1044
1045 switch (col) {
1046 case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
1047 case E_CAL_MODEL_TASKS_FIELD_DUE :
1048 case E_CAL_MODEL_TASKS_FIELD_GEO :
1049 case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
1050 case E_CAL_MODEL_TASKS_FIELD_STATUS :
1051 case E_CAL_MODEL_TASKS_FIELD_URL :
1052 if (value)
1053 g_free (value);
1054 break;
1055 case E_CAL_MODEL_TASKS_FIELD_PERCENT :
1056 case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
1057 case E_CAL_MODEL_TASKS_FIELD_OVERDUE :
1058 break;
1059 }
1060 }
1061
1062 static gpointer
1063 ecmt_initialize_value (ETableModel *etm,
1064 gint col)
1065 {
1066 ECalModelTasks *model = (ECalModelTasks *) etm;
1067
1068 g_return_val_if_fail (E_IS_CAL_MODEL_TASKS (model), NULL);
1069 g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST, NULL);
1070
1071 if (col < E_CAL_MODEL_FIELD_LAST)
1072 return E_TABLE_MODEL_CLASS (e_cal_model_tasks_parent_class)->initialize_value (etm, col);
1073
1074 switch (col) {
1075 case E_CAL_MODEL_TASKS_FIELD_GEO :
1076 case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
1077 case E_CAL_MODEL_TASKS_FIELD_STATUS :
1078 case E_CAL_MODEL_TASKS_FIELD_URL :
1079 return g_strdup ("");
1080 case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
1081 case E_CAL_MODEL_TASKS_FIELD_DUE :
1082 case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
1083 case E_CAL_MODEL_TASKS_FIELD_OVERDUE :
1084 return NULL;
1085 case E_CAL_MODEL_TASKS_FIELD_PERCENT :
1086 return GINT_TO_POINTER (-1);
1087 }
1088
1089 return NULL;
1090 }
1091
1092 static gboolean
1093 ecmt_value_is_empty (ETableModel *etm,
1094 gint col,
1095 gconstpointer value)
1096 {
1097 ECalModelTasks *model = (ECalModelTasks *) etm;
1098
1099 g_return_val_if_fail (E_IS_CAL_MODEL_TASKS (model), TRUE);
1100 g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST, TRUE);
1101
1102 if (col < E_CAL_MODEL_FIELD_LAST)
1103 return E_TABLE_MODEL_CLASS (e_cal_model_tasks_parent_class)->value_is_empty (etm, col, value);
1104
1105 switch (col) {
1106 case E_CAL_MODEL_TASKS_FIELD_GEO :
1107 case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
1108 case E_CAL_MODEL_TASKS_FIELD_STATUS :
1109 case E_CAL_MODEL_TASKS_FIELD_URL :
1110 return string_is_empty (value);
1111 case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
1112 case E_CAL_MODEL_TASKS_FIELD_DUE :
1113 return value ? FALSE : TRUE;
1114 case E_CAL_MODEL_TASKS_FIELD_PERCENT :
1115 return (GPOINTER_TO_INT (value) < 0) ? TRUE : FALSE;
1116 case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
1117 case E_CAL_MODEL_TASKS_FIELD_OVERDUE :
1118 return TRUE;
1119 }
1120
1121 return TRUE;
1122 }
1123
1124 static gchar *
1125 ecmt_value_to_string (ETableModel *etm,
1126 gint col,
1127 gconstpointer value)
1128 {
1129 ECalModelTasks *model = (ECalModelTasks *) etm;
1130
1131 g_return_val_if_fail (E_IS_CAL_MODEL_TASKS (model), g_strdup (""));
1132 g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST, g_strdup (""));
1133
1134 if (col < E_CAL_MODEL_FIELD_LAST)
1135 return E_TABLE_MODEL_CLASS (e_cal_model_tasks_parent_class)->value_to_string (etm, col, value);
1136
1137 switch (col) {
1138 case E_CAL_MODEL_TASKS_FIELD_GEO :
1139 case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
1140 case E_CAL_MODEL_TASKS_FIELD_STATUS :
1141 case E_CAL_MODEL_TASKS_FIELD_URL :
1142 return g_strdup (value);
1143 case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
1144 case E_CAL_MODEL_TASKS_FIELD_DUE :
1145 return e_cal_model_date_value_to_string (E_CAL_MODEL (model), value);
1146 case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
1147 case E_CAL_MODEL_TASKS_FIELD_OVERDUE :
1148 return g_strdup (value ? _("Yes") : _("No"));
1149 case E_CAL_MODEL_TASKS_FIELD_PERCENT :
1150 if (GPOINTER_TO_INT (value) < 0)
1151 return g_strdup ("N/A");
1152 else
1153 return g_strdup_printf ("%i%%", GPOINTER_TO_INT (value));
1154 }
1155
1156 return g_strdup ("");
1157 }
1158
1159 /* ECalModel class methods */
1160
1161 static const gchar *
1162 ecmt_get_color_for_component (ECalModel *model,
1163 ECalModelComponent *comp_data)
1164 {
1165 ECalModelTasks *tasks;
1166
1167 g_return_val_if_fail (E_IS_CAL_MODEL_TASKS (model), NULL);
1168 g_return_val_if_fail (comp_data != NULL, NULL);
1169
1170 tasks = E_CAL_MODEL_TASKS (model);
1171
1172 /* XXX ECalModel's get_color_for_component() method should really
1173 * get a GdkColor instead of a color specification string. */
1174
1175 switch (get_due_status (tasks, comp_data)) {
1176 case E_CAL_MODEL_TASKS_DUE_TODAY:
1177 if (!e_cal_model_tasks_get_highlight_due_today (tasks))
1178 break;
1179 return e_cal_model_tasks_get_color_due_today (tasks);
1180 case E_CAL_MODEL_TASKS_DUE_OVERDUE:
1181 if (!e_cal_model_tasks_get_highlight_overdue (tasks))
1182 break;
1183 return e_cal_model_tasks_get_color_overdue (tasks);
1184 case E_CAL_MODEL_TASKS_DUE_NEVER:
1185 case E_CAL_MODEL_TASKS_DUE_FUTURE:
1186 case E_CAL_MODEL_TASKS_DUE_COMPLETE:
1187 break;
1188 }
1189
1190 return E_CAL_MODEL_CLASS (e_cal_model_tasks_parent_class)->
1191 get_color_for_component (model, comp_data);
1192 }
1193
1194 static void
1195 ecmt_fill_component_from_model (ECalModel *model,
1196 ECalModelComponent *comp_data,
1197 ETableModel *source_model,
1198 gint row)
1199 {
1200 gpointer value;
1201
1202 g_return_if_fail (E_IS_CAL_MODEL_TASKS (model));
1203 g_return_if_fail (comp_data != NULL);
1204 g_return_if_fail (E_IS_TABLE_MODEL (source_model));
1205
1206 /* This just makes sure if anything indicates completion, all
1207 * three fields do or if percent is 0, status is sane */
1208
1209 value = e_table_model_value_at (source_model, E_CAL_MODEL_TASKS_FIELD_COMPLETED, row);
1210 set_completed ((ECalModelTasks *) model, comp_data, value);
1211 if (!value) {
1212 value = e_table_model_value_at (source_model, E_CAL_MODEL_TASKS_FIELD_PERCENT, row);
1213 set_percent (comp_data, value);
1214 if (GPOINTER_TO_INT (value) != 100 && GPOINTER_TO_INT (value) != 0)
1215 set_status (comp_data, e_table_model_value_at (source_model, E_CAL_MODEL_TASKS_FIELD_STATUS, row));
1216 }
1217
1218 set_due (
1219 model, comp_data,
1220 e_table_model_value_at (source_model, E_CAL_MODEL_TASKS_FIELD_DUE, row));
1221 set_geo (
1222 comp_data,
1223 e_table_model_value_at (source_model, E_CAL_MODEL_TASKS_FIELD_GEO, row));
1224 set_priority (
1225 comp_data,
1226 e_table_model_value_at (source_model, E_CAL_MODEL_TASKS_FIELD_PRIORITY, row));
1227 set_url (
1228 comp_data,
1229 e_table_model_value_at (source_model, E_CAL_MODEL_TASKS_FIELD_URL, row));
1230 }
1231
1232 ECalModel *
1233 e_cal_model_tasks_new (ESourceRegistry *registry)
1234 {
1235 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
1236
1237 return g_object_new (
1238 E_TYPE_CAL_MODEL_TASKS,
1239 "registry", registry, NULL);
1240 }
1241
1242 gboolean
1243 e_cal_model_tasks_get_highlight_due_today (ECalModelTasks *model)
1244 {
1245 g_return_val_if_fail (E_IS_CAL_MODEL_TASKS (model), FALSE);
1246
1247 return model->priv->highlight_due_today;
1248 }
1249
1250 void
1251 e_cal_model_tasks_set_highlight_due_today (ECalModelTasks *model,
1252 gboolean highlight)
1253 {
1254 g_return_if_fail (E_IS_CAL_MODEL_TASKS (model));
1255
1256 if (model->priv->highlight_due_today == highlight)
1257 return;
1258
1259 model->priv->highlight_due_today = highlight;
1260
1261 g_object_notify (G_OBJECT (model), "highlight-due-today");
1262 }
1263
1264 const gchar *
1265 e_cal_model_tasks_get_color_due_today (ECalModelTasks *model)
1266 {
1267 g_return_val_if_fail (E_IS_CAL_MODEL_TASKS (model), NULL);
1268
1269 return model->priv->color_due_today;
1270 }
1271
1272 void
1273 e_cal_model_tasks_set_color_due_today (ECalModelTasks *model,
1274 const gchar *color_due_today)
1275 {
1276 g_return_if_fail (E_IS_CAL_MODEL_TASKS (model));
1277 g_return_if_fail (color_due_today != NULL);
1278
1279 if (g_strcmp0 (model->priv->color_due_today, color_due_today) == 0)
1280 return;
1281
1282 g_free (model->priv->color_due_today);
1283 model->priv->color_due_today = g_strdup (color_due_today);
1284
1285 g_object_notify (G_OBJECT (model), "color-due-today");
1286 }
1287
1288 gboolean
1289 e_cal_model_tasks_get_highlight_overdue (ECalModelTasks *model)
1290 {
1291 g_return_val_if_fail (E_IS_CAL_MODEL_TASKS (model), FALSE);
1292
1293 return model->priv->highlight_overdue;
1294 }
1295
1296 void
1297 e_cal_model_tasks_set_highlight_overdue (ECalModelTasks *model,
1298 gboolean highlight)
1299 {
1300 g_return_if_fail (E_IS_CAL_MODEL_TASKS (model));
1301
1302 if (model->priv->highlight_overdue == highlight)
1303 return;
1304
1305 model->priv->highlight_overdue = highlight;
1306
1307 g_object_notify (G_OBJECT (model), "highlight-overdue");
1308 }
1309
1310 const gchar *
1311 e_cal_model_tasks_get_color_overdue (ECalModelTasks *model)
1312 {
1313 g_return_val_if_fail (E_IS_CAL_MODEL_TASKS (model), NULL);
1314
1315 return model->priv->color_overdue;
1316 }
1317
1318 void
1319 e_cal_model_tasks_set_color_overdue (ECalModelTasks *model,
1320 const gchar *color_overdue)
1321 {
1322 g_return_if_fail (E_IS_CAL_MODEL_TASKS (model));
1323 g_return_if_fail (color_overdue != NULL);
1324
1325 if (g_strcmp0 (model->priv->color_overdue, color_overdue) == 0)
1326 return;
1327
1328 g_free (model->priv->color_overdue);
1329 model->priv->color_overdue = g_strdup (color_overdue);
1330
1331 g_object_notify (G_OBJECT (model), "color-overdue");
1332 }
1333
1334 /**
1335 * e_cal_model_tasks_mark_comp_complete
1336 * @model: Currently not used...
1337 * @comp_data: Component of our interest
1338 *
1339 * Marks component as complete and commits changes to the calendar backend.
1340 **/
1341 void e_cal_model_tasks_mark_comp_complete (ECalModelTasks *model, ECalModelComponent *comp_data)
1342 {
1343 g_return_if_fail (model != NULL);
1344 g_return_if_fail (comp_data != NULL);
1345
1346 /* we will receive changes when committed, so don't do this */
1347 /*e_table_model_pre_change (E_TABLE_MODEL (model));*/
1348
1349 ensure_task_complete (comp_data, -1);
1350
1351 /*e_table_model_row_changed (E_TABLE_MODEL (model), model_row);*/
1352
1353 commit_component_changes (comp_data);
1354 }
1355
1356 /**
1357 * e_cal_model_tasks_mark_comp_incomplete
1358 * @model: Currently not used...
1359 * @comp_data: Component of our interest
1360 *
1361 * Marks component as incomplete and commits changes to the calendar backend.
1362 **/
1363 void e_cal_model_tasks_mark_comp_incomplete (ECalModelTasks *model, ECalModelComponent *comp_data)
1364 {
1365 icalproperty *prop,*prop1;
1366
1367 g_return_if_fail (model != NULL);
1368 g_return_if_fail (comp_data != NULL);
1369
1370 /* we will receive changes when committed, so don't do this */
1371 /*e_table_model_pre_change (E_TABLE_MODEL (model));*/
1372
1373 /* Status */
1374 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_STATUS_PROPERTY);
1375 if (prop)
1376 icalproperty_set_status (prop, ICAL_STATUS_NEEDSACTION);
1377 else
1378 icalcomponent_add_property (comp_data->icalcomp, icalproperty_new_status (ICAL_STATUS_NEEDSACTION));
1379
1380 /*complete property*/
1381 prop1 = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_COMPLETED_PROPERTY);
1382 if (prop1) {
1383 icalcomponent_remove_property (comp_data->icalcomp, prop1);
1384 icalproperty_free (prop1);
1385 }
1386
1387 /* Percent. */
1388 prop1 = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
1389 if (prop1) {
1390 icalcomponent_remove_property (comp_data->icalcomp, prop1);
1391 icalproperty_free (prop1);
1392 }
1393
1394 /*e_table_model_row_changed (E_TABLE_MODEL (model), model_row);*/
1395
1396 commit_component_changes (comp_data);
1397 }
1398
1399 /**
1400 * commit_component_changes
1401 * @comp_data: Component of our interest, which has been changed.
1402 *
1403 * Commits changes to the backend calendar of the component.
1404 **/
1405 static void
1406 commit_component_changes (ECalModelComponent *comp_data)
1407 {
1408 GError *error = NULL;
1409
1410 g_return_if_fail (comp_data != NULL);
1411
1412 /* FIXME ask about mod type */
1413 e_cal_client_modify_object_sync (
1414 comp_data->client, comp_data->icalcomp,
1415 CALOBJ_MOD_ALL, NULL, &error);
1416
1417 if (error != NULL) {
1418 g_warning (
1419 G_STRLOC ": Could not modify the object! %s",
1420 error->message);
1421
1422 /* FIXME Show error dialog */
1423 g_error_free (error);
1424 }
1425 }
1426
1427 /**
1428 * e_cal_model_tasks_update_due_tasks
1429 */
1430 void
1431 e_cal_model_tasks_update_due_tasks (ECalModelTasks *model)
1432 {
1433 gint row, row_count;
1434 ECalModelComponent *comp_data;
1435 ECalModelTasksDueStatus status;
1436
1437 g_return_if_fail (E_IS_CAL_MODEL_TASKS (model));
1438
1439 row_count = e_table_model_row_count (E_TABLE_MODEL (model));
1440
1441 for (row = 0; row < row_count; row++)
1442 {
1443 comp_data = e_cal_model_get_component_at (E_CAL_MODEL (model), row);
1444 status = get_due_status (E_CAL_MODEL_TASKS (model), comp_data);
1445 if ((status == E_CAL_MODEL_TASKS_DUE_TODAY) || (status == E_CAL_MODEL_TASKS_DUE_OVERDUE))
1446 {
1447 e_table_model_pre_change (E_TABLE_MODEL (model));
1448 e_table_model_row_changed (E_TABLE_MODEL (model), row);
1449 }
1450 }
1451 }