aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDamon Chaplin <damon@ximian.com>2001-09-18 09:35:46 +0800
committerDamon Chaplin <damon@src.gnome.org>2001-09-18 09:35:46 +0800
commit999889586bbb251669c5a384f1b5d03bd72d0a6d (patch)
tree7041172cea75e0ee3556c3629425a8cda60bd58f
parent5772dcbe43079dd8cf59e5458cb44a7a749df66f (diff)
downloadgsoc2013-evolution-999889586bbb251669c5a384f1b5d03bd72d0a6d.tar
gsoc2013-evolution-999889586bbb251669c5a384f1b5d03bd72d0a6d.tar.gz
gsoc2013-evolution-999889586bbb251669c5a384f1b5d03bd72d0a6d.tar.bz2
gsoc2013-evolution-999889586bbb251669c5a384f1b5d03bd72d0a6d.tar.lz
gsoc2013-evolution-999889586bbb251669c5a384f1b5d03bd72d0a6d.tar.xz
gsoc2013-evolution-999889586bbb251669c5a384f1b5d03bd72d0a6d.tar.zst
gsoc2013-evolution-999889586bbb251669c5a384f1b5d03bd72d0a6d.zip
added a timeout to refresh the list every 10 minutes. Not ideal, as the
2001-09-17 Damon Chaplin <damon@ximian.com> * gui/calendar-model.c: added a timeout to refresh the list every 10 minutes. Not ideal, as the user may be editing a task when it gets refreshed. (adjust_query_sexp): use the 'completed-before?' operator to filter out tasks according to the config settings. * gui/dialogs/task-details-page.c (task_details_page_fill_widgets): added support for the 'Completed' date. This code must have got lost somewhere, as it used to work. (date_changed_cb): set the priv->updating flag while updating the other widgets. * pcs/cal-backend-file.c (cal_backend_file_update_objects): made sure we freed the components. * pcs/query.c (func_completed_before): added 'completed-before?' operator. * gui/calendar-config.c (calendar_config_configure_e_cell_date_edit): don't set the lower & upper hour. Use 0-24 like the EDateEdit does. * gui/dialogs/cal-prefs-dialog.c (cal_prefs_dialog_show_config): set the 12/24-hour time format options sensitive only if we support both. * gui/calendar-config.c (config_read): if the locale doesn't define 'am' and 'pm' strings then we must use 24-hour format. * gui/calendar-commands.c (calendar_set_folder_bar_label): don't translate the '%d' as it doesn't make much sense. Resolves bug #8027. svn path=/trunk/; revision=12925
-rw-r--r--calendar/ChangeLog32
-rw-r--r--calendar/gui/calendar-commands.c2
-rw-r--r--calendar/gui/calendar-config.c29
-rw-r--r--calendar/gui/calendar-config.h3
-rw-r--r--calendar/gui/calendar-model.c114
-rw-r--r--calendar/gui/calendar-model.h2
-rw-r--r--calendar/gui/dialogs/cal-prefs-dialog.c6
-rw-r--r--calendar/gui/dialogs/task-details-page.c45
-rw-r--r--calendar/pcs/cal-backend-file.c37
-rw-r--r--calendar/pcs/query.c72
10 files changed, 303 insertions, 39 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog
index 2224e510f6..880521239a 100644
--- a/calendar/ChangeLog
+++ b/calendar/ChangeLog
@@ -1,3 +1,35 @@
+2001-09-17 Damon Chaplin <damon@ximian.com>
+
+ * gui/calendar-model.c: added a timeout to refresh the list every
+ 10 minutes. Not ideal, as the user may be editing a task when it gets
+ refreshed.
+ (adjust_query_sexp): use the 'completed-before?' operator to filter
+ out tasks according to the config settings.
+
+ * gui/dialogs/task-details-page.c (task_details_page_fill_widgets):
+ added support for the 'Completed' date. This code must have got lost
+ somewhere, as it used to work.
+ (date_changed_cb): set the priv->updating flag while updating the other
+ widgets.
+
+ * pcs/cal-backend-file.c (cal_backend_file_update_objects): made sure
+ we freed the components.
+
+ * pcs/query.c (func_completed_before): added 'completed-before?'
+ operator.
+
+ * gui/calendar-config.c (calendar_config_configure_e_cell_date_edit):
+ don't set the lower & upper hour. Use 0-24 like the EDateEdit does.
+
+ * gui/dialogs/cal-prefs-dialog.c (cal_prefs_dialog_show_config): set
+ the 12/24-hour time format options sensitive only if we support both.
+
+ * gui/calendar-config.c (config_read): if the locale doesn't define
+ 'am' and 'pm' strings then we must use 24-hour format.
+
+ * gui/calendar-commands.c (calendar_set_folder_bar_label): don't
+ translate the '%d' as it doesn't make much sense. Resolves bug #8027.
+
2001-09-17 Federico Mena Quintero <federico@ximian.com>
* gui/component-factory.c (owner_set_cb): Do not call
diff --git a/calendar/gui/calendar-commands.c b/calendar/gui/calendar-commands.c
index efb4b7860c..7c510024c3 100644
--- a/calendar/gui/calendar-commands.c
+++ b/calendar/gui/calendar-commands.c
@@ -448,7 +448,7 @@ calendar_set_folder_bar_label (GnomeCalendar *gcal, BonoboControl *control)
if (start_tm.tm_year == end_tm.tm_year) {
if (start_tm.tm_mon == end_tm.tm_mon) {
strftime (buffer, sizeof (buffer),
- _("%d"), &start_tm);
+ "%d", &start_tm);
strftime (end_buffer, sizeof (end_buffer),
_("%d %B %Y"), &end_tm);
strcat (buffer, " - ");
diff --git a/calendar/gui/calendar-config.c b/calendar/gui/calendar-config.c
index 33be9f2f02..aed61238ec 100644
--- a/calendar/gui/calendar-config.c
+++ b/calendar/gui/calendar-config.c
@@ -90,14 +90,16 @@ calendar_config_init (void)
config_read ();
}
-static gboolean
-locale_uses_24h_time_format (void)
+/* Returns TRUE if the locale has 'am' and 'pm' strings defined, in which
+ case the user can choose between 12 and 24-hour time formats. */
+gboolean
+calendar_config_locale_supports_12_hour_format (void)
{
char s[16];
time_t t = 0;
strftime (s, sizeof s, "%p", gmtime (&t));
- return s[0] == '\0';
+ return s[0] != '\0';
}
static void
@@ -128,8 +130,15 @@ config_read (void)
config->week_start_day = bonobo_config_get_long_with_default (db,
"/Calendar/Display/WeekStartDay", 1, NULL);
- config->use_24_hour_format = bonobo_config_get_boolean_with_default (
- db, "/Calendar/Display/Use24HourFormat", locale_uses_24h_time_format (), NULL);
+ /* If the locale defines 'am' and 'pm' strings then the user has the
+ choice of 12-hour or 24-hour time format, with 12-hour as the
+ default. If the locale doesn't have 'am' and 'pm' strings we have
+ to use 24-hour format, or strftime()/strptime() won't work. */
+ if (calendar_config_locale_supports_12_hour_format ()) {
+ config->use_24_hour_format = bonobo_config_get_boolean_with_default (db, "/Calendar/Display/Use24HourFormat", FALSE, NULL);
+ } else {
+ config->use_24_hour_format = TRUE;
+ }
config->week_start_day = bonobo_config_get_long_with_default (db,
"/Calendar/Display/WeekStartDay", 1, NULL);
@@ -687,15 +696,19 @@ calendar_config_configure_e_cell_date_edit (ECellDateEdit *ecde)
start_hour = calendar_config_get_day_start_hour ();
end_hour = calendar_config_get_day_end_hour ();
+
/* Round up the end hour. */
if (calendar_config_get_day_end_minute () != 0)
- end_hour = end_hour + 1 % 24;
+ end_hour++;
e_cell_date_edit_freeze (ecde);
gtk_object_set (GTK_OBJECT (ecde),
"use_24_hour_format", use_24_hour,
+#if 0
+ /* We use the default 0 - 24 now. */
"lower_hour", start_hour,
"upper_hour", end_hour,
+#endif
NULL);
e_cell_date_edit_thaw (ecde);
}
@@ -725,6 +738,10 @@ calendar_config_configure_e_calendar_table (ECalendarTable *cal_table)
calendar_config_configure_e_cell_date_edit (cal_table->dates_cell);
+ /* Reload the event/tasks, since the 'Hide Completed Tasks' option
+ may have been changed, so the query needs to be updated. */
+ calendar_model_refresh (model);
+
/* This is for changing the colors of the text; they will be re-fetched
* by ECellText when the table is redrawn.
*/
diff --git a/calendar/gui/calendar-config.h b/calendar/gui/calendar-config.h
index 83132267f9..d579cd8190 100644
--- a/calendar/gui/calendar-config.h
+++ b/calendar/gui/calendar-config.h
@@ -159,5 +159,8 @@ void calendar_config_configure_e_cell_date_edit (ECellDateEdit *ecde);
/* Shows the timezone dialog if the user hasn't set a default timezone. */
void calendar_config_check_timezone_set (void);
+/* Returns TRUE if the locale has 'am' and 'pm' strings defined, i.e. it
+ supports 12-hour time format. */
+gboolean calendar_config_locale_supports_12_hour_format(void);
#endif /* _CALENDAR_CONFIG_H_ */
diff --git a/calendar/gui/calendar-model.c b/calendar/gui/calendar-model.c
index 5779266a2f..8a26af5faf 100644
--- a/calendar/gui/calendar-model.c
+++ b/calendar/gui/calendar-model.c
@@ -40,6 +40,12 @@
#include "itip-utils.h"
#include "calendar-model.h"
+/* This specifies how often we refresh the list, so that completed tasks are
+ hidden according to the config setting, and overdue tasks change color etc.
+ It is in milliseconds, so this is 10 minutes.
+ Note that if the user is editing an item in the list, they will probably
+ lose their edit, so this isn't ideal. */
+#define CALENDAR_MODEL_REFRESH_TIMEOUT 1000 * 60 * 10
/* Private part of the ECalendarModel structure */
struct _CalendarModelPrivate {
@@ -75,6 +81,9 @@ struct _CalendarModelPrivate {
/* The current timezone. */
icaltimezone *zone;
+
+ /* The id of our timeout function for refreshing the list. */
+ gint timeout_id;
};
@@ -162,6 +171,25 @@ calendar_model_class_init (CalendarModelClass *class)
etm_class->value_to_string = calendar_model_value_to_string;
}
+
+static gboolean
+calendar_model_timeout_cb (gpointer data)
+{
+ CalendarModel *model;
+
+ g_return_val_if_fail (IS_CALENDAR_MODEL (data), FALSE);
+
+ model = CALENDAR_MODEL (data);
+
+ GDK_THREADS_ENTER ();
+
+ calendar_model_refresh (model);
+
+ GDK_THREADS_LEAVE ();
+ return TRUE;
+}
+
+
/* Object initialization function for the calendar table model */
static void
calendar_model_init (CalendarModel *model)
@@ -179,6 +207,9 @@ calendar_model_init (CalendarModel *model)
priv->new_comp_vtype = CAL_COMPONENT_EVENT;
priv->use_24_hour_format = TRUE;
+ priv->timeout_id = g_timeout_add (CALENDAR_MODEL_REFRESH_TIMEOUT,
+ calendar_model_timeout_cb, model);
+
priv->addresses = itip_addresses_get ();
priv->zone = NULL;
@@ -233,6 +264,11 @@ calendar_model_destroy (GtkObject *object)
model = CALENDAR_MODEL (object);
priv = model->priv;
+ if (priv->timeout_id) {
+ g_source_remove (priv->timeout_id);
+ priv->timeout_id = 0;
+ }
+
/* Free the calendar client interface object */
if (priv->client) {
@@ -1839,7 +1875,8 @@ query_eval_error_cb (CalQuery *query, const char *error_str, gpointer data)
}
/* Builds a complete query sexp for the calendar model by adding the predicates
- * to filter only for the type of objects that the model supports.
+ * to filter only for the type of objects that the model supports, and
+ * whether we want completed tasks.
*/
static char *
adjust_query_sexp (CalendarModel *model, const char *sexp)
@@ -1848,6 +1885,7 @@ adjust_query_sexp (CalendarModel *model, const char *sexp)
CalObjType type;
char *type_sexp;
char *completed_sexp = "";
+ gboolean free_completed_sexp = FALSE;
char *new_sexp;
priv = model->priv;
@@ -1863,15 +1901,60 @@ adjust_query_sexp (CalendarModel *model, const char *sexp)
(type & CALOBJ_TYPE_TODO) ? "(= (get-vtype) \"VTODO\")" : "",
(type & CALOBJ_TYPE_JOURNAL) ? "(= (get-vtype) \"VJOURNAL\")" : "");
- /* FIXME: Use config setting eventually. */
-#if 0
- if (1)
- completed_sexp = "(not is-completed?)";
-#endif
+ /* Create a sub-expression for filtering out completed tasks, based on
+ the config settings. */
+ if (calendar_config_get_hide_completed_tasks ()) {
+ CalUnits units;
+ gint value;
+
+ units = calendar_config_get_hide_completed_tasks_units ();
+ value = calendar_config_get_hide_completed_tasks_value ();
+
+ if (value == 0) {
+ /* If the value is 0, we want to hide completed tasks
+ immediately, so we filter out all completed tasks.*/
+ completed_sexp = "(not is-completed?)";
+ } else {
+ char *location, *isodate;
+ icaltimezone *zone;
+ struct icaltimetype tt;
+ time_t t;
+
+ /* Get the current time, and subtract the appropriate
+ number of days/hours/minutes. */
+ location = calendar_config_get_timezone ();
+ zone = icaltimezone_get_builtin_timezone (location);
+ tt = icaltime_current_time_with_zone (zone);
+
+ switch (units) {
+ case CAL_DAYS:
+ icaltime_adjust (&tt, -value, 0, 0, 0);
+ break;
+ case CAL_HOURS:
+ icaltime_adjust (&tt, 0, -value, 0, 0);
+ break;
+ case CAL_MINUTES:
+ icaltime_adjust (&tt, 0, 0, -value, 0);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ t = icaltime_as_timet_with_zone (tt, zone);
+
+ /* Convert the time to an ISO date string, and build
+ the query sub-expression. */
+ isodate = isodate_from_time_t (t);
+ completed_sexp = g_strdup_printf ("(not (completed-before? (make-time \"%s\")))", isodate);
+ free_completed_sexp = TRUE;
+ }
+ }
new_sexp = g_strdup_printf ("(and %s %s %s)", type_sexp,
completed_sexp, sexp);
g_free (type_sexp);
+ if (free_completed_sexp)
+ g_free (completed_sexp);
g_print ("Calendar mode sexp:\n%s\n", new_sexp);
@@ -2188,7 +2271,7 @@ calendar_model_get_component (CalendarModel *model,
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 client. */
+ Note that this doesn't update the component on the server. */
static void
ensure_task_complete (CalComponent *comp,
time_t completed_date)
@@ -2326,3 +2409,20 @@ calendar_model_set_timezone (CalendarModel *model,
e_table_model_changed (E_TABLE_MODEL (model));
}
}
+
+
+/**
+ * calendar_model_refresh:
+ * @model: A calendar model.
+ *
+ * Refreshes the calendar model, reloading the events/tasks from the server.
+ * Be careful about doing this when the user is editing an event/task.
+ **/
+void
+calendar_model_refresh (CalendarModel *model)
+{
+ g_return_if_fail (model != NULL);
+ g_return_if_fail (IS_CALENDAR_MODEL (model));
+
+ update_query (model);
+}
diff --git a/calendar/gui/calendar-model.h b/calendar/gui/calendar-model.h
index 5e1350100d..6bda61f49d 100644
--- a/calendar/gui/calendar-model.h
+++ b/calendar/gui/calendar-model.h
@@ -66,6 +66,8 @@ void calendar_model_set_cal_client (CalendarModel *model,
void calendar_model_set_query (CalendarModel *model,
const char *sexp);
+void calendar_model_refresh (CalendarModel *model);
+
void calendar_model_set_new_comp_vtype (CalendarModel *model,
CalComponentVType vtype);
CalComponentVType calendar_model_get_new_comp_vtype (CalendarModel *model);
diff --git a/calendar/gui/dialogs/cal-prefs-dialog.c b/calendar/gui/dialogs/cal-prefs-dialog.c
index 0b1d14d55e..0b3d43e98b 100644
--- a/calendar/gui/dialogs/cal-prefs-dialog.c
+++ b/calendar/gui/dialogs/cal-prefs-dialog.c
@@ -483,6 +483,7 @@ cal_prefs_dialog_show_config (CalPrefsDialog *prefs)
gint mask, day, week_start_day, time_divisions;
char *zone_name;
icaltimezone *zone;
+ gboolean sensitive;
priv = prefs->priv;
@@ -521,6 +522,11 @@ cal_prefs_dialog_show_config (CalPrefsDialog *prefs)
else
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->use_12_hour), TRUE);
+ sensitive = calendar_config_locale_supports_12_hour_format ();
+ gtk_widget_set_sensitive (priv->use_12_hour, sensitive);
+ gtk_widget_set_sensitive (priv->use_24_hour, sensitive);
+
+
/* Time Divisions. */
time_divisions = calendar_config_get_time_divisions ();
e_dialog_option_menu_set (priv->time_divisions, time_divisions,
diff --git a/calendar/gui/dialogs/task-details-page.c b/calendar/gui/dialogs/task-details-page.c
index ff7223362a..3196994bd1 100644
--- a/calendar/gui/dialogs/task-details-page.c
+++ b/calendar/gui/dialogs/task-details-page.c
@@ -296,6 +296,7 @@ task_details_page_fill_widgets (CompEditorPage *page, CalComponent *comp)
TaskEditorPriority priority;
icalproperty_status status;
const char *url;
+ struct icaltimetype *completed = NULL;
tdpage = TASK_DETAILS_PAGE (page);
priv = tdpage->priv;
@@ -331,6 +332,30 @@ task_details_page_fill_widgets (CompEditorPage *page, CalComponent *comp)
}
e_dialog_option_menu_set (priv->status, status, status_map);
+ /* Completed Date. */
+ cal_component_get_completed (comp, &completed);
+ if (completed) {
+ icaltimezone *utc_zone, *zone;
+ char *location;
+
+ /* Completed is in UTC, but that would confuse the user, so
+ we convert it to local time. */
+ utc_zone = icaltimezone_get_utc_timezone ();
+ location = calendar_config_get_timezone ();
+ zone = icaltimezone_get_builtin_timezone (location);
+
+ icaltimezone_convert_time (completed, utc_zone, zone);
+
+ e_date_edit_set_date (E_DATE_EDIT (priv->completed_date),
+ completed->year, completed->month,
+ completed->day);
+ e_date_edit_set_time_of_day (E_DATE_EDIT (priv->completed_date),
+ completed->hour,
+ completed->minute);
+
+ cal_component_free_icaltimetype (completed);
+ }
+
/* Priority. */
cal_component_get_priority (comp, &priority_value);
if (priority_value) {
@@ -492,6 +517,8 @@ date_changed_cb (EDateEdit *dedit, gpointer data)
if (priv->updating)
return;
+ priv->updating = TRUE;
+
date_set = e_date_edit_get_date (E_DATE_EDIT (priv->completed_date),
&completed_tt.year,
&completed_tt.month,
@@ -499,20 +526,30 @@ date_changed_cb (EDateEdit *dedit, gpointer data)
e_date_edit_get_time_of_day (E_DATE_EDIT (priv->completed_date),
&completed_tt.hour,
&completed_tt.minute);
+
+ status = e_dialog_option_menu_get (priv->status, status_map);
+
if (!date_set) {
completed_tt = icaltime_null_time ();
-
- status = e_dialog_option_menu_get (priv->status, status_map);
if (status == ICAL_STATUS_COMPLETED) {
- e_dialog_option_menu_set (priv->status, ICAL_STATUS_NEEDSACTION, status_map);
+ e_dialog_option_menu_set (priv->status,
+ ICAL_STATUS_NEEDSACTION,
+ status_map);
e_dialog_spin_set (priv->percent_complete, 0);
}
} else {
- e_dialog_option_menu_set (priv->status, ICAL_STATUS_COMPLETED, status_map);
+ if (status != ICAL_STATUS_COMPLETED) {
+ e_dialog_option_menu_set (priv->status,
+ ICAL_STATUS_COMPLETED,
+ status_map);
+ }
e_dialog_spin_set (priv->percent_complete, 100);
}
+ priv->updating = FALSE;
+
/* Notify upstream */
+ dates.complete = &completed_tt;
comp_editor_page_notify_dates_changed (COMP_EDITOR_PAGE (tdpage), &dates);
}
diff --git a/calendar/pcs/cal-backend-file.c b/calendar/pcs/cal-backend-file.c
index 1313b22f12..fd4e3a2cd0 100644
--- a/calendar/pcs/cal-backend-file.c
+++ b/calendar/pcs/cal-backend-file.c
@@ -1499,7 +1499,7 @@ cal_backend_file_update_objects (CalBackend *backend, const char *calobj)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
- icalcomponent *icalcomp, *vcalendar_comp = NULL;
+ icalcomponent *toplevel_comp, *icalcomp = NULL;
icalcomponent_kind kind;
CalComponent *old_comp;
CalComponent *comp;
@@ -1515,29 +1515,22 @@ cal_backend_file_update_objects (CalBackend *backend, const char *calobj)
/* Pull the component from the string and ensure that it is sane */
- fprintf (stderr, "cal_backend_file: Parsing string:\n%s\n", calobj);
- icalcomp = icalparser_parse_string ((char *) calobj);
+ toplevel_comp = icalparser_parse_string ((char *) calobj);
- if (!icalcomp)
+ if (!toplevel_comp)
return FALSE;
- fprintf (stderr, "cal_backend_file: Parsed OK.\n");
-
- kind = icalcomponent_isa (icalcomp);
+ kind = icalcomponent_isa (toplevel_comp);
if (kind == ICAL_VCALENDAR_COMPONENT) {
int num_found = 0;
icalcomponent_kind child_kind;
icalcomponent *subcomp;
- fprintf (stderr, "cal_backend_file: VCALENDAR found\n");
-
/* We have a VCALENDAR containing the VEVENT/VTODO and the
related timezone data, so we have to step through it to
find the actual VEVENT/VTODO component. */
- vcalendar_comp = icalcomp;
-
- subcomp = icalcomponent_get_first_component (vcalendar_comp,
+ subcomp = icalcomponent_get_first_component (toplevel_comp,
ICAL_ANY_COMPONENT);
while (subcomp) {
child_kind = icalcomponent_isa (subcomp);
@@ -1547,28 +1540,30 @@ cal_backend_file_update_objects (CalBackend *backend, const char *calobj)
icalcomp = subcomp;
num_found++;
}
- subcomp = icalcomponent_get_next_component (vcalendar_comp,
+ subcomp = icalcomponent_get_next_component (toplevel_comp,
ICAL_ANY_COMPONENT);
}
/* If we didn't find exactly 1 VEVENT/VTODO it is an error. */
if (num_found != 1) {
- icalcomponent_free (icalcomp);
+ icalcomponent_free (toplevel_comp);
return FALSE;
}
- } else if (!(kind == ICAL_VEVENT_COMPONENT
- || kind == ICAL_VTODO_COMPONENT
- || kind == ICAL_VJOURNAL_COMPONENT)) {
+ } else if (kind == ICAL_VEVENT_COMPONENT
+ || kind == ICAL_VTODO_COMPONENT
+ || kind == ICAL_VJOURNAL_COMPONENT) {
+ icalcomp = toplevel_comp;
+ } else {
/* We don't support this type of component */
- icalcomponent_free (icalcomp);
+ icalcomponent_free (toplevel_comp);
return FALSE;
}
comp = cal_component_new ();
if (!cal_component_set_icalcomponent (comp, icalcomp)) {
gtk_object_unref (GTK_OBJECT (comp));
- icalcomponent_free (icalcomp);
+ icalcomponent_free (toplevel_comp);
return FALSE;
}
@@ -1578,6 +1573,8 @@ cal_backend_file_update_objects (CalBackend *backend, const char *calobj)
if (!comp_uid || !comp_uid[0]) {
gtk_object_unref (GTK_OBJECT (comp));
+ if (kind == ICAL_VCALENDAR_COMPONENT)
+ icalcomponent_free (toplevel_comp);
return FALSE;
}
@@ -1599,7 +1596,7 @@ cal_backend_file_update_objects (CalBackend *backend, const char *calobj)
/* If we have a VCALENDAR component with child VTIMEZONEs and
the VEVENT/VTODO, we have to merge it into the existing
VCALENDAR, resolving any conflicting TZIDs. */
- icalcomponent_merge_component (priv->icalcomp, vcalendar_comp);
+ icalcomponent_merge_component (priv->icalcomp, toplevel_comp);
/* Now we add the component to our local cache, but we pass
FALSE as the last argument, since we have already added
diff --git a/calendar/pcs/query.c b/calendar/pcs/query.c
index 1b991a85ea..3efd2bde50 100644
--- a/calendar/pcs/query.c
+++ b/calendar/pcs/query.c
@@ -830,6 +830,75 @@ func_is_completed (ESExp *esexp, int argc, ESExpResult **argv, void *data)
return result;
}
+/* (completed-before? TIME)
+ *
+ * TIME - time_t
+ *
+ * Returns a boolean indicating whether the component was completed on or
+ * before the given time (i.e. it checks the COMPLETED property).
+ * This is really only useful for TODO components.
+ */
+static ESExpResult *
+func_completed_before (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+{
+ Query *query;
+ QueryPrivate *priv;
+ CalComponent *comp;
+ ESExpResult *result;
+ struct icaltimetype *tt;
+ icaltimezone *zone;
+ gboolean retval = FALSE;
+ time_t before_time, completed_time;
+
+ query = QUERY (data);
+ priv = query->priv;
+
+ g_assert (priv->next_comp != NULL);
+ comp = priv->next_comp;
+
+ /* Check argument types */
+
+ if (argc != 1) {
+ e_sexp_fatal_error (esexp, _("completed-before? expects 1 argument"));
+ return NULL;
+ }
+
+ if (argv[0]->type != ESEXP_RES_TIME) {
+ e_sexp_fatal_error (esexp, _("completed-before? expects argument 1 "
+ "to be a time_t"));
+ return NULL;
+ }
+ before_time = argv[0]->value.time;
+
+ cal_component_get_completed (comp, &tt);
+ if (tt) {
+ /* COMPLETED must be in UTC. */
+ zone = icaltimezone_get_utc_timezone ();
+ completed_time = icaltime_as_timet_with_zone (*tt, zone);
+
+#if 0
+ g_print ("Query Time : %s", ctime (&before_time));
+ g_print ("Completed Time: %s", ctime (&completed_time));
+#endif
+
+ /* We want to return TRUE if before_time is after
+ completed_time. */
+ if (difftime (before_time, completed_time) > 0) {
+#if 0
+ g_print (" Returning TRUE\n");
+#endif
+ retval = TRUE;
+ }
+
+ cal_component_free_icaltimetype (tt);
+ }
+
+ result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
+ result->value.bool = retval;
+
+ return result;
+}
+
/* Adds a component to our the UIDs hash table and notifies the client */
@@ -948,7 +1017,8 @@ static struct {
{ "occur-in-time-range?", func_occur_in_time_range },
{ "contains?", func_contains },
{ "has-categories?", func_has_categories },
- { "is-completed?", func_is_completed }
+ { "is-completed?", func_is_completed },
+ { "completed-before?", func_completed_before }
};
/* Initializes a sexp by interning our own symbols */