aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFederico Mena Quintero <federico@ximian.com>2001-04-13 00:29:56 +0800
committerFederico Mena Quintero <federico@src.gnome.org>2001-04-13 00:29:56 +0800
commit3b562b0b9f81cdd6cedea7c7c53272a98568e63a (patch)
tree16f563e4357fa6268bbd5930e29f5f17a258e81f
parentb1c4145cd9bde65773aa668939e8557986c205c5 (diff)
downloadgsoc2013-evolution-3b562b0b9f81cdd6cedea7c7c53272a98568e63a.tar.gz
gsoc2013-evolution-3b562b0b9f81cdd6cedea7c7c53272a98568e63a.tar.zst
gsoc2013-evolution-3b562b0b9f81cdd6cedea7c7c53272a98568e63a.zip
New function to restart a query for the day view. (query_obj_updated_cb):
2001-04-12 Federico Mena Quintero <federico@ximian.com> * gui/e-day-view.c (update_query): New function to restart a query for the day view. (query_obj_updated_cb): Renamed from obj_updated_cb(); updated for queries instead of calendar clients. (query_obj_removed_cb): Likewise. (cal_opened_cb): Just update_query() instead of queueing reloading all the events. (e_day_view_set_cal_client): Likewise. (e_day_view_set_query): Likewise. (e_day_view_set_selected_time_range): Likewise. (e_day_view_set_days_shown): Likewise. (e_day_view_recalc_work_week): Likewise. (e_day_view_queue_reload_events): Removed function now that events are updated entirely by the query. (e_day_view_reload_events_idle_cb): Likewise. (e_day_view_reload_events): Likewise. (e_day_view_init): Use a pretty arrow instead of GDK_TOP_LEFT_ARROW. * gui/e-week-view.c: Analogous changes to the ones in e-day-view.c. (e_week_view_init): Use a pretty arrow instead of GDK_TOP_LEFT_ARROW. * cal-util/timeutil.c (isodate_from_time_t): Return a g_strdup()ed version of the string instead of a pointer to a static buffer. (time_from_isodate): Resurrected function. Polished up to our current standards of paranoia. * pcs/query.c (func_time_now): New function (time-now). (func_make_time): New function (make-time ISODATE). (func_time_add_day): New function (time-add-day TIME N). (func_time_day_begin): New function (time-day-begin TIME). (func_time_day_end): New function (time-day-end TIME). (func_occur_in_time_range): Use time_t values instead of ints. (match_component): Free the stringized component. Free the ESexp result value. * gui/e-day-view.h: Removed a couple of unused prototypes. * pcs/query.c (query_destroy): Oops, disconnect from the backend. * pcs/cal.c (Cal_get_query): Duplicate the query reference before we return it. * gui/calendar-commands.c (pixmaps): Fixed paths to image files. svn path=/trunk/; revision=9266
-rw-r--r--calendar/ChangeLog46
-rw-r--r--calendar/cal-client/cal-query.c8
-rw-r--r--calendar/cal-util/timeutil.c75
-rw-r--r--calendar/cal-util/timeutil.h1
-rw-r--r--calendar/gui/calendar-commands.c10
-rw-r--r--calendar/gui/e-day-view.c283
-rw-r--r--calendar/gui/e-day-view.h20
-rw-r--r--calendar/gui/e-week-view.c282
-rw-r--r--calendar/gui/e-week-view.h10
-rw-r--r--calendar/pcs/cal.c17
-rw-r--r--calendar/pcs/query.c194
11 files changed, 662 insertions, 284 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog
index 74b9069362..8498890735 100644
--- a/calendar/ChangeLog
+++ b/calendar/ChangeLog
@@ -1,3 +1,49 @@
+2001-04-12 Federico Mena Quintero <federico@ximian.com>
+
+ * gui/e-day-view.c (update_query): New function to restart a query
+ for the day view.
+ (query_obj_updated_cb): Renamed from obj_updated_cb(); updated for
+ queries instead of calendar clients.
+ (query_obj_removed_cb): Likewise.
+ (cal_opened_cb): Just update_query() instead of queueing reloading
+ all the events.
+ (e_day_view_set_cal_client): Likewise.
+ (e_day_view_set_query): Likewise.
+ (e_day_view_set_selected_time_range): Likewise.
+ (e_day_view_set_days_shown): Likewise.
+ (e_day_view_recalc_work_week): Likewise.
+ (e_day_view_queue_reload_events): Removed function now that events
+ are updated entirely by the query.
+ (e_day_view_reload_events_idle_cb): Likewise.
+ (e_day_view_reload_events): Likewise.
+ (e_day_view_init): Use a pretty arrow instead of GDK_TOP_LEFT_ARROW.
+
+ * gui/e-week-view.c: Analogous changes to the ones in e-day-view.c.
+ (e_week_view_init): Use a pretty arrow instead of GDK_TOP_LEFT_ARROW.
+
+ * cal-util/timeutil.c (isodate_from_time_t): Return a g_strdup()ed
+ version of the string instead of a pointer to a static buffer.
+ (time_from_isodate): Resurrected function. Polished up to our
+ current standards of paranoia.
+
+ * pcs/query.c (func_time_now): New function (time-now).
+ (func_make_time): New function (make-time ISODATE).
+ (func_time_add_day): New function (time-add-day TIME N).
+ (func_time_day_begin): New function (time-day-begin TIME).
+ (func_time_day_end): New function (time-day-end TIME).
+ (func_occur_in_time_range): Use time_t values instead of ints.
+ (match_component): Free the stringized component. Free the ESexp
+ result value.
+
+ * gui/e-day-view.h: Removed a couple of unused prototypes.
+
+ * pcs/query.c (query_destroy): Oops, disconnect from the backend.
+
+ * pcs/cal.c (Cal_get_query): Duplicate the query reference before
+ we return it.
+
+ * gui/calendar-commands.c (pixmaps): Fixed paths to image files.
+
2001-04-11 JP Rosevear <jpr@ximian.com>
* pcs/cal-backend-file.c (cal_backend_file_compute_changes):
diff --git a/calendar/cal-client/cal-query.c b/calendar/cal-client/cal-query.c
index 1a3fd241f9..727a2dcb3b 100644
--- a/calendar/cal-client/cal-query.c
+++ b/calendar/cal-client/cal-query.c
@@ -207,7 +207,7 @@ cal_query_destroy (GtkObject *object)
/* Marshalers */
-typedef void (* ObjUpdatedFunc) (QueryListener *ql, const char *uid,
+typedef void (* ObjUpdatedFunc) (CalQuery *query, const char *uid,
gboolean query_in_progress, int n_scanned, int total,
gpointer data);
@@ -218,12 +218,12 @@ marshal_obj_updated (GtkObject *object, GtkSignalFunc func, gpointer func_data,
f = (ObjUpdatedFunc) func;
- (* f) (QUERY_LISTENER (object), GTK_VALUE_STRING (args[0]),
+ (* f) (CAL_QUERY (object), GTK_VALUE_STRING (args[0]),
GTK_VALUE_BOOL (args[1]), GTK_VALUE_INT (args[2]), GTK_VALUE_INT (args[3]),
func_data);
}
-typedef void (* QueryDoneFunc) (QueryListener *ql, CalQueryDoneStatus status, const char *error_str,
+typedef void (* QueryDoneFunc) (CalQuery *query, CalQueryDoneStatus status, const char *error_str,
gpointer data);
static void
@@ -233,7 +233,7 @@ marshal_query_done (GtkObject *object, GtkSignalFunc func, gpointer func_data, G
f = (QueryDoneFunc) func;
- (* f) (QUERY_LISTENER (object), GTK_VALUE_ENUM (args[0]), GTK_VALUE_STRING (args[1]),
+ (* f) (CAL_QUERY (object), GTK_VALUE_ENUM (args[0]), GTK_VALUE_STRING (args[1]),
func_data);
}
diff --git a/calendar/cal-util/timeutil.c b/calendar/cal-util/timeutil.c
index b48a02b5fa..2d769623aa 100644
--- a/calendar/cal-util/timeutil.c
+++ b/calendar/cal-util/timeutil.c
@@ -9,6 +9,7 @@
*/
#include <string.h>
+#include <ctype.h>
#include <glib.h>
#include "timeutil.h"
@@ -24,15 +25,85 @@ print_time_t (time_t t)
tm->tm_hour, tm->tm_min, tm->tm_sec);
}
+/**
+ * isodate_from_time_t:
+ * @t: A time value.
+ *
+ * Creates an ISO 8601 local time representation from a time value.
+ *
+ * Return value: String with the ISO 8601 representation of the local time.
+ **/
char *
isodate_from_time_t (time_t t)
{
struct tm *tm;
- static char isotime [40];
+ char isotime[40];
tm = localtime (&t);
strftime (isotime, sizeof (isotime)-1, "%Y%m%dT%H%M%S", tm);
- return isotime;
+ return g_strdup (isotime);
+}
+
+/**
+ * time_from_isodate:
+ * @str: Date/time value in ISO 8601 format.
+ *
+ * Converts an ISO 8601 time string into a time_t value.
+ *
+ * Return value: Time_t corresponding to the specified ISO string.
+ **/
+time_t
+time_from_isodate (const char *str)
+{
+ int len;
+ struct tm my_tm;
+ time_t t;
+ int i;
+
+ g_return_val_if_fail (str != NULL, -1);
+
+ /* yyyymmdd[Thhmmss[Z]] */
+
+ len = strlen (str);
+
+ if (!(len == 8 || len == 15 || len == 16))
+ return -1;
+
+ for (i = 0; i < len; i++)
+ if (!((i != 8 && i != 15 && isdigit (str[i]))
+ || (i == 8 && str[i] == 'T')
+ || (i == 15 && str[i] == 'Z')))
+ return -1;
+
+ memset (&my_tm, 0, sizeof (my_tm));
+
+#define digit_at(x,y) (x[y] - '0')
+
+ my_tm.tm_year = (digit_at (str, 0) * 1000 + digit_at (str, 1) * 100 +
+ digit_at (str, 2) * 10 + digit_at (str, 3)) - 1900;
+
+ my_tm.tm_mon = digit_at (str, 4) * 10 + digit_at (str, 5) - 1;
+ my_tm.tm_mday = digit_at (str, 6) * 10 + digit_at (str, 7);
+
+ if (len > 8) {
+ my_tm.tm_hour = digit_at (str, 9) * 10 + digit_at (str, 10);
+ my_tm.tm_min = digit_at (str, 11) * 10 + digit_at (str, 12);
+ my_tm.tm_sec = digit_at (str, 13) * 10 + digit_at (str, 14);
+ }
+
+ my_tm.tm_isdst = -1;
+
+ t = mktime (&my_tm);
+
+ if (len == 16) {
+#if defined(HAVE_TM_GMTOFF)
+ t -= my_tm.tm_gmtoff;
+#elsif defined(HAVE_TIMEZONE)
+ t -= timezone;
+#endif
+ }
+
+ return t;
}
time_t
diff --git a/calendar/cal-util/timeutil.h b/calendar/cal-util/timeutil.h
index 730c7dc089..04f1ca4867 100644
--- a/calendar/cal-util/timeutil.h
+++ b/calendar/cal-util/timeutil.h
@@ -17,6 +17,7 @@
char *isodate_from_time_t (time_t t);
+time_t time_from_isodate (const char *str);
time_t time_add_minutes (time_t time, int minutes);
time_t time_add_day (time_t time, int days);
diff --git a/calendar/gui/calendar-commands.c b/calendar/gui/calendar-commands.c
index d31d252dfd..3556554d82 100644
--- a/calendar/gui/calendar-commands.c
+++ b/calendar/gui/calendar-commands.c
@@ -387,12 +387,12 @@ static EPixmap pixmaps [] =
E_PIXMAP ("/menu/File/Print/Print Preview", "print-preview.xpm"),
E_PIXMAP ("/menu/Actions/Component/CalendarNew", "new_appointment.xpm"),
E_PIXMAP ("/menu/Tools/Component/CalendarPreferences", "configure_16_calendar.xpm"),
- E_PIXMAP ("/Toolbar/New", "buttons/new_appointment.png"),
- E_PIXMAP ("/Toolbar/DayView", "buttons/dayview.xpm"),
- E_PIXMAP ("/Toolbar/WorkWeekView", "buttons/workweekview.xpm"),
- E_PIXMAP ("/Toolbar/WeekView", "buttons/weekview.xpm"),
- E_PIXMAP ("/Toolbar/MonthView", "buttons/monthview.xpm"),
+ E_PIXMAP ("/Toolbar/New", "buttons/new_appointment.png"),
+ E_PIXMAP ("/Toolbar/DayView", "buttons/dayview.xpm"),
+ E_PIXMAP ("/Toolbar/WorkWeekView", "buttons/workweekview.xpm"),
+ E_PIXMAP ("/Toolbar/WeekView", "buttons/weekview.xpm"),
+ E_PIXMAP ("/Toolbar/MonthView", "buttons/monthview.xpm"),
E_PIXMAP_END
};
diff --git a/calendar/gui/e-day-view.c b/calendar/gui/e-day-view.c
index 828eff3419..b10382a3ea 100644
--- a/calendar/gui/e-day-view.c
+++ b/calendar/gui/e-day-view.c
@@ -253,9 +253,6 @@ static void e_day_view_foreach_event_with_uid (EDayView *day_view,
EDayViewForeachEventCallback callback,
gpointer data);
-static void e_day_view_queue_reload_events (EDayView *day_view);
-static gboolean e_day_view_reload_events_idle_cb (gpointer data);
-static void e_day_view_reload_events (EDayView *day_view);
static void e_day_view_free_events (EDayView *day_view);
static void e_day_view_free_event_array (EDayView *day_view,
GArray *array);
@@ -488,13 +485,14 @@ e_day_view_init (EDayView *day_view)
day_view->calendar = NULL;
day_view->client = NULL;
+ day_view->sexp = g_strdup ("#t"); /* match all by default */
+ day_view->query = NULL;
day_view->long_events = g_array_new (FALSE, FALSE,
sizeof (EDayViewEvent));
day_view->long_events_sorted = TRUE;
day_view->long_events_need_layout = FALSE;
day_view->long_events_need_reshape = FALSE;
- day_view->reload_events_idle_id = 0;
for (day = 0; day < E_DAY_VIEW_MAX_DAYS; day++) {
day_view->events[day] = g_array_new (FALSE, FALSE,
@@ -794,7 +792,7 @@ e_day_view_init (EDayView *day_view)
/* Create the cursors. */
- day_view->normal_cursor = gdk_cursor_new (GDK_TOP_LEFT_ARROW);
+ day_view->normal_cursor = gdk_cursor_new (GDK_LEFT_PTR);
day_view->move_cursor = gdk_cursor_new (GDK_FLEUR);
day_view->resize_width_cursor = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
day_view->resize_height_cursor = gdk_cursor_new (GDK_SB_V_DOUBLE_ARROW);
@@ -851,17 +849,23 @@ e_day_view_destroy (GtkObject *object)
e_day_view_stop_auto_scroll (day_view);
- if (day_view->reload_events_idle_id != 0) {
- g_source_remove (day_view->reload_events_idle_id);
- day_view->reload_events_idle_id = 0;
- }
-
if (day_view->client) {
gtk_signal_disconnect_by_data (GTK_OBJECT (day_view->client), day_view);
gtk_object_unref (GTK_OBJECT (day_view->client));
day_view->client = NULL;
}
+ if (day_view->sexp) {
+ g_free (day_view->sexp);
+ day_view->sexp = NULL;
+ }
+
+ if (day_view->query) {
+ gtk_signal_disconnect_by_data (GTK_OBJECT (day_view->query), day_view);
+ gtk_object_unref (GTK_OBJECT (day_view->query));
+ day_view->query = NULL;
+ }
+
if (day_view->large_font)
gdk_font_unref (day_view->large_font);
@@ -1372,23 +1376,11 @@ e_day_view_set_calendar (EDayView *day_view,
}
-/* Callback used when the calendar client finishes opening */
-static void
-cal_opened_cb (CalClient *client, CalClientOpenStatus status, gpointer data)
-{
- EDayView *day_view;
-
- day_view = E_DAY_VIEW (data);
-
- if (status != CAL_CLIENT_OPEN_SUCCESS)
- return;
-
- e_day_view_queue_reload_events (day_view);
-}
-
-/* Callback used when the calendar client tells us that an object changed */
+/* Callback used when a component is updated in the live query */
static void
-obj_updated_cb (CalClient *client, const char *uid, gpointer data)
+query_obj_updated_cb (CalQuery *query, const char *uid,
+ gboolean query_in_progress, int n_scanned, int total,
+ gpointer data)
{
EDayView *day_view;
EDayViewEvent *event;
@@ -1396,13 +1388,8 @@ obj_updated_cb (CalClient *client, const char *uid, gpointer data)
CalClientGetStatus status;
gint day, event_num;
- g_return_if_fail (E_IS_DAY_VIEW (data));
-
day_view = E_DAY_VIEW (data);
- /* Sanity check. */
- g_return_if_fail (client == day_view->client);
-
/* If our time hasn't been set yet, just return. */
if (day_view->lower == 0 && day_view->upper == 0)
return;
@@ -1416,7 +1403,7 @@ obj_updated_cb (CalClient *client, const char *uid, gpointer data)
break;
case CAL_CLIENT_GET_SYNTAX_ERROR:
- g_message ("obj_updated_cb(): Syntax error when getting object `%s'", uid);
+ g_message ("query_obj_updated_cb(): Syntax error when getting object `%s'", uid);
return;
case CAL_CLIENT_GET_NOT_FOUND:
@@ -1428,12 +1415,6 @@ obj_updated_cb (CalClient *client, const char *uid, gpointer data)
return;
}
- /* We only care about events. */
- if (cal_component_get_vtype (comp) != CAL_COMPONENT_EVENT) {
- gtk_object_unref (GTK_OBJECT (comp));
- return;
- }
-
/* If the event already exists and the dates didn't change, we can
update the event fairly easily without changing the events arrays
or computing a new layout. */
@@ -1481,10 +1462,9 @@ obj_updated_cb (CalClient *client, const char *uid, gpointer data)
gtk_widget_queue_draw (day_view->main_canvas);
}
-
-/* Callback used when the calendar client tells us that an object was removed */
+/* Callback used when a component is removed from the live query */
static void
-obj_removed_cb (CalClient *client, const char *uid, gpointer data)
+query_obj_removed_cb (CalQuery *query, const char *uid, gpointer data)
{
EDayView *day_view;
@@ -1498,6 +1478,117 @@ obj_removed_cb (CalClient *client, const char *uid, gpointer data)
gtk_widget_queue_draw (day_view->main_canvas);
}
+/* Callback used when a query ends */
+static void
+query_query_done_cb (CalQuery *query, CalQueryDoneStatus status, const char *error_str, gpointer data)
+{
+ EDayView *day_view;
+
+ day_view = E_DAY_VIEW (data);
+
+ /* FIXME */
+
+ if (status != CAL_QUERY_DONE_SUCCESS)
+ fprintf (stderr, "query done: %s\n", error_str);
+}
+
+/* Callback used when an evaluation error occurs when running a query */
+static void
+query_eval_error_cb (CalQuery *query, const char *error_str, gpointer data)
+{
+ EDayView *day_view;
+
+ day_view = E_DAY_VIEW (data);
+
+ /* FIXME */
+
+ fprintf (stderr, "eval error: %s\n", error_str);
+}
+
+
+/* Builds a complete query sexp for the day view by adding the predicates to
+ * filter only for VEVENTS that fit in the day view's time range.
+ */
+static char *
+adjust_query_sexp (EDayView *day_view, const char *sexp)
+{
+ char *start, *end;
+ char *new_sexp;
+
+ /* If the dates have not been set yet, we just want an empty query. */
+ if (day_view->lower == 0 || day_view->upper == 0)
+ return g_strdup ("#f");
+
+ start = isodate_from_time_t (day_view->lower);
+ end = isodate_from_time_t (day_view->upper);
+
+ new_sexp = g_strdup_printf ("(and (= (get-vtype) \"VEVENT\")"
+ " (occur-in-time-range? (make-time \"%s\")"
+ " (make-time \"%s\"))"
+ " %s)",
+ start, end,
+ sexp);
+
+ g_free (start);
+ g_free (end);
+
+ return new_sexp;
+}
+
+
+/* Restarts a query for the day view */
+static void
+update_query (EDayView *day_view)
+{
+ char *real_sexp;
+
+ e_day_view_free_events (day_view);
+ gtk_widget_queue_draw (day_view->top_canvas);
+ gtk_widget_queue_draw (day_view->main_canvas);
+
+ if (!(day_view->client
+ && cal_client_get_load_state (day_view->client) == CAL_CLIENT_LOAD_LOADED))
+ return;
+
+ if (day_view->query) {
+ gtk_signal_disconnect_by_data (GTK_OBJECT (day_view->query), day_view);
+ gtk_object_unref (GTK_OBJECT (day_view->query));
+ }
+
+ g_assert (day_view->sexp != NULL);
+ real_sexp = adjust_query_sexp (day_view, day_view->sexp);
+
+ day_view->query = cal_client_get_query (day_view->client, real_sexp);
+ g_free (real_sexp);
+
+ if (!day_view->query) {
+ g_message ("update_query(): Could not create the query");
+ return;
+ }
+
+ gtk_signal_connect (GTK_OBJECT (day_view->query), "obj_updated",
+ GTK_SIGNAL_FUNC (query_obj_updated_cb), day_view);
+ gtk_signal_connect (GTK_OBJECT (day_view->query), "obj_removed",
+ GTK_SIGNAL_FUNC (query_obj_removed_cb), day_view);
+ gtk_signal_connect (GTK_OBJECT (day_view->query), "query_done",
+ GTK_SIGNAL_FUNC (query_query_done_cb), day_view);
+ gtk_signal_connect (GTK_OBJECT (day_view->query), "eval_error",
+ GTK_SIGNAL_FUNC (query_eval_error_cb), day_view);
+}
+
+/* Callback used when the calendar client finishes opening */
+static void
+cal_opened_cb (CalClient *client, CalClientOpenStatus status, gpointer data)
+{
+ EDayView *day_view;
+
+ day_view = E_DAY_VIEW (data);
+
+ if (status != CAL_CLIENT_OPEN_SUCCESS)
+ return;
+
+ update_query (day_view);
+}
/**
* e_day_view_set_cal_client:
@@ -1530,17 +1621,35 @@ e_day_view_set_cal_client (EDayView *day_view,
day_view->client = client;
if (day_view->client) {
- if (cal_client_get_load_state (day_view->client) != CAL_CLIENT_LOAD_LOADED)
+ if (cal_client_get_load_state (day_view->client) == CAL_CLIENT_LOAD_LOADED)
+ update_query (day_view);
+ else
gtk_signal_connect (GTK_OBJECT (day_view->client), "cal_opened",
GTK_SIGNAL_FUNC (cal_opened_cb), day_view);
-
- gtk_signal_connect (GTK_OBJECT (day_view->client), "obj_updated",
- GTK_SIGNAL_FUNC (obj_updated_cb), day_view);
- gtk_signal_connect (GTK_OBJECT (day_view->client), "obj_removed",
- GTK_SIGNAL_FUNC (obj_removed_cb), day_view);
}
+}
- e_day_view_queue_reload_events (day_view);
+/**
+ * e_day_view_set_query:
+ * @day_view: A day view.
+ * @sexp: S-expression that defines the query.
+ *
+ * Sets the query sexp that the day view will use for filtering the displayed
+ * events.
+ **/
+void
+e_day_view_set_query (EDayView *day_view, const char *sexp)
+{
+ g_return_if_fail (day_view != NULL);
+ g_return_if_fail (E_IS_DAY_VIEW (day_view));
+ g_return_if_fail (sexp != NULL);
+
+ if (day_view->sexp)
+ g_free (day_view->sexp);
+
+ day_view->sexp = g_strdup (sexp);
+
+ update_query (day_view);
}
@@ -1943,7 +2052,7 @@ e_day_view_set_selected_time_range (EDayView *day_view,
/* See if we need to change the days shown. */
if (lower != day_view->lower) {
e_day_view_recalc_day_starts (day_view, lower);
- e_day_view_queue_reload_events (day_view);
+ update_query (day_view);
}
/* Set the selection. */
@@ -2140,7 +2249,8 @@ e_day_view_set_days_shown (EDayView *day_view,
e_day_view_recalc_day_starts (day_view, day_view->lower);
e_day_view_recalc_cell_sizes (day_view);
- e_day_view_queue_reload_events (day_view);
+
+ update_query (day_view);
}
@@ -2419,7 +2529,7 @@ e_day_view_recalc_work_week (EDayView *day_view)
day_view->selection_start_day = -1;
e_day_view_recalc_day_starts (day_view, lower);
- e_day_view_queue_reload_events (day_view);
+ update_query (day_view);
/* This updates the date navigator. */
e_day_view_update_calendar_selection_time (day_view);
@@ -3927,77 +4037,6 @@ e_day_view_abort_resize (EDayView *day_view,
}
-/* This frees any events currently loaded, and queues a reload. */
-static void
-e_day_view_queue_reload_events (EDayView *day_view)
-{
- e_day_view_free_events (day_view);
-
- if (day_view->reload_events_idle_id == 0) {
- /* We'll use a high idle priority here, so the events are
- reloaded before the canvas is updated. */
- day_view->reload_events_idle_id = g_idle_add_full
- (G_PRIORITY_HIGH_IDLE,
- e_day_view_reload_events_idle_cb, day_view, NULL);
- }
-}
-
-
-static gboolean
-e_day_view_reload_events_idle_cb (gpointer data)
-{
- EDayView *day_view;
-
- g_return_val_if_fail (E_IS_DAY_VIEW (data), FALSE);
-
- GDK_THREADS_ENTER ();
-
- day_view = E_DAY_VIEW (data);
-
- day_view->reload_events_idle_id = 0;
-
- e_day_view_reload_events (day_view);
-
- GDK_THREADS_LEAVE ();
- return FALSE;
-}
-
-
-static void
-e_day_view_reload_events (EDayView *day_view)
-{
- e_day_view_free_events (day_view);
-
- if (!(day_view->client
- && cal_client_get_load_state (day_view->client) == CAL_CLIENT_LOAD_LOADED))
- return;
-
- /* If both lower & upper are 0, then the time range hasn't been set,
- so we don't try to load any events. */
- if (day_view->lower != 0 || day_view->upper != 0) {
-#if 0
- g_print ("EDayView (%s) generating instances\n",
- day_view->work_week_view ? "Work Week" : "1 Day View");
-#endif
- cal_client_generate_instances (day_view->client,
- CALOBJ_TYPE_EVENT,
- day_view->lower,
- day_view->upper,
- e_day_view_add_event,
- day_view);
- }
-
- /* We need to do this to make sure the top canvas is resized. */
- day_view->long_events_need_layout = TRUE;
-
- e_day_view_check_layout (day_view);
- e_day_view_reshape_main_canvas_resize_bars (day_view);
-
- gtk_widget_queue_draw (day_view->top_canvas);
- gtk_widget_queue_draw (day_view->main_canvas);
-}
-
-
static void
e_day_view_free_events (EDayView *day_view)
{
diff --git a/calendar/gui/e-day-view.h b/calendar/gui/e-day-view.h
index 2379a76b87..18f8187951 100644
--- a/calendar/gui/e-day-view.h
+++ b/calendar/gui/e-day-view.h
@@ -235,6 +235,10 @@ struct _EDayView
/* Calendar client object we are monitoring */
CalClient *client;
+ /* S-expression for query and the query object */
+ char *sexp;
+ CalQuery *query;
+
/* The start and end of the days shown. */
time_t lower;
time_t upper;
@@ -270,9 +274,6 @@ struct _EDayView
gboolean long_events_need_reshape;
gboolean need_reshape[E_DAY_VIEW_MAX_DAYS];
- /* The id of our idle function to reload all events. */
- gint reload_events_idle_id;
-
/* The number of minutes per row. 5, 10, 15, 30 or 60. */
gint mins_per_row;
@@ -488,6 +489,9 @@ void e_day_view_set_calendar (EDayView *day_view,
void e_day_view_set_cal_client (EDayView *day_view,
CalClient *client);
+void e_day_view_set_query (EDayView *day_view,
+ const char *sexp);
+
/* This sets the selected time range. The EDayView will show the day or week
corresponding to the start time. If the start_time & end_time are not equal
and are both visible in the view, then the selection is set to those times,
@@ -501,16 +505,6 @@ void e_day_view_get_selected_time_range (EDayView *day_view,
time_t *start_time,
time_t *end_time);
-/* This is called when one event has been added or updated. */
-void e_day_view_update_event (EDayView *day_view,
- const gchar *uid);
-
-/* This removes all the events associated with the given uid. Note that for
- recurring events there may be more than one. If any events are found and
- removed we need to layout the events again. */
-void e_day_view_remove_event (EDayView *day_view,
- const gchar *uid);
-
/* Whether we are displaying a work-week, in which case the display always
starts on the first day of the working week. */
gboolean e_day_view_get_work_week_view (EDayView *day_view);
diff --git a/calendar/gui/e-week-view.c b/calendar/gui/e-week-view.c
index 90a7b2c695..c06b568d9d 100644
--- a/calendar/gui/e-week-view.c
+++ b/calendar/gui/e-week-view.c
@@ -109,9 +109,6 @@ static gint e_week_view_convert_position_to_day (EWeekView *week_view,
static void e_week_view_update_selection (EWeekView *week_view,
gint day);
-static void e_week_view_queue_reload_events (EWeekView *week_view);
-static gboolean e_week_view_reload_events_idle_cb (gpointer data);
-static void e_week_view_reload_events (EWeekView *week_view);
static void e_week_view_free_events (EWeekView *week_view);
static gboolean e_week_view_add_event (CalComponent *comp,
time_t start,
@@ -257,13 +254,14 @@ e_week_view_init (EWeekView *week_view)
week_view->calendar = NULL;
week_view->client = NULL;
+ week_view->sexp = g_strdup ("#t"); /* match all by default */
+ week_view->query = NULL;
week_view->events = g_array_new (FALSE, FALSE,
sizeof (EWeekViewEvent));
week_view->events_sorted = TRUE;
week_view->events_need_layout = FALSE;
week_view->events_need_reshape = FALSE;
- week_view->reload_events_idle_id = 0;
week_view->spans = NULL;
@@ -383,7 +381,7 @@ e_week_view_init (EWeekView *week_view)
/* Create the cursors. */
- week_view->normal_cursor = gdk_cursor_new (GDK_TOP_LEFT_ARROW);
+ week_view->normal_cursor = gdk_cursor_new (GDK_LEFT_PTR);
week_view->move_cursor = gdk_cursor_new (GDK_FLEUR);
week_view->resize_width_cursor = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
week_view->last_cursor_set = NULL;
@@ -416,17 +414,23 @@ e_week_view_destroy (GtkObject *object)
e_week_view_free_events (week_view);
- if (week_view->reload_events_idle_id != 0) {
- g_source_remove (week_view->reload_events_idle_id);
- week_view->reload_events_idle_id = 0;
- }
-
if (week_view->client) {
gtk_signal_disconnect_by_data (GTK_OBJECT (week_view->client), week_view);
gtk_object_unref (GTK_OBJECT (week_view->client));
week_view->client = NULL;
}
+ if (week_view->sexp) {
+ g_free (week_view->sexp);
+ week_view->sexp = NULL;
+ }
+
+ if (week_view->query) {
+ gtk_signal_disconnect_by_data (GTK_OBJECT (week_view->query), week_view);
+ gtk_object_unref (GTK_OBJECT (week_view->query));
+ week_view->query = NULL;
+ }
+
if (week_view->small_font)
gdk_font_unref (week_view->small_font);
@@ -880,23 +884,11 @@ e_week_view_set_calendar (EWeekView *week_view,
}
-/* Callback used when the calendar client finishes opening */
-static void
-cal_opened_cb (CalClient *client, CalClientOpenStatus status, gpointer data)
-{
- EWeekView *week_view;
-
- week_view = E_WEEK_VIEW (data);
-
- if (status != CAL_CLIENT_OPEN_SUCCESS)
- return;
-
- e_week_view_queue_reload_events (week_view);
-}
-
-/* Callback used when the calendar client tells us that an object changed */
+/* Callback used when a component is updated in the live query */
static void
-obj_updated_cb (CalClient *client, const char *uid, gpointer data)
+query_obj_updated_cb (CalQuery *query, const char *uid,
+ gboolean query_in_progress, int n_scanned, int total,
+ gpointer data)
{
EWeekView *week_view;
EWeekViewEvent *event;
@@ -906,9 +898,6 @@ obj_updated_cb (CalClient *client, const char *uid, gpointer data)
week_view = E_WEEK_VIEW (data);
- /* Sanity check. */
- g_return_if_fail (client == week_view->client);
-
/* If we don't have a valid date set yet, just return. */
if (!g_date_valid (&week_view->first_day_shown))
return;
@@ -930,12 +919,6 @@ obj_updated_cb (CalClient *client, const char *uid, gpointer data)
return;
}
- /* We only care about events. */
- if (cal_component_get_vtype (comp) != CAL_COMPONENT_EVENT) {
- gtk_object_unref (GTK_OBJECT (comp));
- return;
- }
-
/* If the event already exists and the dates didn't change, we can
update the event fairly easily without changing the events arrays
or computing a new layout. */
@@ -981,9 +964,9 @@ obj_updated_cb (CalClient *client, const char *uid, gpointer data)
gtk_widget_queue_draw (week_view->main_canvas);
}
-/* Callback used when the calendar client tells us that an object was removed */
+/* Callback used when a component is removed from the live query */
static void
-obj_removed_cb (CalClient *client, const char *uid, gpointer data)
+query_obj_removed_cb (CalClient *client, const char *uid, gpointer data)
{
EWeekView *week_view;
@@ -996,6 +979,117 @@ obj_removed_cb (CalClient *client, const char *uid, gpointer data)
gtk_widget_queue_draw (week_view->main_canvas);
}
+/* Callback used when a query ends */
+static void
+query_query_done_cb (CalQuery *query, CalQueryDoneStatus status, const char *error_str, gpointer data)
+{
+ EWeekView *week_view;
+
+ week_view = E_WEEK_VIEW (data);
+
+ /* FIXME */
+
+ if (status != CAL_QUERY_DONE_SUCCESS)
+ fprintf (stderr, "query done: %s\n", error_str);
+}
+
+/* Callback used when an evaluation error occurs when running a query */
+static void
+query_eval_error_cb (CalQuery *query, const char *error_str, gpointer data)
+{
+ EWeekView *week_view;
+
+ week_view = E_WEEK_VIEW (data);
+
+ /* FIXME */
+
+ fprintf (stderr, "eval error: %s\n", error_str);
+}
+
+/* Builds a complete query sexp for the week view by adding the predicates to
+ * filter only for VEVENTS that fit in the week view's time range.
+ */
+static char *
+adjust_query_sexp (EWeekView *week_view, const char *sexp)
+{
+ int num_days;
+ char *start, *end;
+ char *new_sexp;
+
+ /* If the dates have not been set yet, we just want an empty query. */
+ if (!g_date_valid (&week_view->first_day_shown))
+ return g_strdup ("#f");
+
+ num_days = week_view->multi_week_view ? week_view->weeks_shown * 7 : 7;
+
+ start = isodate_from_time_t (week_view->day_starts[0]);
+ end = isodate_from_time_t (week_view->day_starts[num_days]);
+
+ new_sexp = g_strdup_printf ("(and (= (get-vtype) \"VEVENT\")"
+ " (occur-in-time-range? (make-time \"%s\")"
+ " (make-time \"%s\"))"
+ " %s)",
+ start, end,
+ sexp);
+
+ g_free (start);
+ g_free (end);
+
+ return new_sexp;
+}
+
+/* Restarts a query for the week view */
+static void
+update_query (EWeekView *week_view)
+{
+ char *real_sexp;
+
+ e_week_view_free_events (week_view);
+ gtk_widget_queue_draw (week_view->main_canvas);
+
+ if (!(week_view->client
+ && cal_client_get_load_state (week_view->client) == CAL_CLIENT_LOAD_LOADED))
+ return;
+
+ if (week_view->query) {
+ gtk_signal_disconnect_by_data (GTK_OBJECT (week_view->query), week_view);
+ gtk_object_unref (GTK_OBJECT (week_view->query));
+ }
+
+ g_assert (week_view->sexp != NULL);
+ real_sexp = adjust_query_sexp (week_view, week_view->sexp);
+
+ week_view->query = cal_client_get_query (week_view->client, real_sexp);
+ g_free (real_sexp);
+
+ if (!week_view->query) {
+ g_message ("update_query(): Could not create the query");
+ return;
+ }
+
+ gtk_signal_connect (GTK_OBJECT (week_view->query), "obj_updated",
+ GTK_SIGNAL_FUNC (query_obj_updated_cb), week_view);
+ gtk_signal_connect (GTK_OBJECT (week_view->query), "obj_removed",
+ GTK_SIGNAL_FUNC (query_obj_removed_cb), week_view);
+ gtk_signal_connect (GTK_OBJECT (week_view->query), "query_done",
+ GTK_SIGNAL_FUNC (query_query_done_cb), week_view);
+ gtk_signal_connect (GTK_OBJECT (week_view->query), "eval_error",
+ GTK_SIGNAL_FUNC (query_eval_error_cb), week_view);
+}
+
+/* Callback used when the calendar client finishes opening */
+static void
+cal_opened_cb (CalClient *client, CalClientOpenStatus status, gpointer data)
+{
+ EWeekView *week_view;
+
+ week_view = E_WEEK_VIEW (data);
+
+ if (status != CAL_CLIENT_OPEN_SUCCESS)
+ return;
+
+ update_query (week_view);
+}
/**
* e_week_view_set_cal_client:
@@ -1028,17 +1122,35 @@ e_week_view_set_cal_client (EWeekView *week_view,
week_view->client = client;
if (week_view->client) {
- if (cal_client_get_load_state (week_view->client) != CAL_CLIENT_LOAD_LOADED)
+ if (cal_client_get_load_state (week_view->client) == CAL_CLIENT_LOAD_LOADED)
+ update_query (week_view);
+ else
gtk_signal_connect (GTK_OBJECT (week_view->client), "cal_opened",
GTK_SIGNAL_FUNC (cal_opened_cb), week_view);
-
- gtk_signal_connect (GTK_OBJECT (week_view->client), "obj_updated",
- GTK_SIGNAL_FUNC (obj_updated_cb), week_view);
- gtk_signal_connect (GTK_OBJECT (week_view->client), "obj_removed",
- GTK_SIGNAL_FUNC (obj_removed_cb), week_view);
}
+}
+
+/**
+ * e_week_view_set_query:
+ * @week_view: A week view.
+ * @sexp: S-expression that defines the query.
+ *
+ * Sets the query sexp that the week view will use for filtering the displayed
+ * events.
+ **/
+void
+e_week_view_set_query (EWeekView *week_view, const char *sexp)
+{
+ g_return_if_fail (week_view != NULL);
+ g_return_if_fail (E_IS_WEEK_VIEW (week_view));
+ g_return_if_fail (sexp != NULL);
+
+ if (week_view->sexp)
+ g_free (week_view->sexp);
- e_week_view_queue_reload_events (week_view);
+ week_view->sexp = g_strdup (sexp);
+
+ update_query (week_view);
}
@@ -1108,7 +1220,7 @@ e_week_view_set_selected_time_range (EWeekView *week_view,
start_time = time_add_day (start_time, -day_offset);
start_time = time_day_begin (start_time);
e_week_view_recalc_day_starts (week_view, start_time);
- e_week_view_queue_reload_events (week_view);
+ update_query (week_view);
}
/* Set the selection to the given days. */
@@ -1139,7 +1251,6 @@ e_week_view_set_selected_time_range (EWeekView *week_view,
if (update_adjustment_value)
gtk_adjustment_set_value (GTK_RANGE (week_view->vscrollbar)->adjustment, 0);
-
gtk_widget_queue_draw (week_view->main_canvas);
}
@@ -1227,7 +1338,7 @@ e_week_view_set_first_day_shown (EWeekView *week_view,
g_date_to_struct_tm (&base_date, &start_tm);
start_time = mktime (&start_tm);
e_week_view_recalc_day_starts (week_view, start_time);
- e_week_view_queue_reload_events (week_view);
+ update_query (week_view);
}
/* Try to keep the previous selection, but if it is no longer shown
@@ -1256,7 +1367,6 @@ e_week_view_set_first_day_shown (EWeekView *week_view,
if (update_adjustment_value)
gtk_adjustment_set_value (GTK_RANGE (week_view->vscrollbar)->adjustment, 0);
-
gtk_widget_queue_draw (week_view->main_canvas);
}
@@ -1364,8 +1474,7 @@ e_week_view_set_weeks_shown (EWeekView *week_view,
if (g_date_valid (&week_view->first_day_shown))
e_week_view_set_first_day_shown (week_view, &week_view->first_day_shown);
- /* Make sure the events are reloaded. */
- e_week_view_queue_reload_events (week_view);
+ update_query (week_view);
}
}
@@ -2019,77 +2128,6 @@ e_week_view_update_selection (EWeekView *week_view,
}
-/* This frees any events currently loaded, and queues a reload. */
-static void
-e_week_view_queue_reload_events (EWeekView *week_view)
-{
- e_week_view_free_events (week_view);
-
- if (week_view->reload_events_idle_id == 0) {
- /* We'll use a low priority here, so the user can scroll
- the view quickly. */
- week_view->reload_events_idle_id = g_idle_add_full
- (G_PRIORITY_LOW,
- e_week_view_reload_events_idle_cb, week_view, NULL);
- }
-}
-
-
-static gboolean
-e_week_view_reload_events_idle_cb (gpointer data)
-{
- EWeekView *week_view;
-
- g_return_val_if_fail (E_IS_WEEK_VIEW (data), FALSE);
-
- GDK_THREADS_ENTER ();
-
- week_view = E_WEEK_VIEW (data);
-
- week_view->reload_events_idle_id = 0;
-
- e_week_view_reload_events (week_view);
-
- GDK_THREADS_LEAVE ();
- return FALSE;
-}
-
-
-static void
-e_week_view_reload_events (EWeekView *week_view)
-{
- gint num_days;
-
- e_week_view_free_events (week_view);
-
- if (!(week_view->client
- && cal_client_get_load_state (week_view->client) == CAL_CLIENT_LOAD_LOADED))
- return;
-
- /* Only load events if the date range has been set. */
- if (g_date_valid (&week_view->first_day_shown)) {
- num_days = week_view->multi_week_view
- ? week_view->weeks_shown * 7 : 7;
-
-#if 0
- g_print ("EWeekView (%s) generating instances\n",
- week_view->multi_week_view ? "Month View" : "Week View");
-#endif
- cal_client_generate_instances (week_view->client,
- CALOBJ_TYPE_EVENT,
- week_view->day_starts[0],
- week_view->day_starts[num_days],
- e_week_view_add_event,
- week_view);
- }
-
- week_view->events_need_reshape = TRUE;
- e_week_view_check_layout (week_view);
-
- gtk_widget_queue_draw (week_view->main_canvas);
-}
-
-
static void
e_week_view_free_events (EWeekView *week_view)
{
@@ -2777,7 +2815,7 @@ e_week_view_on_adjustment_changed (GtkAdjustment *adjustment,
lower = time_day_begin (lower);
e_week_view_recalc_day_starts (week_view, lower);
- e_week_view_queue_reload_events (week_view);
+ update_query (week_view);
/* Update the selection, if needed. */
if (week_view->selection_start_day != -1) {
diff --git a/calendar/gui/e-week-view.h b/calendar/gui/e-week-view.h
index 47362d0ee6..6717da9ea3 100644
--- a/calendar/gui/e-week-view.h
+++ b/calendar/gui/e-week-view.h
@@ -186,15 +186,16 @@ struct _EWeekView
/* Calendar client object we are monitoring */
CalClient *client;
+ /* S-expression for query and the query object */
+ char *sexp;
+ CalQuery *query;
+
/* The array of EWeekViewEvent elements. */
GArray *events;
gboolean events_sorted;
gboolean events_need_layout;
gboolean events_need_reshape;
- /* The id of our idle function to reload all events. */
- gint reload_events_idle_id;
-
/* An array of EWeekViewEventSpan elements. Each event has its own
space within this array, and uses the spans_index and num_spans
fields of the EWeekViewEvent struct to access it. */
@@ -363,6 +364,9 @@ void e_week_view_set_first_day_shown (EWeekView *week_view,
void e_week_view_set_cal_client (EWeekView *week_view,
CalClient *client);
+void e_week_view_set_query (EWeekView *week_view,
+ const char *sexp);
+
/* The selected time range. The EWeekView will show the corresponding
month and the days between start_time and end_time will be selected.
To select a single day, use the same value for start_time & end_time. */
diff --git a/calendar/pcs/cal.c b/calendar/pcs/cal.c
index 3129665466..e723c077cb 100644
--- a/calendar/pcs/cal.c
+++ b/calendar/pcs/cal.c
@@ -456,6 +456,8 @@ Cal_get_query (PortableServer_Servant servant,
Cal *cal;
CalPrivate *priv;
Query *query;
+ CORBA_Environment ev2;
+ GNOME_Evolution_Calendar_Query query_copy;
cal = CAL (bonobo_object_from_servant (servant));
priv = cal->priv;
@@ -468,7 +470,20 @@ Cal_get_query (PortableServer_Servant servant,
return CORBA_OBJECT_NIL;
}
- return BONOBO_OBJREF (query);
+ CORBA_exception_init (&ev2);
+ query_copy = CORBA_Object_duplicate (BONOBO_OBJREF (query), &ev2);
+ if (ev2._major != CORBA_NO_EXCEPTION) {
+ CORBA_exception_free (&ev2);
+ g_message ("Cal_get_query(): Could not duplicate the query reference");
+ CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
+ ex_GNOME_Evolution_Calendar_Cal_CouldNotCreate,
+ NULL);
+ return CORBA_OBJECT_NIL;
+ }
+
+ CORBA_exception_free (&ev2);
+
+ return query_copy;
}
/**
diff --git a/calendar/pcs/query.c b/calendar/pcs/query.c
index 708a160794..474a2eb971 100644
--- a/calendar/pcs/query.c
+++ b/calendar/pcs/query.c
@@ -30,6 +30,7 @@
#include <gtk/gtksignal.h>
#include <e-util/e-sexp.h>
#include <cal-util/cal-recur.h>
+#include <cal-util/timeutil.h>
#include "query.h"
@@ -138,6 +139,7 @@ query_destroy (GtkObject *object)
priv = query->priv;
if (priv->backend) {
+ gtk_signal_disconnect_by_data (GTK_OBJECT (priv->backend), query);
gtk_object_unref (GTK_OBJECT (priv->backend));
priv->backend = NULL;
}
@@ -200,7 +202,164 @@ query_destroy (GtkObject *object)
-/* Search engine functions */
+/* E-Sexp functions */
+
+/* (time-now)
+ *
+ * Returns a time_t of time (NULL).
+ */
+static ESExpResult *
+func_time_now (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+{
+ ESExpResult *result;
+
+ if (argc != 0) {
+ e_sexp_fatal_error (esexp, _("time-now expects 0 arguments"));
+ return NULL;
+ }
+
+ result = e_sexp_result_new (esexp, ESEXP_RES_TIME);
+ result->value.time = time (NULL);
+
+ return result;
+}
+
+/* (make-time ISODATE)
+ *
+ * ISODATE - string, ISO 8601 date/time representation
+ *
+ * Constructs a time_t value for the specified date.
+ */
+static ESExpResult *
+func_make_time (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+{
+ const char *str;
+ time_t t;
+ ESExpResult *result;
+
+ if (argc != 1) {
+ e_sexp_fatal_error (esexp, _("make-time expects 1 argument"));
+ return NULL;
+ }
+
+ if (argv[0]->type != ESEXP_RES_STRING) {
+ e_sexp_fatal_error (esexp, _("make-time expects argument 1 "
+ "to be a string"));
+ return NULL;
+ }
+ str = argv[0]->value.string;
+
+ t = time_from_isodate (str);
+ if (t == -1) {
+ e_sexp_fatal_error (esexp, _("make-time argument 1 must be an "
+ "ISO 8601 date/time string"));
+ return NULL;
+ }
+
+ result = e_sexp_result_new (esexp, ESEXP_RES_TIME);
+ result->value.time = t;
+
+ return result;
+}
+
+/* (time-add-day TIME N)
+ *
+ * TIME - time_t, base time
+ * N - int, number of days to add
+ *
+ * Adds the specified number of days to a time value.
+ */
+static ESExpResult *
+func_time_add_day (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+{
+ ESExpResult *result;
+ time_t t;
+ int n;
+
+ if (argc != 2) {
+ e_sexp_fatal_error (esexp, _("time-add-day expects 2 arguments"));
+ return NULL;
+ }
+
+ if (argv[0]->type != ESEXP_RES_TIME) {
+ e_sexp_fatal_error (esexp, _("time-add-day expects argument 1 "
+ "to be a time_t"));
+ return NULL;
+ }
+ t = argv[0]->value.time;
+
+ if (argv[1]->type != ESEXP_RES_INT) {
+ e_sexp_fatal_error (esexp, _("time-add-day expects argument 2 "
+ "to be an integer"));
+ return NULL;
+ }
+ n = argv[1]->value.number;
+
+ result = e_sexp_result_new (esexp, ESEXP_RES_TIME);
+ result->value.time = time_add_day (t, n);
+
+ return result;
+}
+
+/* (time-day-begin TIME)
+ *
+ * TIME - time_t, base time
+ *
+ * Returns the start of the day, according to the local time.
+ */
+static ESExpResult *
+func_time_day_begin (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+{
+ time_t t;
+ ESExpResult *result;
+
+ if (argc != 1) {
+ e_sexp_fatal_error (esexp, _("time-day-begin expects 1 argument"));
+ return NULL;
+ }
+
+ if (argv[0]->type != ESEXP_RES_TIME) {
+ e_sexp_fatal_error (esexp, _("time-day-begin expects argument 1 "
+ "to be a time_t"));
+ return NULL;
+ }
+ t = argv[0]->value.time;
+
+ result = e_sexp_result_new (esexp, ESEXP_RES_TIME);
+ result->value.time = time_day_begin (t);
+
+ return result;
+}
+
+/* (time-day-end TIME)
+ *
+ * TIME - time_t, base time
+ *
+ * Returns the end of the day, according to the local time.
+ */
+static ESExpResult *
+func_time_day_end (ESExp *esexp, int argc, ESExpResult **argv, void *data)
+{
+ time_t t;
+ ESExpResult *result;
+
+ if (argc != 1) {
+ e_sexp_fatal_error (esexp, _("time-day-end expects 1 argument"));
+ return NULL;
+ }
+
+ if (argv[0]->type != ESEXP_RES_TIME) {
+ e_sexp_fatal_error (esexp, _("time-day-end expects argument 1 "
+ "to be a time_t"));
+ return NULL;
+ }
+ t = argv[0]->value.time;
+
+ result = e_sexp_result_new (esexp, ESEXP_RES_TIME);
+ result->value.time = time_day_end (t);
+
+ return result;
+}
/* (get-vtype)
*
@@ -284,14 +443,12 @@ instance_occur_cb (CalComponent *comp, time_t start, time_t end, gpointer data)
/* (occur-in-time-range? START END)
*
- * START - int, time_t start of the time range
- * END - int, time_t end of the time range
+ * START - time_t, start of the time range
+ * END - time_t, end of the time range
*
* Returns a boolean indicating whether the component has any occurrences in the
* specified time range.
- *
- * We may prefer to switch this to a string representation of times (ISO 8601,
- * perhaps). */
+ */
static ESExpResult *
func_occur_in_time_range (ESExp *esexp, int argc, ESExpResult **argv, void *data)
{
@@ -315,19 +472,19 @@ func_occur_in_time_range (ESExp *esexp, int argc, ESExpResult **argv, void *data
return NULL;
}
- if (argv[0]->type != ESEXP_RES_INT) {
+ if (argv[0]->type != ESEXP_RES_TIME) {
e_sexp_fatal_error (esexp, _("occur-in-time-range? expects argument 1 "
- "to be an integer"));
+ "to be a time_t"));
return NULL;
}
- start = argv[0]->value.number;
+ start = argv[0]->value.time;
- if (argv[1]->type != ESEXP_RES_INT) {
+ if (argv[1]->type != ESEXP_RES_TIME) {
e_sexp_fatal_error (esexp, _("occur-in-time-range? expects argument 2 "
- "to be an integer"));
+ "to be a time_t"));
return NULL;
}
- end = argv[1]->value.number;
+ end = argv[1]->value.time;
/* See if there is at least one instance in that range */
@@ -446,6 +603,14 @@ static struct {
char *name;
ESExpFunc *func;
} functions[] = {
+ /* Time-related functions */
+ { "time-now", func_time_now },
+ { "make-time", func_make_time },
+ { "time-add-day", func_time_add_day },
+ { "time-day-begin", func_time_day_begin },
+ { "time-day-end", func_time_day_end },
+
+ /* Component-related functions */
{ "get-vtype", func_get_vtype },
{ "occur-in-time-range?", func_occur_in_time_range }
};
@@ -487,6 +652,8 @@ match_component (Query *query, const char *uid,
icalcomp = icalparser_parse_string (comp_str);
g_assert (icalcomp != NULL);
+ g_free (comp_str);
+
comp = cal_component_new ();
set_succeeded = cal_component_set_icalcomponent (comp, icalcomp);
g_assert (set_succeeded);
@@ -518,6 +685,7 @@ match_component (Query *query, const char *uid,
"an evaluation error");
CORBA_exception_free (&ev);
+ return;
} else if (result->type != ESEXP_RES_BOOL) {
CORBA_Environment ev;
@@ -541,6 +709,8 @@ match_component (Query *query, const char *uid,
else
remove_component (query, uid);
}
+
+ e_sexp_result_free (priv->esexp, result);
}
/* Processes a single component that is queued in the list */