From 909eac7b7007ed089596324d0df4485fbafb9e48 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 25 Jul 2013 12:59:35 -0500 Subject: add a (currently unimplemented) PROFILE_PHONE to our enum --- src/service.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/service.c b/src/service.c index f0eed76..b270e89 100644 --- a/src/service.c +++ b/src/service.c @@ -59,6 +59,7 @@ enum enum { + PROFILE_PHONE, PROFILE_DESKTOP, PROFILE_GREETER, N_PROFILES @@ -66,6 +67,7 @@ enum static const char * const menu_names[N_PROFILES] = { + "phone", "desktop", "desktop_greeter" }; @@ -1151,16 +1153,21 @@ create_menu (IndicatorDatetimeService * self, int profile) g_assert (0<=profile && profilepriv->menus[profile].menu == NULL); - if (profile == PROFILE_DESKTOP) + switch (profile) { - sections[n++] = create_calendar_section (self); - sections[n++] = create_appointments_section (self); - sections[n++] = create_locations_section (self); - sections[n++] = create_settings_section (self); - } - else if (profile == PROFILE_GREETER) - { - sections[n++] = create_calendar_section (self); + case PROFILE_PHONE: + break; + + case PROFILE_DESKTOP: + sections[n++] = create_calendar_section (self); + sections[n++] = create_appointments_section (self); + sections[n++] = create_locations_section (self); + sections[n++] = create_settings_section (self); + break; + + case PROFILE_GREETER: + sections[n++] = create_calendar_section (self); + break; } /* add sections to the submenu */ -- cgit v1.2.3 From 7364cf8dcb250e69748cdf077556778dd60a5f1d Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 25 Jul 2013 13:08:34 -0500 Subject: for the phone menu, add a 'Time & Date settings...' menuitem to launch 'system-settings time-date' --- data/com.canonical.indicator.datetime | 2 +- src/service.c | 38 ++++++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/data/com.canonical.indicator.datetime b/data/com.canonical.indicator.datetime index f1b5304..b26b5ec 100644 --- a/data/com.canonical.indicator.datetime +++ b/data/com.canonical.indicator.datetime @@ -10,5 +10,5 @@ ObjectPath=/com/canonical/indicator/datetime/desktop ObjectPath=/com/canonical/indicator/datetime/desktop_greeter [phone] -ObjectPath=/com/canonical/indicator/datetime/desktop +ObjectPath=/com/canonical/indicator/datetime/phone diff --git a/src/service.c b/src/service.c index b270e89..4a7dedf 100644 --- a/src/service.c +++ b/src/service.c @@ -1133,10 +1133,18 @@ on_set_location (GSimpleAction * a G_GNUC_UNUSED, ***/ static GMenuModel * -create_settings_section (IndicatorDatetimeService * self G_GNUC_UNUSED) +create_desktop_settings_section (IndicatorDatetimeService * self G_GNUC_UNUSED) { GMenu * menu = g_menu_new (); - g_menu_append (menu, _("Date & Time Settings…"), "indicator.activate-settings"); + g_menu_append (menu, _("Date & Time Settings…"), "indicator.activate-desktop-settings"); + return G_MENU_MODEL (menu); +} + +static GMenuModel * +create_phone_settings_section (IndicatorDatetimeService * self G_GNUC_UNUSED) +{ + GMenu * menu = g_menu_new (); + g_menu_append (menu, _("Time & Date settings…"), "indicator.activate-phone-settings"); return G_MENU_MODEL (menu); } @@ -1156,13 +1164,14 @@ create_menu (IndicatorDatetimeService * self, int profile) switch (profile) { case PROFILE_PHONE: + sections[n++] = create_phone_settings_section (self); break; case PROFILE_DESKTOP: sections[n++] = create_calendar_section (self); sections[n++] = create_appointments_section (self); sections[n++] = create_locations_section (self); - sections[n++] = create_settings_section (self); + sections[n++] = create_desktop_settings_section (self); break; case PROFILE_GREETER: @@ -1210,15 +1219,15 @@ execute_command (const gchar * cmd) if (!g_spawn_command_line_async (cmd, &err)) { - g_warning ("Unable to start %s: %s", cmd, err->message); + g_warning ("Unable to start \"%s\": %s", cmd, err->message); g_error_free (err); } } static void -on_settings_activated (GSimpleAction * a G_GNUC_UNUSED, - GVariant * param G_GNUC_UNUSED, - gpointer gself G_GNUC_UNUSED) +on_desktop_settings_activated (GSimpleAction * a G_GNUC_UNUSED, + GVariant * param G_GNUC_UNUSED, + gpointer gself G_GNUC_UNUSED) { #ifdef HAVE_CCPANEL execute_command ("gnome-control-center indicator-datetime"); @@ -1227,6 +1236,14 @@ on_settings_activated (GSimpleAction * a G_GNUC_UNUSED, #endif } +static void +on_phone_settings_activated (GSimpleAction * a G_GNUC_UNUSED, + GVariant * param G_GNUC_UNUSED, + gpointer gself G_GNUC_UNUSED) +{ + execute_command ("system-settings time-date"); +} + static void on_activate_planner (GSimpleAction * a G_GNUC_UNUSED, GVariant * param, @@ -1278,7 +1295,8 @@ init_gactions (IndicatorDatetimeService * self) priv_t * p = self->priv; GActionEntry entries[] = { - { "activate-settings", on_settings_activated }, + { "activate-desktop-settings", on_desktop_settings_activated }, + { "activate-phone-settings", on_phone_settings_activated }, { "activate-planner", on_activate_planner, "x", NULL }, { "set-location", on_set_location, "s" } }; @@ -1328,6 +1346,7 @@ static void rebuild_now (IndicatorDatetimeService * self, int sections) { priv_t * p = self->priv; + struct ProfileMenuInfo * phone = &p->menus[PROFILE_PHONE]; struct ProfileMenuInfo * desktop = &p->menus[PROFILE_DESKTOP]; struct ProfileMenuInfo * greeter = &p->menus[PROFILE_GREETER]; @@ -1354,7 +1373,8 @@ rebuild_now (IndicatorDatetimeService * self, int sections) if (sections & SECTION_SETTINGS) { - rebuild_section (desktop->submenu, 3, create_settings_section (self)); + rebuild_section (phone->submenu, 0, create_phone_settings_section (self)); + rebuild_section (desktop->submenu, 3, create_desktop_settings_section (self)); } } -- cgit v1.2.3 From 7b4baac1d34ce22a570f080066856e229462f606 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 25 Jul 2013 19:04:47 -0500 Subject: Add support for displaying alarms. EDS treats alarms as attributes of existing calendar events, so the difference in supporting them in the indicator is largely visual -- we use a different x-canonical-type for the menuitem so that clients can render them differently, such as with an alarm icon. --- README | 6 ++++++ src/planner-eds.c | 5 +++++ src/planner.h | 1 + src/service.c | 14 ++++++++++---- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/README b/README index c6a8780..5dc9764 100644 --- a/README +++ b/README @@ -42,6 +42,12 @@ CUSTOM MENUITEMS * Calendar - x-canonical-type s "com.canonical.indicator.calendar" + * Alarm + - label s short summary of the appointment + - x-canonical-type s "com.canonical.indicator.alarm" + - x-canonical-time x the date of the appointment + - x-canonical-time-format s strftime format string + * Appointment - label s short summary of the appointment - x-canonical-type s "com.canonical.indicator.appointment" diff --git a/src/planner-eds.c b/src/planner-eds.c index 8fdc50b..d417d41 100644 --- a/src/planner-eds.c +++ b/src/planner-eds.c @@ -81,6 +81,7 @@ my_get_appointments_foreach (ECalComponent * component, e_cal_component_get_status (component, &status); if ((status != ICAL_STATUS_COMPLETED) && (status != ICAL_STATUS_CANCELLED)) { + GList * alarm_uids; ECalComponentText text; struct IndicatorDatetimeAppt * appt = g_new0 (struct IndicatorDatetimeAppt, 1); @@ -93,6 +94,10 @@ my_get_appointments_foreach (ECalComponent * component, appt->is_event = vtype == E_CAL_COMPONENT_EVENT; appt->summary = g_strdup (text.value); + alarm_uids = e_cal_component_get_alarm_uids (component); + appt->has_alarms = alarm_uids != NULL; + cal_obj_uid_list_free (alarm_uids); + data->appointments = g_slist_prepend (data->appointments, appt); } } diff --git a/src/planner.h b/src/planner.h index 7499b75..eab5f9a 100644 --- a/src/planner.h +++ b/src/planner.h @@ -44,6 +44,7 @@ struct IndicatorDatetimeAppt GDateTime * begin; GDateTime * end; gboolean is_event; + gboolean has_alarms; }; /** diff --git a/src/service.c b/src/service.c index 4a7dedf..0167d82 100644 --- a/src/service.c +++ b/src/service.c @@ -725,14 +725,18 @@ create_appointments_section (IndicatorDatetimeService * self) const gint64 unix_time = g_date_time_to_unix (appt->begin); menu_item = g_menu_item_new (appt->summary, NULL); - g_menu_item_set_attribute (menu_item, "x-canonical-color", - "s", appt->color); + + if (!appt->has_alarms) + g_menu_item_set_attribute (menu_item, "x-canonical-color", + "s", appt->color); + g_menu_item_set_attribute (menu_item, "x-canonical-time", "x", unix_time); g_menu_item_set_attribute (menu_item, "x-canonical-time-format", "s", fmt); g_menu_item_set_attribute (menu_item, "x-canonical-type", - "s", "com.canonical.indicator.appointment"); + "s", appt->has_alarms ? "com.canonical.indicator.alarm" + : "com.canonical.indicator.appointment"); g_menu_item_set_action_and_target_value (menu_item, "indicator.activate-planner", g_variant_new_int64 (unix_time)); @@ -1164,6 +1168,7 @@ create_menu (IndicatorDatetimeService * self, int profile) switch (profile) { case PROFILE_PHONE: + sections[n++] = create_appointments_section (self); sections[n++] = create_phone_settings_section (self); break; @@ -1363,6 +1368,7 @@ rebuild_now (IndicatorDatetimeService * self, int sections) if (sections & SECTION_APPOINTMENTS) { + rebuild_section (phone->submenu, 0, create_appointments_section (self)); rebuild_section (desktop->submenu, 1, create_appointments_section (self)); } @@ -1373,7 +1379,7 @@ rebuild_now (IndicatorDatetimeService * self, int sections) if (sections & SECTION_SETTINGS) { - rebuild_section (phone->submenu, 0, create_phone_settings_section (self)); + rebuild_section (phone->submenu, 1, create_phone_settings_section (self)); rebuild_section (desktop->submenu, 3, create_desktop_settings_section (self)); } } -- cgit v1.2.3 From 30d45a522eb83d519f1ee44ebe06a6696d2b094d Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 25 Jul 2013 21:06:25 -0500 Subject: in the appointments section, only show the next instance of recurring events. If the event is daily, say so in the time format string. --- src/planner-eds.c | 36 +++++++++++++++++++++++++++++++++--- src/planner.h | 1 + src/service.c | 8 +++++++- src/utils.c | 19 ++++++++++++++----- src/utils.h | 1 + 5 files changed, 56 insertions(+), 9 deletions(-) diff --git a/src/planner-eds.c b/src/planner-eds.c index d417d41..276058d 100644 --- a/src/planner-eds.c +++ b/src/planner-eds.c @@ -64,6 +64,9 @@ struct my_get_appointments_data { ESource * source; GSList * appointments; + + /* ensure that recurring events don't get multiple IndicatorDatetimeAppts */ + GHashTable * added; }; static gboolean @@ -77,13 +80,37 @@ my_get_appointments_foreach (ECalComponent * component, if ((vtype == E_CAL_COMPONENT_EVENT) || (vtype == E_CAL_COMPONENT_TODO)) { - icalproperty_status status; + const gchar * uid = NULL; + icalproperty_status status = 0; + + e_cal_component_get_uid (component, &uid); e_cal_component_get_status (component, &status); - if ((status != ICAL_STATUS_COMPLETED) && (status != ICAL_STATUS_CANCELLED)) + + if ((uid != NULL) && + (!g_hash_table_contains (data->added, uid)) && + (status != ICAL_STATUS_COMPLETED) && + (status != ICAL_STATUS_CANCELLED)) { GList * alarm_uids; + GSList * l; + GSList * recur_list; ECalComponentText text; - struct IndicatorDatetimeAppt * appt = g_new0 (struct IndicatorDatetimeAppt, 1); + struct IndicatorDatetimeAppt * appt; + + appt = g_new0 (struct IndicatorDatetimeAppt, 1); + + /* Determine whether this is a recurring event. + NB: icalrecurrencetype supports complex recurrence patterns; + however, since design only allows daily recurrence, + that's all we support here. */ + e_cal_component_get_rrule_list (component, &recur_list); + for (l=recur_list; l!=NULL; l=l->next) + { + const struct icalrecurrencetype * recur = l->data; + appt->is_daily |= ((recur->freq == ICAL_DAILY_RECURRENCE) + && (recur->interval == 1)); + } + e_cal_component_free_recur_list (recur_list); text.value = ""; e_cal_component_get_summary (component, &text); @@ -99,6 +126,7 @@ my_get_appointments_foreach (ECalComponent * component, cal_obj_uid_list_free (alarm_uids); data->appointments = g_slist_prepend (data->appointments, appt); + g_hash_table_add (data->added, g_strdup(uid)); } } @@ -146,6 +174,7 @@ my_get_appointments (IndicatorDatetimePlanner * planner, data.source = NULL; data.appointments = NULL; + data.added = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); sources = e_source_registry_list_sources (p->source_registry, E_SOURCE_EXTENSION_CALENDAR); for (l=sources; l!=NULL; l=l->next) @@ -188,6 +217,7 @@ my_get_appointments (IndicatorDatetimePlanner * planner, g_list_free_full (sources, g_object_unref); g_debug ("%s EDS get_appointments returning %d appointments", G_STRLOC, g_slist_length (data.appointments)); + g_hash_table_destroy (data.added); return data.appointments; } diff --git a/src/planner.h b/src/planner.h index eab5f9a..f6148c6 100644 --- a/src/planner.h +++ b/src/planner.h @@ -44,6 +44,7 @@ struct IndicatorDatetimeAppt GDateTime * begin; GDateTime * end; gboolean is_event; + gboolean is_daily; gboolean has_alarms; }; diff --git a/src/service.c b/src/service.c index 0167d82..8d82355 100644 --- a/src/service.c +++ b/src/service.c @@ -687,7 +687,13 @@ get_appointment_time_format (struct IndicatorDatetimeAppt * appt, GDateTime * n char * fmt; gboolean full_day = g_date_time_difference (appt->end, appt->begin) == G_TIME_SPAN_DAY; - if (full_day) + if (appt->is_daily) + { + char * time_string = generate_format_string_full (FALSE, FALSE); + fmt = join_date_and_time_format_strings (_("Daily"), time_string); + g_free (time_string); + } + else if (full_day) { /* TRANSLATORS: This is a strftime string for the day for full day events in the menu. It should most likely be either '%A' for a full text day diff --git a/src/utils.c b/src/utils.c index fa54008..a408f68 100644 --- a/src/utils.c +++ b/src/utils.c @@ -154,6 +154,19 @@ T_(const char *msg) return rv; } +gchar * +join_date_and_time_format_strings (const char * date_string, + const char * time_string) +{ + /* TRANSLATORS: This is a format string passed to strftime to combine the + * date and the time. The value of "%s\xE2\x80\x82%s" will result in a + * string like this in US English 12-hour time: 'Fri Jul 16 11:50 AM'. + * The space in between date and time is a Unicode en space + * (E28082 in UTF-8 hex). */ + return g_strdup_printf (T_("%s\xE2\x80\x82%s"), date_string, time_string); +} + + /* Tries to figure out what our format string should be. Lots of translator comments in here. */ gchar * @@ -218,11 +231,7 @@ generate_format_string_full (gboolean show_day, gboolean show_date) /* Check point, we should have a date string */ g_return_val_if_fail(date_string != NULL, g_strdup(time_string)); - /* TRANSLATORS: This is a format string passed to strftime to combine the - date and the time. The value of "%s\xE2\x80\x82%s" would result in a string like - this in US English 12-hour time: 'Fri Jul 16 11:50 AM'. - The space in between date and time is a Unicode en space (E28082 in UTF-8 hex). */ - return g_strdup_printf(T_("%s\xE2\x80\x82%s"), date_string, time_string); + return join_date_and_time_format_strings (date_string, time_string); } gchar * diff --git a/src/utils.h b/src/utils.h index 8dc2964..73bd83a 100644 --- a/src/utils.h +++ b/src/utils.h @@ -32,6 +32,7 @@ void split_settings_location (const gchar * location, gchar ** zone, gchar ** na gchar * get_current_zone_name (const gchar * location); gchar * generate_format_string_full (gboolean show_day, gboolean show_date); gchar * generate_format_string_at_time (GDateTime * now, GDateTime * time); +gchar * join_date_and_time_format_strings (const char * date, const char * time); G_END_DECLS -- cgit v1.2.3 From 79bca62afa1ef33b5ef3dd6c4d477bcf603a6435 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 25 Jul 2013 21:37:18 -0500 Subject: =?UTF-8?q?split=20the=20phone=20and=20desktop=20flavors=20of=20th?= =?UTF-8?q?e=20appointments=20section=20s.t.=20the=20phone=20menu=20doesn'?= =?UTF-8?q?t=20have=20a=20'Add=20Event=E2=80=A6'=20menuitem?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/service.c | 92 +++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 54 insertions(+), 38 deletions(-) diff --git a/src/service.c b/src/service.c index 8d82355..1f3fe29 100644 --- a/src/service.c +++ b/src/service.c @@ -709,65 +709,81 @@ get_appointment_time_format (struct IndicatorDatetimeAppt * appt, GDateTime * n return fmt; } -static GMenuModel * -create_appointments_section (IndicatorDatetimeService * self) +static void +add_appointments (IndicatorDatetimeService * self, GMenu * menu) { - priv_t * p = self->priv; - GMenu * menu = g_menu_new (); + GDateTime * now = indicator_datetime_service_get_localtime (self); + GSList * appts; + GSList * l; - if (g_settings_get_boolean (p->settings, SETTINGS_SHOW_EVENTS_S)) + /* build appointment menuitems */ + appts = get_upcoming_appointments (self); + for (l=appts; l!=NULL; l=l->next) { - GSList * l; - GSList * appts; + struct IndicatorDatetimeAppt * appt = l->data; + char * fmt = get_appointment_time_format (appt, now); + const gint64 unix_time = g_date_time_to_unix (appt->begin); GMenuItem * menu_item; - GDateTime * now = indicator_datetime_service_get_localtime (self); - - /* build appointment menuitems */ - appts = get_upcoming_appointments (self); - for (l=appts; l!=NULL; l=l->next) - { - struct IndicatorDatetimeAppt * appt = l->data; - char * fmt = get_appointment_time_format (appt, now); - const gint64 unix_time = g_date_time_to_unix (appt->begin); - menu_item = g_menu_item_new (appt->summary, NULL); + menu_item = g_menu_item_new (appt->summary, NULL); - if (!appt->has_alarms) - g_menu_item_set_attribute (menu_item, "x-canonical-color", - "s", appt->color); + if (!appt->has_alarms) + g_menu_item_set_attribute (menu_item, "x-canonical-color", + "s", appt->color); - g_menu_item_set_attribute (menu_item, "x-canonical-time", + g_menu_item_set_attribute (menu_item, "x-canonical-time", "x", unix_time); - g_menu_item_set_attribute (menu_item, "x-canonical-time-format", + g_menu_item_set_attribute (menu_item, "x-canonical-time-format", "s", fmt); - g_menu_item_set_attribute (menu_item, "x-canonical-type", + g_menu_item_set_attribute (menu_item, "x-canonical-type", "s", appt->has_alarms ? "com.canonical.indicator.alarm" : "com.canonical.indicator.appointment"); - g_menu_item_set_action_and_target_value (menu_item, + g_menu_item_set_action_and_target_value (menu_item, "indicator.activate-planner", g_variant_new_int64 (unix_time)); - g_menu_append_item (menu, menu_item); - g_object_unref (menu_item); - g_free (fmt); - } + g_menu_append_item (menu, menu_item); + g_object_unref (menu_item); + g_free (fmt); + } - /* build 'add event' menuitem */ + /* cleanup */ + g_date_time_unref (now); + g_slist_free_full (appts, (GDestroyNotify)indicator_datetime_appt_free); +} + +static GMenuModel * +create_phone_appointments_section (IndicatorDatetimeService * self) +{ + GMenu * menu = g_menu_new (); + + add_appointments (self, menu); + + return G_MENU_MODEL (menu); +} + +static GMenuModel * +create_desktop_appointments_section (IndicatorDatetimeService * self) +{ + GMenu * menu = g_menu_new (); + + if (g_settings_get_boolean (self->priv->settings, SETTINGS_SHOW_EVENTS_S)) + { + GMenuItem * menu_item; + + add_appointments (self, menu); + + /* add the 'Add Event…' menuitem */ menu_item = g_menu_item_new (_("Add Event…"), NULL); g_menu_item_set_action_and_target_value (menu_item, "indicator.activate-planner", g_variant_new_int64 (0)); g_menu_append_item (menu, menu_item); g_object_unref (menu_item); - - /* cleanup */ - g_date_time_unref (now); - g_slist_free_full (appts, (GDestroyNotify)indicator_datetime_appt_free); } return G_MENU_MODEL (menu); } - /*** **** **** LOCATIONS SECTION @@ -1174,13 +1190,13 @@ create_menu (IndicatorDatetimeService * self, int profile) switch (profile) { case PROFILE_PHONE: - sections[n++] = create_appointments_section (self); + sections[n++] = create_phone_appointments_section (self); sections[n++] = create_phone_settings_section (self); break; case PROFILE_DESKTOP: sections[n++] = create_calendar_section (self); - sections[n++] = create_appointments_section (self); + sections[n++] = create_desktop_appointments_section (self); sections[n++] = create_locations_section (self); sections[n++] = create_desktop_settings_section (self); break; @@ -1374,8 +1390,8 @@ rebuild_now (IndicatorDatetimeService * self, int sections) if (sections & SECTION_APPOINTMENTS) { - rebuild_section (phone->submenu, 0, create_appointments_section (self)); - rebuild_section (desktop->submenu, 1, create_appointments_section (self)); + rebuild_section (phone->submenu, 0, create_phone_appointments_section (self)); + rebuild_section (desktop->submenu, 1, create_desktop_appointments_section (self)); } if (sections & SECTION_LOCATIONS) -- cgit v1.2.3 From eb32ed8ddbf819e02dccb952d381e8bed0460016 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 25 Jul 2013 21:49:51 -0500 Subject: add calendar section for the phone menu --- src/service.c | 86 +++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 29 deletions(-) diff --git a/src/service.c b/src/service.c index 1f3fe29..911e8f4 100644 --- a/src/service.c +++ b/src/service.c @@ -604,41 +604,67 @@ update_calendar_action_state (IndicatorDatetimeService * self) create_calendar_state (self)); } -static GMenuModel * -create_calendar_section (IndicatorDatetimeService * self) +static void +add_localtime_menuitem (GMenu * menu, + IndicatorDatetimeService * self, + const char * time_format) { + GDateTime * now; char * label; GMenuItem * menu_item; - GDateTime * now; - GMenu * menu = g_menu_new (); - /* create the local date menuitem */ now = indicator_datetime_service_get_localtime (self); - label = g_date_time_format (now, _("%A, %e %B %Y")); + label = g_date_time_format (now, time_format); menu_item = g_menu_item_new (label, NULL); - g_menu_item_set_action_and_target_value (menu_item, "indicator.activate-planner", - g_variant_new_int64(0)); + g_menu_item_set_action_and_target_value (menu_item, "indicator.activate-planner", g_variant_new_int64(0)); g_menu_append_item (menu, menu_item); + g_object_unref (menu_item); g_free (label); g_date_time_unref (now); +} + +static void +add_calendar_menuitem (GMenu * menu) +{ + char * label; + GMenuItem * menu_item; + + label = g_strdup ("[calendar]"); + menu_item = g_menu_item_new ("[calendar]", NULL); + g_menu_item_set_action_and_target_value (menu_item, "indicator.calendar", g_variant_new_int64(0)); + g_menu_item_set_attribute (menu_item, "x-canonical-type", "s", "com.canonical.indicator.calendar"); + g_menu_item_set_attribute (menu_item, "activation-action", "s", "indicator.activate-planner"); + + g_menu_append_item (menu, menu_item); + g_object_unref (menu_item); + g_free (label); +} + +static GMenuModel * +create_desktop_calendar_section (IndicatorDatetimeService * self) +{ + GMenu * menu = g_menu_new (); + + /* strftime(3) format string to show the day of the week and the date */ + add_localtime_menuitem (menu, self, _("%A, %e %B %Y")); - /* create the calendar menuitem */ if (g_settings_get_boolean (self->priv->settings, SETTINGS_SHOW_CALENDAR_S)) - { - label = g_strdup ("[calendar]"); - menu_item = g_menu_item_new ("[calendar]", NULL); - g_menu_item_set_action_and_target_value (menu_item, - "indicator.calendar", - g_variant_new_int64(0)); - g_menu_item_set_attribute (menu_item, "x-canonical-type", - "s", "com.canonical.indicator.calendar"); - g_menu_item_set_attribute (menu_item, "activation-action", - "s", "indicator.activate-planner"); - g_menu_append_item (menu, menu_item); - g_object_unref (menu_item); - g_free (label); - } + add_calendar_menuitem (menu); + + return G_MENU_MODEL (menu); +} + +static GMenuModel * +create_phone_calendar_section (IndicatorDatetimeService * self) +{ + GMenu * menu = g_menu_new (); + + /* strftime(3) format string to show day of week */ + add_localtime_menuitem (menu, self, _("%A")); + + /* strftime(3) format string to show date */ + add_localtime_menuitem (menu, self, _("%e %B %Y")); return G_MENU_MODEL (menu); } @@ -1190,19 +1216,20 @@ create_menu (IndicatorDatetimeService * self, int profile) switch (profile) { case PROFILE_PHONE: + sections[n++] = create_phone_calendar_section (self); sections[n++] = create_phone_appointments_section (self); sections[n++] = create_phone_settings_section (self); break; case PROFILE_DESKTOP: - sections[n++] = create_calendar_section (self); + sections[n++] = create_desktop_calendar_section (self); sections[n++] = create_desktop_appointments_section (self); sections[n++] = create_locations_section (self); sections[n++] = create_desktop_settings_section (self); break; case PROFILE_GREETER: - sections[n++] = create_calendar_section (self); + sections[n++] = create_desktop_calendar_section (self); break; } @@ -1384,13 +1411,14 @@ rebuild_now (IndicatorDatetimeService * self, int sections) if (sections & SECTION_CALENDAR) { - rebuild_section (desktop->submenu, 0, create_calendar_section (self)); - rebuild_section (greeter->submenu, 0, create_calendar_section (self)); + rebuild_section (phone->submenu, 0, create_phone_calendar_section (self)); + rebuild_section (desktop->submenu, 0, create_desktop_calendar_section (self)); + rebuild_section (greeter->submenu, 0, create_desktop_calendar_section (self)); } if (sections & SECTION_APPOINTMENTS) { - rebuild_section (phone->submenu, 0, create_phone_appointments_section (self)); + rebuild_section (phone->submenu, 1, create_phone_appointments_section (self)); rebuild_section (desktop->submenu, 1, create_desktop_appointments_section (self)); } @@ -1401,7 +1429,7 @@ rebuild_now (IndicatorDatetimeService * self, int sections) if (sections & SECTION_SETTINGS) { - rebuild_section (phone->submenu, 1, create_phone_settings_section (self)); + rebuild_section (phone->submenu, 2, create_phone_settings_section (self)); rebuild_section (desktop->submenu, 3, create_desktop_settings_section (self)); } } -- cgit v1.2.3 From c79fd08f7e54a466f0bc78c6abb51767cf1295eb Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 25 Jul 2013 22:05:49 -0500 Subject: add a calendar icon to the todays-date menuitems as per spec --- src/service.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/service.c b/src/service.c index 911e8f4..4b65508 100644 --- a/src/service.c +++ b/src/service.c @@ -607,7 +607,8 @@ update_calendar_action_state (IndicatorDatetimeService * self) static void add_localtime_menuitem (GMenu * menu, IndicatorDatetimeService * self, - const char * time_format) + const char * time_format, + const char * icon_name) { GDateTime * now; char * label; @@ -616,6 +617,8 @@ add_localtime_menuitem (GMenu * menu, now = indicator_datetime_service_get_localtime (self); label = g_date_time_format (now, time_format); menu_item = g_menu_item_new (label, NULL); + if (icon_name && *icon_name) + g_menu_item_set_attribute (menu_item, G_MENU_ATTRIBUTE_ICON, "s", icon_name); g_menu_item_set_action_and_target_value (menu_item, "indicator.activate-planner", g_variant_new_int64(0)); g_menu_append_item (menu, menu_item); @@ -647,7 +650,7 @@ create_desktop_calendar_section (IndicatorDatetimeService * self) GMenu * menu = g_menu_new (); /* strftime(3) format string to show the day of the week and the date */ - add_localtime_menuitem (menu, self, _("%A, %e %B %Y")); + add_localtime_menuitem (menu, self, _("%A, %e %B %Y"), "calendar"); if (g_settings_get_boolean (self->priv->settings, SETTINGS_SHOW_CALENDAR_S)) add_calendar_menuitem (menu); @@ -661,10 +664,10 @@ create_phone_calendar_section (IndicatorDatetimeService * self) GMenu * menu = g_menu_new (); /* strftime(3) format string to show day of week */ - add_localtime_menuitem (menu, self, _("%A")); + add_localtime_menuitem (menu, self, _("%A"), NULL); /* strftime(3) format string to show date */ - add_localtime_menuitem (menu, self, _("%e %B %Y")); + add_localtime_menuitem (menu, self, _("%e %B %Y"), "calendar"); return G_MENU_MODEL (menu); } -- cgit v1.2.3 From 23c79e10fcced9f2721d6b72780f7318943e82e3 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 25 Jul 2013 22:11:17 -0500 Subject: in the phone menu, add a 'Clock' menuitem above the alarm and appointment events. --- src/service.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/service.c b/src/service.c index 4b65508..874c866 100644 --- a/src/service.c +++ b/src/service.c @@ -784,6 +784,12 @@ static GMenuModel * create_phone_appointments_section (IndicatorDatetimeService * self) { GMenu * menu = g_menu_new (); + GMenuItem * menu_item; + + menu_item = g_menu_item_new (_("Clock"), NULL); + g_menu_item_set_attribute (menu_item, G_MENU_ATTRIBUTE_ICON, "s", "clock"); + g_menu_append_item (menu, menu_item); + g_object_unref (menu_item); add_appointments (self, menu); -- cgit v1.2.3 From 2c8cf9196bea17d20b9afd680f679eb285c5dc81 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 26 Jul 2013 08:29:25 -0500 Subject: add the phone's header action --- src/service.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 92 insertions(+), 10 deletions(-) diff --git a/src/service.c b/src/service.c index 874c866..c8781eb 100644 --- a/src/service.c +++ b/src/service.c @@ -113,7 +113,8 @@ struct _IndicatorDatetimeServicePrivate GDateTime * calendar_date; GSimpleActionGroup * actions; - GSimpleAction * header_action; + GSimpleAction * phone_header_action; + GSimpleAction * desktop_header_action; GSimpleAction * calendar_action; GDBusProxy * login1_manager; @@ -467,16 +468,15 @@ get_header_label_format_string (IndicatorDatetimeService * self) } static GVariant * -create_header_state (IndicatorDatetimeService * self) +create_desktop_header_state (IndicatorDatetimeService * self) { GVariantBuilder b; gchar * fmt; gchar * str; gboolean visible; GDateTime * now; - priv_t * p = self->priv; - visible = g_settings_get_boolean (p->settings, SETTINGS_SHOW_CLOCK_S); + visible = g_settings_get_boolean (self->priv->settings, SETTINGS_SHOW_CLOCK_S); /* build the time string for the label & a11y */ fmt = get_header_label_format_string (self); @@ -500,6 +500,54 @@ create_header_state (IndicatorDatetimeService * self) return g_variant_builder_end (&b); } +static gboolean +service_has_alarms (IndicatorDatetimeService * self); + +static GVariant * +create_phone_header_state (IndicatorDatetimeService * self) +{ + GVariantBuilder b; + GDateTime * now; + const gchar * fmt; + gchar * label; + gboolean has_alarms; + gchar * a11y; + + g_variant_builder_init (&b, G_VARIANT_TYPE("a{sv}")); + + /* label */ + now = indicator_datetime_service_get_localtime (self); + fmt = _("%I:%M %p"); + label = g_date_time_format (now, fmt); + g_variant_builder_add (&b, "{sv}", "label", g_variant_new_string (label)); + + /* icon */ + if ((has_alarms = service_has_alarms (self))) + { + GIcon * icon; + icon = g_themed_icon_new_with_default_fallbacks ("alarm-symbolic"); + g_variant_builder_add (&b, "{sv}", "icon", g_icon_serialize (icon)); + g_object_unref (icon); + } + + /* a11y */ + if (has_alarms) + a11y = g_strdup_printf (_("%s (has alarms)"), label); + else + a11y = g_strdup (label); + g_variant_builder_add (&b, "{sv}", "accessible-desc", + g_variant_new_string (a11y)); + + /* visible */ + g_variant_builder_add (&b, "{sv}", "visible", g_variant_new_boolean (TRUE)); + + /* cleanup */ + g_free (a11y); + g_free (label); + g_date_time_unref (now); + return g_variant_builder_end (&b); +} + /*** **** @@ -710,6 +758,25 @@ get_upcoming_appointments (IndicatorDatetimeService * self) return appts; } +static gboolean +service_has_alarms (IndicatorDatetimeService * self) +{ + gboolean has_alarms = FALSE; + GSList * appts; + GSList * l; + + appts = get_upcoming_appointments (self); + for (l=appts; l!=NULL; l=l->next) + { + struct IndicatorDatetimeAppt * appt = l->data; + if ((has_alarms = appt->has_alarms)) + break; + } + + g_slist_free_full (appts, (GDestroyNotify)indicator_datetime_appt_free); + return has_alarms; +} + static char * get_appointment_time_format (struct IndicatorDatetimeAppt * appt, GDateTime * now) { @@ -1216,6 +1283,7 @@ create_menu (IndicatorDatetimeService * self, int profile) GMenu * submenu; GMenuItem * header; GMenuModel * sections[16]; + const gchar * header_action; int i; int n = 0; @@ -1228,6 +1296,7 @@ create_menu (IndicatorDatetimeService * self, int profile) sections[n++] = create_phone_calendar_section (self); sections[n++] = create_phone_appointments_section (self); sections[n++] = create_phone_settings_section (self); + header_action = "indicator.phone-header"; break; case PROFILE_DESKTOP: @@ -1235,10 +1304,12 @@ create_menu (IndicatorDatetimeService * self, int profile) sections[n++] = create_desktop_appointments_section (self); sections[n++] = create_locations_section (self); sections[n++] = create_desktop_settings_section (self); + header_action = "indicator.desktop-header"; break; case PROFILE_GREETER: sections[n++] = create_desktop_calendar_section (self); + header_action = "indicator.desktop-header"; break; } @@ -1253,7 +1324,7 @@ create_menu (IndicatorDatetimeService * self, int profile) } /* add submenu to the header */ - header = g_menu_item_new (NULL, "indicator._header"); + header = g_menu_item_new (NULL, header_action); g_menu_item_set_attribute (header, "x-canonical-type", "s", "com.canonical.indicator.root"); g_menu_item_set_submenu (header, G_MENU_MODEL (submenu)); @@ -1371,10 +1442,17 @@ init_gactions (IndicatorDatetimeService * self) G_N_ELEMENTS(entries), self); - /* add the header action */ - a = g_simple_action_new_stateful ("_header", NULL, create_header_state (self)); + /* add the header actions */ + + a = g_simple_action_new_stateful ("desktop-header", NULL, + create_desktop_header_state (self)); + g_simple_action_group_insert (p->actions, G_ACTION(a)); + p->desktop_header_action = a; + + a = g_simple_action_new_stateful ("phone-header", NULL, + create_phone_header_state (self)); g_simple_action_group_insert (p->actions, G_ACTION(a)); - p->header_action = a; + p->phone_header_action = a; /* add the calendar action */ a = g_simple_action_new_stateful ("calendar", @@ -1415,7 +1493,10 @@ rebuild_now (IndicatorDatetimeService * self, int sections) if (sections & SECTION_HEADER) { - g_simple_action_set_state (p->header_action, create_header_state (self)); + g_simple_action_set_state (p->desktop_header_action, + create_desktop_header_state (self)); + g_simple_action_set_state (p->phone_header_action, + create_phone_header_state (self)); } if (sections & SECTION_CALENDAR) @@ -1678,7 +1759,8 @@ my_dispose (GObject * o) g_clear_object (&p->planner); g_clear_object (&p->calendar_action); - g_clear_object (&p->header_action); + g_clear_object (&p->desktop_header_action); + g_clear_object (&p->phone_header_action); g_clear_object (&p->conn); G_OBJECT_CLASS (indicator_datetime_service_parent_class)->dispose (o); -- cgit v1.2.3 From 18012d5e396e87d1c0c5534c35c5d0de82c2f7aa Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 26 Jul 2013 13:26:03 -0500 Subject: add 'terse' time formats for phone menu to match the spec. --- src/datetime-prefs-locations.c | 2 +- src/service.c | 33 ++-- src/settings-shared.h | 29 ---- src/utils.c | 349 ++++++++++++++++++++++++++++------------- src/utils.h | 32 +++- 5 files changed, 286 insertions(+), 159 deletions(-) diff --git a/src/datetime-prefs-locations.c b/src/datetime-prefs-locations.c index 4bbf053..bc044a2 100644 --- a/src/datetime-prefs-locations.c +++ b/src/datetime-prefs-locations.c @@ -428,7 +428,7 @@ update_times (GtkWidget * dlg) if (strzone && *strzone) { GTimeZone * tz = g_time_zone_new (strzone); GDateTime * now_tz = g_date_time_to_timezone (now, tz); - gchar * format = generate_format_string_at_time (now, now_tz); + gchar * format = generate_full_format_string_at_time (now, now_tz); gchar * time_str = g_date_time_format (now_tz, format); gchar * old_time_str; diff --git a/src/service.c b/src/service.c index c8781eb..b52556d 100644 --- a/src/service.c +++ b/src/service.c @@ -461,7 +461,7 @@ get_header_label_format_string (IndicatorDatetimeService * self) { gboolean show_day = g_settings_get_boolean (s, SETTINGS_SHOW_DAY_S); gboolean show_date = g_settings_get_boolean (s, SETTINGS_SHOW_DATE_S); - fmt = generate_format_string_full (show_day, show_date); + fmt = generate_full_format_string (show_day, show_date); } return fmt; @@ -517,7 +517,7 @@ create_phone_header_state (IndicatorDatetimeService * self) /* label */ now = indicator_datetime_service_get_localtime (self); - fmt = _("%I:%M %p"); + fmt = get_terse_time_format_string (now); label = g_date_time_format (now, fmt); g_variant_builder_add (&b, "{sv}", "label", g_variant_new_string (label)); @@ -778,35 +778,36 @@ service_has_alarms (IndicatorDatetimeService * self) } static char * -get_appointment_time_format (struct IndicatorDatetimeAppt * appt, GDateTime * now) +get_appointment_time_format (struct IndicatorDatetimeAppt * appt, + GDateTime * now, + gboolean terse) { char * fmt; gboolean full_day = g_date_time_difference (appt->end, appt->begin) == G_TIME_SPAN_DAY; if (appt->is_daily) { - char * time_string = generate_format_string_full (FALSE, FALSE); - fmt = join_date_and_time_format_strings (_("Daily"), time_string); - g_free (time_string); + const char * time_fmt = terse ? get_terse_time_format_string (appt->begin) + : get_full_time_format_string (); + fmt = join_date_and_time_format_strings (_("Daily"), time_fmt); } else if (full_day) { - /* TRANSLATORS: This is a strftime string for the day for full day events - in the menu. It should most likely be either '%A' for a full text day - (Wednesday) or '%a' for a shortened one (Wed). You should only need to - change for '%a' in the case of langauges with very long day names. */ + /* TRANSLATORS: a strftime(3) format showing full day events. + * "%A" means a full text day (Wednesday), "%a" means abbreviated (Wed). */ fmt = g_strdup (_("%A")); } else { - fmt = generate_format_string_at_time (now, appt->begin); + fmt = terse ? generate_terse_format_string_at_time (now, appt->begin) + : generate_full_format_string_at_time (now, appt->begin); } return fmt; } static void -add_appointments (IndicatorDatetimeService * self, GMenu * menu) +add_appointments (IndicatorDatetimeService * self, GMenu * menu, gboolean terse) { GDateTime * now = indicator_datetime_service_get_localtime (self); GSList * appts; @@ -817,7 +818,7 @@ add_appointments (IndicatorDatetimeService * self, GMenu * menu) for (l=appts; l!=NULL; l=l->next) { struct IndicatorDatetimeAppt * appt = l->data; - char * fmt = get_appointment_time_format (appt, now); + char * fmt = get_appointment_time_format (appt, now, terse); const gint64 unix_time = g_date_time_to_unix (appt->begin); GMenuItem * menu_item; @@ -858,7 +859,7 @@ create_phone_appointments_section (IndicatorDatetimeService * self) g_menu_append_item (menu, menu_item); g_object_unref (menu_item); - add_appointments (self, menu); + add_appointments (self, menu, TRUE); return G_MENU_MODEL (menu); } @@ -872,7 +873,7 @@ create_desktop_appointments_section (IndicatorDatetimeService * self) { GMenuItem * menu_item; - add_appointments (self, menu); + add_appointments (self, menu, FALSE); /* add the 'Add Event…' menuitem */ menu_item = g_menu_item_new (_("Add Event…"), NULL); @@ -1100,7 +1101,7 @@ create_locations_section (IndicatorDatetimeService * self) detailed_action = g_strdup_printf ("indicator.set-location::%s %s", loc->zone, loc->name); - fmt = generate_format_string_at_time (now, loc->local_time); + fmt = generate_full_format_string_at_time (now, loc->local_time); menu_item = g_menu_item_new (label, detailed_action); g_menu_item_set_attribute (menu_item, "x-canonical-type", diff --git a/src/settings-shared.h b/src/settings-shared.h index 8c14f1e..27ce34c 100644 --- a/src/settings-shared.h +++ b/src/settings-shared.h @@ -37,33 +37,4 @@ with this program. If not, see . #define SETTINGS_LOCATIONS_S "locations" #define SETTINGS_TIMEZONE_NAME_S "timezone-name" -enum { - SETTINGS_TIME_LOCALE = 0, - SETTINGS_TIME_12_HOUR = 1, - SETTINGS_TIME_24_HOUR = 2, - SETTINGS_TIME_CUSTOM = 3 -}; - -/* TRANSLATORS: A format string for the strftime function for - a clock showing 12-hour time without seconds. */ -#define DEFAULT_TIME_12_FORMAT N_("%l:%M %p") - -/* TRANSLATORS: A format string for the strftime function for - a clock showing 24-hour time without seconds. */ -#define DEFAULT_TIME_24_FORMAT N_("%H:%M") - -#define DEFAULT_TIME_FORMAT DEFAULT_TIME_12_FORMAT -#define DEFAULT_TIME_FORMAT_WITH_DAY DEFAULT_TIME_12_FORMAT_WITH_DAY - -/* TRANSLATORS: A format string for the strftime function for - a clock showing the day of the week and the time in 12-hour format without - seconds. */ -#define DEFAULT_TIME_12_FORMAT_WITH_DAY N_("%a %l:%M %p") - -/* TRANSLATORS: A format string for the strftime function for - a clock showing the day of the week and the time in 24-hour format without - seconds. Information is available in this Launchpad answer: - https://answers.launchpad.net/ubuntu/+source/indicator-datetime/+question/149752 */ -#define DEFAULT_TIME_24_FORMAT_WITH_DAY N_("%a %H:%M") - #endif diff --git a/src/utils.c b/src/utils.c index a408f68..1297981 100644 --- a/src/utils.c +++ b/src/utils.c @@ -118,7 +118,7 @@ get_current_zone_name (const gchar * location) } /* Translate msg according to the locale specified by LC_TIME */ -static char * +static const char * T_(const char *msg) { /* General strategy here is to make sure LANGUAGE is empty (since that @@ -158,127 +158,262 @@ gchar * join_date_and_time_format_strings (const char * date_string, const char * time_string) { - /* TRANSLATORS: This is a format string passed to strftime to combine the - * date and the time. The value of "%s\xE2\x80\x82%s" will result in a - * string like this in US English 12-hour time: 'Fri Jul 16 11:50 AM'. - * The space in between date and time is a Unicode en space - * (E28082 in UTF-8 hex). */ - return g_strdup_printf (T_("%s\xE2\x80\x82%s"), date_string, time_string); + gchar * str; + + if (date_string && time_string) + { + /* TRANSLATORS: This is a format string passed to strftime to combine the + * date and the time. The value of "%s\xE2\x80\x82%s" will result in a + * string like this in US English 12-hour time: 'Fri Jul 16 11:50 AM'. + * The space in between date and time is a Unicode en space + * (E28082 in UTF-8 hex). */ + str = g_strdup_printf (T_("%s\xE2\x80\x82%s"), date_string, time_string); + } + else if (date_string) + { + str = g_strdup_printf (T_("%s"), date_string); + } + else /* time_string */ + { + str = g_strdup_printf (T_("%s"), time_string); + } + + return str; +} + +/*** +**** +***/ + +typedef enum +{ + DATE_PROXIMITY_TODAY, + DATE_PROXIMITY_TOMORROW, + DATE_PROXIMITY_WEEK, + DATE_PROXIMITY_FAR +} +date_proximity_t; + +static date_proximity_t +get_date_proximity (GDateTime * now, GDateTime * time) +{ + date_proximity_t prox = DATE_PROXIMITY_FAR; + gint now_year, now_month, now_day; + gint time_year, time_month, time_day; + + /* does it happen today? */ + g_date_time_get_ymd (now, &now_year, &now_month, &now_day); + g_date_time_get_ymd (time, &time_year, &time_month, &time_day); + if ((now_year == time_year) && (now_month == time_month) && (now_day == time_day)) + prox = DATE_PROXIMITY_TODAY; + + /* does it happen tomorrow? */ + if (prox == DATE_PROXIMITY_FAR) + { + GDateTime * tomorrow; + gint tom_year, tom_month, tom_day; + + tomorrow = g_date_time_add_days (now, 1); + g_date_time_get_ymd (tomorrow, &tom_year, &tom_month, &tom_day); + if ((tom_year == time_year) && (tom_month == time_month) && (tom_day == time_day)) + prox = DATE_PROXIMITY_TOMORROW; + + g_date_time_unref (tomorrow); + } + + /* does it happen this week? */ + if (prox == DATE_PROXIMITY_FAR) + { + GDateTime * week; + GDateTime * week_bound; + + week = g_date_time_add_days (now, 6); + week_bound = g_date_time_new_local (g_date_time_get_year(week), + g_date_time_get_month (week), + g_date_time_get_day_of_month(week), + 23, 59, 59.9); + + if (g_date_time_compare (time, week_bound) <= 0) + prox = DATE_PROXIMITY_WEEK; + + g_date_time_unref (week_bound); + g_date_time_unref (week); + } + + return prox; } -/* Tries to figure out what our format string should be. Lots - of translator comments in here. */ +/* + * "Terse" time & date format strings + * + * Used on the phone menu where space is at a premium, these strings + * express the time and date in as brief a form as possible. + * + * Examples from spec: + * 1. "Daily 6:30 AM" + * 2. "5:07 PM" (note date is omitted; today's date is implicit) + * 3. "Daily 12 PM" (note minutes are omitted for on-the-hour times) + * 4. "Tomorrow 7 AM" (note "Tomorrow" is used instead of a day of week) + */ + +static const gchar * +get_terse_date_format_string (date_proximity_t proximity) +{ + const gchar * fmt; + + switch (proximity) + { + case DATE_PROXIMITY_TODAY: fmt = NULL; break; + case DATE_PROXIMITY_TOMORROW: fmt = T_("Tomorrow"); break; + case DATE_PROXIMITY_WEEK: fmt = T_("%a"); break; + default: fmt = T_("%d %b"); break; + } + + return fmt; +} + +const gchar * +get_terse_time_format_string (GDateTime * time) +{ + const gchar * fmt; + + if (g_date_time_get_minute (time) != 0) + fmt = T_("%I:%M %p"); + else + fmt = T_("%I %p"); + + return fmt; +} + gchar * -generate_format_string_full (gboolean show_day, gboolean show_date) +generate_terse_format_string_at_time (GDateTime * now, GDateTime * time) { - gboolean twelvehour = TRUE; + const date_proximity_t prox = get_date_proximity (now, time); + const gchar * date_fmt = get_terse_date_format_string (prox); + const gchar * time_fmt = get_terse_time_format_string (time); + return join_date_and_time_format_strings (date_fmt, time_fmt); +} - GSettings * settings = g_settings_new (SETTINGS_INTERFACE); - gint time_mode = g_settings_get_enum (settings, SETTINGS_TIME_FORMAT_S); - gboolean show_seconds = g_settings_get_boolean (settings, SETTINGS_SHOW_SECONDS_S); - g_object_unref (settings); +/*** +**** FULL +***/ - if (time_mode == SETTINGS_TIME_LOCALE) { - twelvehour = is_locale_12h(); - } else if (time_mode == SETTINGS_TIME_24_HOUR) { - twelvehour = FALSE; - } +static const gchar * +get_full_date_format_string (gboolean show_day, gboolean show_date) +{ + const gchar * fmt; + + if (show_date && show_day) + /* TRANSLATORS: a strftime(3) format showing the date and weekday */ + fmt = T_("%a %b %e"); + else if (show_date) + /* TRANSLATORS: a strftime(3) format showing the date */ + fmt = T_("%b %e"); + else if (show_day) + /* TRANSLATORS: a strftime(3) format showing the weekday */ + fmt = T_("%a"); + else + fmt = NULL; + + return fmt; +} - const gchar * time_string = NULL; - if (twelvehour) { - if (show_seconds) { - /* TRANSLATORS: A format string for the strftime function for - a clock showing 12-hour time with seconds. */ - time_string = T_("%l:%M:%S %p"); - } else { - time_string = T_(DEFAULT_TIME_12_FORMAT); - } - } else { - if (show_seconds) { - /* TRANSLATORS: A format string for the strftime function for - a clock showing 24-hour time with seconds. */ - time_string = T_("%H:%M:%S"); - } else { - time_string = T_(DEFAULT_TIME_24_FORMAT); - } - } - - /* Checkpoint, let's not fail */ - g_return_val_if_fail(time_string != NULL, g_strdup(DEFAULT_TIME_FORMAT)); - - /* If there's no date or day let's just leave now and - not worry about the rest of this code */ - if (!show_date && !show_day) { - return g_strdup(time_string); - } - const gchar * date_string = NULL; - if (show_date && show_day) { - /* TRANSLATORS: This is a format string passed to strftime to represent - the day of the week, the month and the day of the month. */ - date_string = T_("%a %b %e"); - } else if (show_date) { - /* TRANSLATORS: This is a format string passed to strftime to represent - the month and the day of the month. */ - date_string = T_("%b %e"); - } else if (show_day) { - /* TRANSLATORS: This is a format string passed to strftime to represent - the day of the week. */ - date_string = T_("%a"); - } +/* + * "Full" time & date format strings + * + * These are used on the desktop menu & header and honors the + * GSettings entries for 12/24hr mode and whether or not to show seconds. + * + */ - /* Check point, we should have a date string */ - g_return_val_if_fail(date_string != NULL, g_strdup(time_string)); +enum +{ + SETTINGS_TIME_LOCALE = 0, + SETTINGS_TIME_12_HOUR = 1, + SETTINGS_TIME_24_HOUR = 2, + SETTINGS_TIME_CUSTOM = 3 +}; + +const gchar * +get_full_time_format_string (void) +{ + GSettings * settings; + gboolean twelvehour; + gboolean show_seconds; + const gchar * fmt; - return join_date_and_time_format_strings (date_string, time_string); + settings = g_settings_new (SETTINGS_INTERFACE); + + show_seconds = g_settings_get_boolean (settings, SETTINGS_SHOW_SECONDS_S); + + switch (g_settings_get_enum (settings, SETTINGS_TIME_FORMAT_S)) + { + case SETTINGS_TIME_LOCALE: + twelvehour = is_locale_12h(); + break; + + case SETTINGS_TIME_24_HOUR: + twelvehour = FALSE; + break; + + default: + twelvehour = TRUE; + break; + } + + g_object_unref (settings); + + if (twelvehour && show_seconds) + /* TRANSLATORS: a strftime(3) format for 12hr time w/seconds */ + fmt = T_("%l:%M:%S %p"); + else if (twelvehour) + /* TRANSLATORS: a strftime(3) format for 12hr time */ + fmt = T_("%l:%M %p"); + else if (show_seconds) + /* TRANSLATORS: a strftime(3) format for 24hr time w/seconds */ + fmt = T_("%H:%M:%S"); + else + /* TRANSLATORS: a strftime(3) format for 24hr time */ + fmt = T_("%H:%M"); + + return fmt; } gchar * -generate_format_string_at_time (GDateTime * now, GDateTime * time) +generate_full_format_string (gboolean show_day, gboolean show_date) { - /* This is a bit less free-form than for the main "now" time label. */ - /* If it is today, just the time should be shown (e.g. “3:55 PM”) - If it is a different day this week, the day and time should be shown (e.g. “Wed 3:55 PM”) - If it is after this week, the day, date, and time should be shown (e.g. “Wed 21 Apr 3:55 PM”). - In addition, when presenting the times of upcoming events, the time should be followed by the timezone if it is different from the one the computer is currently set to. For example, “Wed 3:55 PM UTC−5”. */ - gboolean show_day = FALSE; - gboolean show_date = FALSE; - - /* First, are we same day? */ - gint time_year, time_month, time_day; - gint now_year, now_month, now_day; - g_date_time_get_ymd(time, &time_year, &time_month, &time_day); - g_date_time_get_ymd(now, &now_year, &now_month, &now_day); - - if (time_year != now_year || - time_month != now_month || - time_day != now_day) { - /* OK, different days so we must at least show the day. */ - show_day = TRUE; - - /* Is it this week? */ - /* Here, we define "is this week" as yesterday, today, or the next five days */ - GDateTime * past = g_date_time_add_days(now, -1); - GDateTime * future = g_date_time_add_days(now, 5); - GDateTime * past_bound = g_date_time_new_local(g_date_time_get_year(past), - g_date_time_get_month(past), - g_date_time_get_day_of_month(past), - 0, 0, 0.0); - GDateTime * future_bound = g_date_time_new_local(g_date_time_get_year(future), - g_date_time_get_month(future), - g_date_time_get_day_of_month(future), - 23, 59, 59.9); - if (g_date_time_compare(time, past_bound) < 0 || - g_date_time_compare(time, future_bound) > 0) { - show_date = TRUE; - } - g_date_time_unref(past); - g_date_time_unref(future); - g_date_time_unref(past_bound); - g_date_time_unref(future_bound); - } + const gchar * date_fmt = get_full_date_format_string (show_day, show_date); + const gchar * time_fmt = get_full_time_format_string (); + return join_date_and_time_format_strings (date_fmt, time_fmt); +} + +gchar * +generate_full_format_string_at_time (GDateTime * now, GDateTime * time) +{ + gboolean show_day; + gboolean show_date; + + switch (get_date_proximity (now, time)) + { + case DATE_PROXIMITY_TODAY: + show_day = FALSE; + show_date = FALSE; + break; + + case DATE_PROXIMITY_TOMORROW: + case DATE_PROXIMITY_WEEK: + show_day = FALSE; + show_date = TRUE; + break; + + default: + show_day = TRUE; + show_date = TRUE; + break; + } - return generate_format_string_full(show_day, show_date); + return generate_full_format_string (show_day, show_date); } diff --git a/src/utils.h b/src/utils.h index 73bd83a..3b0d0a2 100644 --- a/src/utils.h +++ b/src/utils.h @@ -27,13 +27,33 @@ with this program. If not, see . G_BEGIN_DECLS -gboolean is_locale_12h (void); -void split_settings_location (const gchar * location, gchar ** zone, gchar ** name); -gchar * get_current_zone_name (const gchar * location); -gchar * generate_format_string_full (gboolean show_day, gboolean show_date); -gchar * generate_format_string_at_time (GDateTime * now, GDateTime * time); -gchar * join_date_and_time_format_strings (const char * date, const char * time); +gboolean is_locale_12h (void); +void split_settings_location (const char * location, + char ** zone, + char ** name); + +gchar * get_current_zone_name (const char * location); + +gchar* join_date_and_time_format_strings (const char * date_fmt, + const char * time_fmt); +/*** +**** +***/ + +const gchar * get_terse_time_format_string (GDateTime * time); + +const gchar * get_full_time_format_string (void); + +gchar * generate_terse_format_string_at_time (GDateTime * now, + GDateTime * time); + +gchar * generate_full_format_string (gboolean show_day, + gboolean show_date); + +gchar * generate_full_format_string_at_time (GDateTime * now, + GDateTime * time); + G_END_DECLS #endif -- cgit v1.2.3 From e94e06f6d1708ed30aac8ea9503e17cd618bcae3 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 30 Jul 2013 15:34:03 -0500 Subject: as per discussion in #systems, use 'Recommends: ubuntu-system-settings | gnome-control-center' --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index b3c1db1..221bd22 100644 --- a/debian/control +++ b/debian/control @@ -34,12 +34,12 @@ Package: indicator-datetime Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, - gnome-control-center, geoclue-ubuntu-geoip | geoclue-provider, systemd-services, systemd-shim, Recommends: indicator-applet | indicator-renderer, evolution-data-server, + ubuntu-system-settings | gnome-control-center, Description: Simple clock A simple clock appearing in the indicator bar -- cgit v1.2.3 From d5aaabfd15c782cae1515b5edf221951c43dcb9d Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 30 Jul 2013 15:44:11 -0500 Subject: add i18n comments to get_terse_date_format_string() and get_terse_time_format_string() --- src/utils.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/utils.c b/src/utils.c index 1297981..d18a5cc 100644 --- a/src/utils.c +++ b/src/utils.c @@ -264,10 +264,24 @@ get_terse_date_format_string (date_proximity_t proximity) switch (proximity) { - case DATE_PROXIMITY_TODAY: fmt = NULL; break; - case DATE_PROXIMITY_TOMORROW: fmt = T_("Tomorrow"); break; - case DATE_PROXIMITY_WEEK: fmt = T_("%a"); break; - default: fmt = T_("%d %b"); break; + case DATE_PROXIMITY_TODAY: + /* 'Today' is implicit in the terse case, so no string needed */ + fmt = NULL; + break; + + case DATE_PROXIMITY_TOMORROW: + fmt = T_("Tomorrow"); + break; + + case DATE_PROXIMITY_WEEK: + /* a strftime(3) fmt string for abbreviated day of week */ + fmt = T_("%a"); + break; + + default: + /* a strftime(3) fmt string for day-of-month and abbreviated month */ + fmt = T_("%d %b"); + break; } return fmt; @@ -279,9 +293,15 @@ get_terse_time_format_string (GDateTime * time) const gchar * fmt; if (g_date_time_get_minute (time) != 0) - fmt = T_("%I:%M %p"); + { + /* a strftime(3) fmt string for a HH:MM 12 hour time */ + fmt = T_("%I:%M %p"); + } else - fmt = T_("%I %p"); + { + /* a strftime(3) fmt string for a HH 12 hour time */ + fmt = T_("%I %p"); + } return fmt; } -- cgit v1.2.3 From a60f5e911160d1f0b15e40a1eefe429b5fe973f9 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 30 Jul 2013 16:01:24 -0500 Subject: remove the leading zero from the terse time format string. --- src/utils.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils.c b/src/utils.c index d18a5cc..b99de94 100644 --- a/src/utils.c +++ b/src/utils.c @@ -294,13 +294,13 @@ get_terse_time_format_string (GDateTime * time) if (g_date_time_get_minute (time) != 0) { - /* a strftime(3) fmt string for a HH:MM 12 hour time */ + /* a strftime(3) fmt string for a HH:MM 12 hour time, eg "06:59 PM" */ fmt = T_("%I:%M %p"); } else { - /* a strftime(3) fmt string for a HH 12 hour time */ - fmt = T_("%I %p"); + /* a strftime(3) fmt string for a 12 hour on-the-hour time, eg "7 PM" */ + fmt = T_("%l %p"); } return fmt; -- cgit v1.2.3