aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/gui/calendar-model.c
diff options
context:
space:
mode:
Diffstat (limited to 'calendar/gui/calendar-model.c')
-rw-r--r--calendar/gui/calendar-model.c249
1 files changed, 184 insertions, 65 deletions
diff --git a/calendar/gui/calendar-model.c b/calendar/gui/calendar-model.c
index 7274c13e18..fa05ba407a 100644
--- a/calendar/gui/calendar-model.c
+++ b/calendar/gui/calendar-model.c
@@ -52,6 +52,9 @@ struct _CalendarModelPrivate {
/* UID -> array index hash */
GHashTable *uid_index_hash;
+ /* Whether we display dates in 24-hour format. */
+ gboolean use_24_hour_format;
+
/* HACK: so that ETable can do its stupid append_row() thing */
guint appending_row : 1;
};
@@ -157,6 +160,7 @@ calendar_model_init (CalendarModel *model)
priv->objects = g_array_new (FALSE, TRUE, sizeof (CalComponent *));
priv->uid_index_hash = g_hash_table_new (g_str_hash, g_str_equal);
+ priv->use_24_hour_format = TRUE;
}
/* Called from g_hash_table_foreach_remove(), frees a stored UID->index
@@ -261,10 +265,11 @@ calendar_model_row_count (ETableModel *etm)
/* Creates a nice string representation of a time value */
static char*
-get_time_t (time_t *t, gboolean skip_midnight)
+get_time_t (CalendarModel *model, time_t *t, gboolean skip_midnight)
{
- static char buffer[32];
+ static char buffer[64];
struct tm *tmp_tm;
+ char *format;
if (*t <= 0) {
buffer[0] = '\0';
@@ -273,9 +278,18 @@ get_time_t (time_t *t, gboolean skip_midnight)
if (skip_midnight && tmp_tm->tm_hour == 0
&& tmp_tm->tm_min == 0 && tmp_tm->tm_sec == 0)
- strftime (buffer, 32, "%a %x", tmp_tm);
+ /* strftime format of a weekday and a date. */
+ format = _("%a %m/%d/%Y");
+ else if (model->priv->use_24_hour_format)
+ /* strftime format of a weekday, a date and a time,
+ in 24-hour format. */
+ format = _("%a %m/%d/%Y %H:%M:%S");
else
- strftime (buffer, 32, "%a %x %T", tmp_tm);
+ /* strftime format of a weekday, a date and a time,
+ in 12-hour format. */
+ format = _("%a %m/%d/%Y %I:%M:%S %p");
+
+ strftime (buffer, sizeof (buffer), format, tmp_tm);
}
return buffer;
@@ -346,7 +360,8 @@ get_classification (CalComponent *comp)
/* Builds a string for the COMPLETED property of a calendar component */
static char *
-get_completed (CalComponent *comp)
+get_completed (CalendarModel *model,
+ CalComponent *comp)
{
struct icaltimetype *completed;
time_t t;
@@ -360,12 +375,12 @@ get_completed (CalComponent *comp)
cal_component_free_icaltimetype (completed);
}
- return get_time_t (&t, FALSE);
+ return get_time_t (model, &t, FALSE);
}
/* Builds a string for and frees a date/time value */
static char *
-get_and_free_datetime (CalComponentDateTime dt)
+get_and_free_datetime (CalendarModel *model, CalComponentDateTime dt)
{
time_t t;
@@ -376,37 +391,37 @@ get_and_free_datetime (CalComponentDateTime dt)
cal_component_free_datetime (&dt);
- return get_time_t (&t, FALSE);
+ return get_time_t (model, &t, FALSE);
}
/* Builds a string for the DTEND property of a calendar component */
static char *
-get_dtend (CalComponent *comp)
+get_dtend (CalendarModel *model, CalComponent *comp)
{
CalComponentDateTime dt;
cal_component_get_dtend (comp, &dt);
- return get_and_free_datetime (dt);
+ return get_and_free_datetime (model, dt);
}
/* Builds a string for the DTSTART property of a calendar component */
static char *
-get_dtstart (CalComponent *comp)
+get_dtstart (CalendarModel *model, CalComponent *comp)
{
CalComponentDateTime dt;
cal_component_get_dtstart (comp, &dt);
- return get_and_free_datetime (dt);
+ return get_and_free_datetime (model, dt);
}
/* Builds a string for the DUE property of a calendar component */
static char *
-get_due (CalComponent *comp)
+get_due (CalendarModel *model, CalComponent *comp)
{
CalComponentDateTime dt;
cal_component_get_due (comp, &dt);
- return get_and_free_datetime (dt);
+ return get_and_free_datetime (model, dt);
}
/* Builds a string for the GEO property of a calendar component */
@@ -546,8 +561,6 @@ get_is_complete (CalComponent *comp)
struct icaltimetype *t;
gboolean retval;
- /* May not be reliable, especially at the moment when
- we can't set a Completed Date to None. */
cal_component_get_completed (comp, &t);
retval = (t != NULL);
@@ -627,16 +640,16 @@ calendar_model_value_at (ETableModel *etm, int col, int row)
return get_classification (comp);
case CAL_COMPONENT_FIELD_COMPLETED:
- return get_completed (comp);
+ return get_completed (model, comp);
case CAL_COMPONENT_FIELD_DTEND:
- return get_dtend (comp);
+ return get_dtend (model, comp);
case CAL_COMPONENT_FIELD_DTSTART:
- return get_dtstart (comp);
+ return get_dtstart (model, comp);
case CAL_COMPONENT_FIELD_DUE:
- return get_due (comp);
+ return get_due (model, comp);
case CAL_COMPONENT_FIELD_GEO:
return get_geo (comp);
@@ -712,16 +725,24 @@ string_is_empty (const char *value)
/* FIXME: We need to set the "transient_for" property for the dialog, but
the model doesn't know anything about the windows. */
static void
-show_date_warning (void)
+show_date_warning (CalendarModel *model)
{
GtkWidget *dialog;
- char buffer[32], message[256];
+ char buffer[64], message[256], *format;
time_t t;
struct tm *tmp_tm;
t = time (NULL);
tmp_tm = localtime (&t);
- strftime (buffer, 32, "%a %x %T", tmp_tm);
+
+ if (model->priv->use_24_hour_format)
+ /* strftime format of a weekday, a date and a time, 24-hour. */
+ format = _("%a %m/%d/%Y %H:%M:%S");
+ else
+ /* strftime format of a weekday, a date and a time, 12-hour. */
+ format = _("%a %m/%d/%Y %I:%M:%S %p");
+
+ strftime (buffer, sizeof (buffer), format, tmp_tm);
g_snprintf (message, 256,
_("The date must be entered in the format: \n\n%s"),
@@ -801,62 +822,137 @@ set_categories (CalComponent *comp, const char *value)
static time_t
parse_time (const char *value)
{
- struct tm tmp_tm;
+ struct tm discard_tm, date_tm, time_tm;
struct tm *today_tm;
time_t t;
- const char *p;
+ const char *pos, *parse_end;
+ char *format[4];
+ gboolean parsed_date = FALSE, parsed_time = FALSE;
+ gint i;
if (string_is_empty (value))
return 0;
- /* Skip any weekday name. */
- p = strptime (value, "%a", &tmp_tm);
- if (!p)
- p = value;
+ pos = value;
- /* Try to match the full date & time, or without the seconds,
- or just the date, or just the time with/without seconds.
- The info pages say we should clear the tm before calling
- strptime. It also means that if we don't match a time we
- get 00:00:00 which is good. */
- memset (&tmp_tm, 0, sizeof (tmp_tm));
- if (!strptime (value, "%x %T", &tmp_tm)) {
- memset (&tmp_tm, 0, sizeof (tmp_tm));
- if (!strptime (value, "%x %H:%M", &tmp_tm)) {
- memset (&tmp_tm, 0, sizeof (tmp_tm));
- if (!strptime (value, "%x", &tmp_tm)) {
- memset (&tmp_tm, 0, sizeof (tmp_tm));
- if (!strptime (value, "%T", &tmp_tm)) {
- memset (&tmp_tm, 0, sizeof (tmp_tm));
- if (!strptime (value, "%H:%M", &tmp_tm))
- return -1; /* Could not parse it */
- }
-
- /* We only got a time, so we use the
- current day. */
- t = time (NULL);
- today_tm = localtime (&t);
- tmp_tm.tm_mday = today_tm->tm_mday;
- tmp_tm.tm_mon = today_tm->tm_mon;
- tmp_tm.tm_year = today_tm->tm_year;
- }
+ /* Skip any whitespace. */
+ while (isspace (*pos))
+ pos++;
+
+ /* Skip any weekday name, full or abbreviated. */
+ parse_end = strptime (pos, "%a ", &discard_tm);
+ if (parse_end)
+ pos = parse_end;
+
+ memset (&date_tm, 0, sizeof (date_tm));
+ /* strptime format for a date. */
+ parse_end = strptime (pos, _("%m/%d/%Y"), &date_tm);
+ if (parse_end) {
+ pos = parse_end;
+ parsed_date = TRUE;
+ }
+
+ /* Skip any whitespace. */
+ while (isspace (*pos))
+ pos++;
+
+ /* Skip any weekday name, full or abbreviated, again. */
+ parse_end = strptime (pos, "%a ", &discard_tm);
+ if (parse_end)
+ pos = parse_end;
+
+
+ /* strptime format for a time of day, in 12-hour format.
+ If it is is not appropriate in the locale set to an empty string. */
+ format[0] = _("%I:%M:%S %p%n");
+
+ /* strptime format for a time of day, in 24-hour format. */
+ format[1] = _("%H:%M:%S%n");
+
+ /* strptime format for time of day, without seconds, 12-hour format.
+ If it is is not appropriate in the locale set to an empty string. */
+ format[2] = _("%I:%M %p%n");
+
+ /* strptime format for time of day, without seconds 24-hour format. */
+ format[3] = _("%H:%M%n");
+
+ for (i = 0; i < sizeof (format) / sizeof (format[0]); i++) {
+ memset (&time_tm, 0, sizeof (time_tm));
+ parse_end = strptime (pos, format[i], &time_tm);
+ if (parse_end) {
+ pos = parse_end;
+ parsed_time = TRUE;
+ break;
+ }
+ }
+
+ /* Skip any whitespace. */
+ while (isspace (*pos))
+ pos++;
+
+ /* If we haven't already parsed a date, try again. */
+ if (!parsed_date) {
+ memset (&date_tm, 0, sizeof (date_tm));
+ /* strptime format for a date. */
+ parse_end = strptime (pos, _("%m/%d/%Y"), &date_tm);
+ if (parse_end) {
+ pos = parse_end;
+ parsed_date = TRUE;
}
}
- tmp_tm.tm_isdst = -1;
- return mktime (&tmp_tm);
+ /* If we don't have a date or a time it must be invalid. */
+ if (!parsed_date && !parsed_time)
+ return -1;
+
+
+ if (parsed_date) {
+ /* If a 2-digit year was used we use the current century. */
+ if (date_tm.tm_year < 0) {
+ t = time (NULL);
+ today_tm = localtime (&t);
+
+ /* This should convert it into a value from 0 to 99. */
+ date_tm.tm_year += 1900;
+
+ /* Now add on the century. */
+ date_tm.tm_year += today_tm->tm_year
+ - (today_tm->tm_year % 100);
+ }
+ } else {
+ /* If we didn't get a date we use the current day. */
+ t = time (NULL);
+ today_tm = localtime (&t);
+ date_tm.tm_mday = today_tm->tm_mday;
+ date_tm.tm_mon = today_tm->tm_mon;
+ date_tm.tm_year = today_tm->tm_year;
+ }
+
+ if (parsed_time) {
+ date_tm.tm_hour = time_tm.tm_hour;
+ date_tm.tm_min = time_tm.tm_min;
+ date_tm.tm_sec = time_tm.tm_sec;
+ } else {
+ date_tm.tm_hour = 0;
+ date_tm.tm_min = 0;
+ date_tm.tm_sec = 0;
+ }
+
+
+ date_tm.tm_isdst = -1;
+ return mktime (&date_tm);
}
/* Called to set the "Date Completed" field. We also need to update the
Status and Percent fields to make sure they match. */
static void
-set_completed (CalComponent *comp, const char *value)
+set_completed (CalendarModel *model, CalComponent *comp, const char *value)
{
time_t t;
t = parse_time (value);
if (t == -1) {
- show_date_warning ();
+ show_date_warning (model);
} else if (t == 0) {
ensure_task_not_complete (comp);
} else {
@@ -866,14 +962,14 @@ set_completed (CalComponent *comp, const char *value)
/* Sets a CalComponentDateTime value */
static void
-set_datetime (CalComponent *comp, const char *value,
+set_datetime (CalendarModel *model, CalComponent *comp, const char *value,
void (* set_func) (CalComponent *comp, CalComponentDateTime *dt))
{
time_t t;
t = parse_time (value);
if (t == -1) {
- show_date_warning ();
+ show_date_warning (model);
return;
} else if (t == 0) {
(* set_func) (comp, NULL);
@@ -1073,21 +1169,21 @@ calendar_model_set_value_at (ETableModel *etm, int col, int row, const void *val
/* FIXME: CLASSIFICATION requires an option menu cell renderer */
case CAL_COMPONENT_FIELD_COMPLETED:
- set_completed (comp, value);
+ set_completed (model, comp, value);
break;
case CAL_COMPONENT_FIELD_DTEND:
/* FIXME: Need to reset dtstart if dtend happens before it */
- set_datetime (comp, value, cal_component_set_dtend);
+ set_datetime (model, comp, value, cal_component_set_dtend);
break;
case CAL_COMPONENT_FIELD_DTSTART:
/* FIXME: Need to reset dtend if dtstart happens after it */
- set_datetime (comp, value, cal_component_set_dtstart);
+ set_datetime (model, comp, value, cal_component_set_dtstart);
break;
case CAL_COMPONENT_FIELD_DUE:
- set_datetime (comp, value, cal_component_set_due);
+ set_datetime (model, comp, value, cal_component_set_due);
break;
case CAL_COMPONENT_FIELD_GEO:
@@ -1904,3 +2000,26 @@ ensure_task_not_complete (CalComponent *comp)
}
+/* Whether we use 24 hour format to display the times. */
+gboolean
+calendar_model_get_use_24_hour_format (CalendarModel *model)
+{
+ g_return_val_if_fail (IS_CALENDAR_MODEL (model), TRUE);
+
+ return model->priv->use_24_hour_format;
+}
+
+
+void
+calendar_model_set_use_24_hour_format (CalendarModel *model,
+ gboolean use_24_hour_format)
+{
+ g_return_if_fail (IS_CALENDAR_MODEL (model));
+
+ if (model->priv->use_24_hour_format != use_24_hour_format) {
+ model->priv->use_24_hour_format = use_24_hour_format;
+ /* Get the views to redraw themselves. */
+ e_table_model_changed (E_TABLE_MODEL (model));
+ }
+}
+