[Xfce4-commits] <orage:master> 4.8.1.10 fixes to excluded time alarms
Juha Kautto
noreply at xfce.org
Mon Aug 29 13:32:01 CEST 2011
Updating branch refs/heads/master
to 09df53e97f41c22a1652b2a4367b899432c4d5d0 (commit)
from 19d9f003b8e1c0e4da5d151a7863bdfdbbfca2c4 (commit)
commit 09df53e97f41c22a1652b2a4367b899432c4d5d0
Author: Juha Kautto <juha at xfce.org>
Date: Mon Aug 29 14:29:26 2011 +0300
4.8.1.10 fixes to excluded time alarms
Made excluded alarms on excluded days and times work correctly and give
proper warnings.
configure.in.in | 2 +-
src/appointment.c | 34 ++++++++++---
src/functions.c | 29 +++++++++--
src/ical-code.c | 143 +++++++++++++++++++++++++++++++++++++++++++++++------
4 files changed, 180 insertions(+), 28 deletions(-)
diff --git a/configure.in.in b/configure.in.in
index 9a95057..3a24b99 100644
--- a/configure.in.in
+++ b/configure.in.in
@@ -9,7 +9,7 @@ dnl Written for Xfce by Juha Kautto <juha at xfce.org>
dnl
dnl Version information
-m4_define([orage_version], [4.8.1.9-git])
+m4_define([orage_version], [4.8.1.10-git])
m4_define([gtk_minimum_version], [2.10.0])
m4_define([xfce_minimum_version], [4.6.0])
diff --git a/src/appointment.c b/src/appointment.c
index d956e12..b043827 100644
--- a/src/appointment.c
+++ b/src/appointment.c
@@ -1312,6 +1312,8 @@ static xfical_exception *new_exception(char *text)
{
xfical_exception *recur_exception;
gint i;
+ struct tm tm_time = {0,0,0,0,0,0,0,0,0};
+ char *tmp;
recur_exception = g_new(xfical_exception, 1);
i = strlen(text);
@@ -1326,9 +1328,22 @@ static xfical_exception *new_exception(char *text)
/* need to add time also as standard libical can not handle dates
correctly yet. Check more from BUG 5764.
We use start time from appointment. */
- strcpy(recur_exception->time, orage_i18_time_to_icaltime(text));
+ /* we should not have dates as we are using standard libical,
+ but if this fails (=return NULL) we may have date from somewhere
+ else */
+ if ((char *)strptime(text, "%x %R", &tm_time) == NULL)
+ strcpy(recur_exception->time, orage_i18_date_to_icaldate(text));
+ else
+ strcpy(recur_exception->time, orage_i18_time_to_icaltime(text));
#else
- strcpy(recur_exception->time, orage_i18_date_to_icaldate(text));
+ /* we should not have date-times as we are using internal libical,
+ which only uses dates, but if this returns non null, we may have
+ datetime from somewhere else */
+ tmp = (char *)strptime(text, "%x", &tm_time);
+ if (ORAGE_STR_EXISTS(tmp))
+ strcpy(recur_exception->time, orage_i18_time_to_icaltime(text));
+ else
+ strcpy(recur_exception->time, orage_i18_date_to_icaldate(text));
#endif
}
text[i-2] = ' ';
@@ -1455,11 +1470,16 @@ static void recur_day_selected_double_click_cb(GtkCalendar *calendar
/* need to add time also as standard libical can not handle dates
correctly yet. Check more from BUG 5764.
We use start time from appointment. */
- hh = gtk_spin_button_get_value_as_int(
- GTK_SPIN_BUTTON(apptw->StartTime_spin_hh));
- mm = gtk_spin_button_get_value_as_int(
- GTK_SPIN_BUTTON(apptw->StartTime_spin_mm));
- cal_date = g_strdup(orage_cal_to_i18_time(calendar, hh, mm));
+ if (gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON(apptw->AllDay_checkbutton)))
+ cal_date = g_strdup(orage_cal_to_i18_date(calendar));
+ else {
+ hh = gtk_spin_button_get_value_as_int(
+ GTK_SPIN_BUTTON(apptw->StartTime_spin_hh));
+ mm = gtk_spin_button_get_value_as_int(
+ GTK_SPIN_BUTTON(apptw->StartTime_spin_mm));
+ cal_date = g_strdup(orage_cal_to_i18_time(calendar, hh, mm));
+ }
#else
/* date is enough */
cal_date = g_strdup(orage_cal_to_i18_date(calendar));
diff --git a/src/functions.c b/src/functions.c
index fd7e637..ffc92a4 100644
--- a/src/functions.c
+++ b/src/functions.c
@@ -96,8 +96,15 @@ void orage_message(gint level, const char *format, ...)
formatted = g_strdup_vprintf(format, args);
va_end(args);
- if (level < 0)
- g_debug("%s", formatted);
+ if (level < 0) {
+ if (g_log_level < -1000) {
+ struct tm *t = orage_localtime();
+
+ g_debug("%d:%d:%d %s", t->tm_hour, t->tm_min, t->tm_sec, formatted);
+ }
+ else
+ g_debug("%s", formatted);
+ }
else if (level < 100)
g_message("Orage **: %s", formatted);
else if (level < 200)
@@ -482,7 +489,7 @@ struct tm orage_i18_time_to_tm_time(const char *i18_time)
if (ret == NULL)
g_error("Orage: orage_i18_time_to_tm_time wrong format (%s)", i18_time);
else if (ret[0] != '\0')
- g_error("Orage: orage_i18_time_to_tm_time too long format (%s-%s)"
+ g_warning("Orage: orage_i18_time_to_tm_time too long format (%s). Ignoring:%s)"
, i18_time, ret);
return(tm_time);
}
@@ -496,7 +503,7 @@ struct tm orage_i18_date_to_tm_date(const char *i18_date)
if (ret == NULL)
g_error("Orage: orage_i18_date_to_tm_date wrong format (%s)", i18_date);
else if (ret[0] != '\0')
- g_error("Orage: orage_i18_date_to_tm_date too long format (%s-%s)"
+ g_warning("Orage: orage_i18_date_to_tm_date too long format (%s). Ignoring:%s)"
, i18_date, ret);
return(tm_date);
}
@@ -892,7 +899,9 @@ OrageRc *orage_rc_file_open(char *fpath, gboolean read_only)
orc->cur_group = NULL;
}
else {
+#ifdef ORAGE_DEBUG
orage_message(-90, "orage_rc_file_open: Unable to open RC file (%s). Creating it. (%s)", fpath, error->message);
+#endif
g_clear_error(&error);
if (g_file_set_contents((const gchar *)fpath, "#Created by Orage", -1
, &error)) { /* successfully created new file */
@@ -903,7 +912,9 @@ OrageRc *orage_rc_file_open(char *fpath, gboolean read_only)
orc->cur_group = NULL;
}
else {
+#ifdef ORAGE_DEBUG
orage_message(150, "orage_rc_file_open: Unable to open (create) RC file (%s). (%s)", fpath, error->message);
+#endif
g_key_file_free(grc);
}
}
@@ -936,7 +947,9 @@ void orage_rc_file_close(OrageRc *orc)
g_free(orc);
}
else {
+#ifdef ORAGE_DEBUG
orage_message(-90, "orage_rc_file_close: closing empty file.");
+#endif
}
}
@@ -957,7 +970,9 @@ void orage_rc_del_group(OrageRc *orc, char *grp)
if (!g_key_file_remove_group((GKeyFile *)orc->rc, (const gchar *)grp
, &error)) {
+#ifdef ORAGE_DEBUG
orage_message(150, "orage_rc_del_group: Group remove failed. RC file (%s). group (%s) (%s)", orc->file_name, grp, error->message);
+#endif
}
}
@@ -975,7 +990,9 @@ gchar *orage_rc_get_str(OrageRc *orc, char *key, char *def)
, (const gchar *)key, &error);
if (!ret && error) {
ret = g_strdup(def);
+#ifdef ORAGE_DEBUG
orage_message(-90, "orage_rc_get_str: str (%s) group (%s) in RC file (%s) not found, using default (%s)", key, orc->cur_group, orc->file_name, ret);
+#endif
}
return(ret);
}
@@ -989,7 +1006,9 @@ gint orage_rc_get_int(OrageRc *orc, char *key, gint def)
, (const gchar *)key, &error);
if (!ret && error) {
ret = def;
+#ifdef ORAGE_DEBUG
orage_message(-90, "orage_rc_get_int: str (%s) group (%s) in RC file (%s) not found, using default (%d)", key, orc->cur_group, orc->file_name, ret);
+#endif
}
return(ret);
}
@@ -1003,7 +1022,9 @@ gboolean orage_rc_get_bool(OrageRc *orc, char *key, gboolean def)
, (const gchar *)key, &error);
if (!ret && error) {
ret = def;
+#ifdef ORAGE_DEBUG
orage_message(-90, "orage_rc_get_bool: str (%s) group (%s) in RC file (%s) not found, using default (%d)", key, orc->cur_group, orc->file_name, ret);
+#endif
}
return(ret);
}
diff --git a/src/ical-code.c b/src/ical-code.c
index e1633fa..ffaf956 100644
--- a/src/ical-code.c
+++ b/src/ical-code.c
@@ -86,7 +86,7 @@ static void xfical_alarm_build_list_internal(gboolean first_list_today);
#define ZONES_TAB_FILE_LOC ZONEINFO_DIRECTORY "/" ZONES_TAB_FILENAME
-typedef struct
+typedef struct _xfical_timezone_array
{
int count; /* how many timezones we have */
char **city; /* pointer to timezone location name strings */
@@ -105,13 +105,18 @@ gboolean ic_file_modified = FALSE; /* has any ical file been changed */
static guint file_close_timer = 0; /* delayed file close timer */
typedef struct _foreign_ical_files
-{;
+{
icalset *fical;
icalcomponent *ical;
} ic_foreign_ical_files;
ic_foreign_ical_files ic_f_ical[10];
+typedef struct _excluded_time
+{
+ struct icaltimetype e_time;
+} excluded_time;
+
/* timezone handling */
static icaltimezone *utc_icaltimezone = NULL;
static icaltimezone *local_icaltimezone = NULL;
@@ -1156,9 +1161,10 @@ static void appt_add_exception_internal(xfical_appt *appt
excp = (xfical_exception *)gl_tmp->data;
wtime = icaltime_from_string(excp->time);
if (strcmp(excp->type, "EXDATE") == 0) {
- /* Orage only supports date as EXDATE */
- if (!icaltime_is_date(wtime))
- orage_message(110, "appt_add_exceptions_internal: EXDATE not date (%s) (%d). Orage can handle dates only.", excp->time, strlen(excp->time));
+#ifdef HAVE_LIBICAL
+ if (icaltime_is_date(wtime))
+ orage_message(110, "appt_add_exceptions_internal: EXDATE is date (%s) (%d). There is libical bug http://sourceforge.net/tracker/?func=detail&aid=2901161&group_id=16077&atid=116077 which causes that excluded dates do not work properly in Orage.", excp->time, strlen(excp->time));
+#endif
icalcomponent_add_property(icmp
, icalproperty_new_exdate(wtime));
}
@@ -2552,6 +2558,98 @@ static struct icaltimetype count_alarm_time(xfical_period per
return(alarm_time);
}
+static gint exclude_order(gconstpointer a, gconstpointer b)
+{
+#undef P_N
+#define P_N "exclude_order: "
+ return(icaltime_compare(((excluded_time *)a)->e_time
+ , ((excluded_time *)b)->e_time));
+}
+
+static icaltimezone *build_excluded_list_dtstart(icalcomponent *c)
+{
+ const icaltimezone *zone=NULL;
+ icalproperty *p = NULL;
+ const char *text;
+ struct icaltimetype itime;
+
+ p = icalcomponent_get_first_property(c, ICAL_DTSTART_PROPERTY);
+ if (p) {
+ text = icalproperty_get_value_as_string(p);
+ itime = icaltime_from_string(text);
+ itime = ic_convert_to_timezone(itime, p);
+ zone = itime.zone;
+ }
+ if (!zone) /* we have floating time, so let's use local timezone */
+ zone = local_icaltimezone;
+
+ return((icaltimezone *)zone);
+}
+
+static void build_excluded_list(GList **exclude_l, icalcomponent *comp
+ , const icaltimezone *zone)
+{
+#undef P_N
+#define P_N "build_excluded_list: "
+ icalproperty *exdate;
+ struct icaltimetype exdatetime;
+ excluded_time *l_etime;
+
+ for (exdate = icalcomponent_get_first_property(comp,ICAL_EXDATE_PROPERTY);
+ exdate != NULL;
+ exdate = icalcomponent_get_next_property(comp,ICAL_EXDATE_PROPERTY)) {
+ exdatetime = icalproperty_get_exdate(exdate);
+ exdatetime = ic_convert_to_timezone(exdatetime, exdate);
+ if (!exdatetime.zone)
+ icaltime_set_timezone(&exdatetime, zone);
+
+ l_etime = g_new(excluded_time, 1);
+ l_etime->e_time = exdatetime;
+ *exclude_l = g_list_prepend(*exclude_l, l_etime);
+ }
+}
+
+static void free_exclude_time(gpointer e_t, gpointer dummy)
+{
+ g_free(e_t);
+}
+
+static void free_excluded_list(GList *exclude_l)
+{
+
+ g_list_foreach(exclude_l, free_exclude_time, NULL);
+ g_list_free(exclude_l);
+ exclude_l = NULL;
+}
+
+static gboolean time_is_excluded(GList *exclude_l, struct icaltimetype *time)
+{
+#undef P_N
+#define P_N "time_is_excluded: "
+ GList *e_l=NULL;
+ excluded_time *excl_time;
+ struct icaltimetype e_time;
+
+ if (exclude_l == NULL || time == NULL || icaltime_is_null_time(*time))
+ return 0;
+
+ for (e_l = g_list_first(exclude_l); e_l != NULL; e_l = g_list_next(e_l)) {
+ excl_time = (excluded_time *)e_l->data;
+ e_time = excl_time->e_time;
+ if ((icaltime_is_date(e_time)
+ && icaltime_compare_date_only(e_time, *time) == 0)
+ || (icaltime_compare(e_time, *time) == 0))
+ return(1);
+ else if ((icaltime_is_date(e_time)
+ && icaltime_compare_date_only(e_time, *time) > 0)
+ || (icaltime_compare(e_time, *time) > 0))
+ /* remember that it is sorted list, so when e_time is bigger than
+ searched time, we know that we did not find a match */
+ return(0);
+ }
+ return(0); /* end of list reached */
+}
+
/* let's find the trigger and check that it is active.
* return new alarm struct if alarm is active and NULL if it is not
* FIXME: We assume all alarms have similar trigger, which
@@ -2576,6 +2674,8 @@ static alarm_struct *process_alarm_trigger(icalcomponent *c
struct icaldurationtype alarm_start_diff;
struct icaldatetimeperiodtype rdate_period;
gchar *tmp1, *tmp2;
+ GList *excluded_list = NULL;
+ icaltimezone *dtstart_zone;
/* pvl_elem property_iterator; */ /* for saving the iterator */
#ifdef ORAGE_DEBUG
@@ -2596,11 +2696,11 @@ static alarm_struct *process_alarm_trigger(icalcomponent *c
per = ic_get_period(c, TRUE);
next_alarm_time = count_alarm_time(per, cur_time, trg.duration, rel);
alarm_start_diff = icaltime_subtract(next_alarm_time, per.stime);
-/*
-orage_message(120, P_N "current %s", icaltime_as_ical_string(cur_time));
-orage_message(120, P_N "Start %s", icaltime_as_ical_string(per.stime));
-orage_message(120, P_N "End %s", icaltime_as_ical_string(per.etime));
-orage_message(120, P_N "Alarm %s", icaltime_as_ical_string(next_alarm_time));
+ /*
+orage_message(120, P_N "current %s %s", icaltime_as_ical_string(cur_time), icaltime_get_tzid(cur_time));
+orage_message(120, P_N "Start %s %s", icaltime_as_ical_string(per.stime), icaltime_get_tzid(per.stime));
+orage_message(120, P_N "End %s %s", icaltime_as_ical_string(per.etime), icaltime_get_tzid(per.etime));
+orage_message(120, P_N "Alarm %s %s", icaltime_as_ical_string(next_alarm_time), icaltime_get_tzid(next_alarm_time));
*/
/* we only have ctime for TODOs and only if todo has been completed.
* So if we have ctime, we need to compare against it instead of
@@ -2622,7 +2722,12 @@ orage_message(120, P_N "Alarm %s", icaltime_as_ical_string(next_alarm_time));
if (!trg_active
&& (p = icalcomponent_get_first_property(c, ICAL_RRULE_PROPERTY)) != 0) {
+icalproperty *exdate;
+struct icaltimetype exdatetime;
/* check recurring EVENTs */
+ dtstart_zone = build_excluded_list_dtstart(c);
+ build_excluded_list(&excluded_list, c, dtstart_zone);
+ excluded_list = g_list_sort(excluded_list, exclude_order);
rrule = icalproperty_get_rrule(p);
set_todo_times(c, &per); /* may change per.stime to be per.ctime */
next_alarm_time = count_alarm_time(per, cur_time, trg.duration, rel);
@@ -2640,8 +2745,8 @@ orage_message(120, P_N "rec Alarm %s", icaltime_as_ical_string(next_alarm_time))
&& icaltime_compare(next_start_time, per.ctime) <= 0)
|| (per.ikind != ICAL_VTODO_COMPONENT
&& icaltime_compare(next_alarm_time, cur_time) <= 0)
- || icalproperty_recurrence_is_excluded(c
- , &per.stime, &next_start_time));
+ || time_is_excluded(excluded_list, &next_start_time)
+ );
next_start_time = icalrecur_iterator_next(ri),
next_alarm_time = icaltime_add(next_start_time, alarm_start_diff)) {
/* we loop = search next active alarm time as long as
@@ -2650,16 +2755,22 @@ orage_message(120, P_N "rec Alarm %s", icaltime_as_ical_string(next_alarm_time))
* or if not TODO (= EVENT) and next_alarm_time before current time
*/
(*cnt_repeat)++;
-/*
-orage_message(120, P_N "rec loop Alarm start:%s alarm:%s", icaltime_as_ical_string(next_start_time), icaltime_as_ical_string(next_alarm_time));
+ /*
+orage_message(120, P_N "Alarm rec loop next_start:%s next_alarm:%s per.stime:%s", icaltime_as_ical_string(next_start_time), icaltime_as_ical_string(next_alarm_time), icaltime_as_ical_string(per.stime));
*/
}
icalrecur_iterator_free(ri);
if (icaltime_compare(cur_time, next_alarm_time) <= 0) {
trg_active = TRUE;
}
-/*
-orage_message(120, P_N "rec loop end Alarm start:%s alarm:%s", icaltime_as_ical_string(next_start_time), icaltime_as_ical_string(next_alarm_time));
+ free_excluded_list(excluded_list);
+ /*
+orage_message(120, P_N "Alarm rec loop END next_start:%s next_alarm:%s per.stime:%s excluded:%d", icaltime_as_ical_string(next_start_time), icaltime_as_ical_string(next_alarm_time), icaltime_as_ical_string(per.stime), icalproperty_recurrence_is_excluded(c, &per.stime, &next_start_time));
+exdate = icalcomponent_get_first_property(c,ICAL_EXDATE_PROPERTY);
+if (exdate) {
+ exdatetime = icalproperty_get_exdate(exdate);
+ orage_message(120, P_N "Alarm rec loop END exdate:%s compare: %d", icaltime_as_ical_string(exdatetime), icaltime_compare(next_start_time, exdatetime));
+}
*/
}
More information about the Xfce4-commits
mailing list