diff options
Diffstat (limited to 'src/datetime-service.c')
-rw-r--r-- | src/datetime-service.c | 241 |
1 files changed, 115 insertions, 126 deletions
diff --git a/src/datetime-service.c b/src/datetime-service.c index ccdfe14..1a37fde 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -29,7 +29,6 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <glib/gi18n.h> #include <gio/gio.h> #include <math.h> -#include <gconf/gconf-client.h> #include <libdbusmenu-gtk/menuitem.h> #include <libdbusmenu-glib/server.h> @@ -55,6 +54,8 @@ with this program. If not, see <http://www.gnu.org/licenses/>. /* how often to check for clock skew */ #define SKEW_CHECK_INTERVAL_SEC 10 +#define MAX_APPOINTMENT_MENUITEMS 5 + #define SKEW_DIFF_THRESHOLD_SEC (SKEW_CHECK_INTERVAL_SEC + 5) #ifdef HAVE_CCPANEL @@ -85,13 +86,14 @@ static DbusmenuMenuitem * settings = NULL; static DbusmenuMenuitem * events_separator = NULL; static DbusmenuMenuitem * locations_separator = NULL; static DbusmenuMenuitem * add_appointment = NULL; -static GList * appointments = NULL; +static DbusmenuMenuitem * appointments[MAX_APPOINTMENT_MENUITEMS]; static GSList * location_menu_items = NULL; static GList * comp_instances = NULL; static gboolean updating_appointments = FALSE; static time_t start_time_appointments = (time_t) 0; static GSettings * conf = NULL; -static GConfClient * gconf = NULL; +static ESourceRegistry * source_registry = NULL; +static GList * appointment_sources = NULL; /* Geoclue trackers */ @@ -392,6 +394,15 @@ update_appointment_menu_items_idle (gpointer user_data) return FALSE; } +static void +hide_all_appointments (void) +{ + int i; + + for (i=0; i<MAX_APPOINTMENT_MENUITEMS; i++) + dbusmenu_menuitem_property_set_bool(appointments[i], DBUSMENU_MENUITEM_PROP_ENABLED, FALSE); +} + static gboolean month_changed_cb (DbusmenuMenuitem * menuitem, gchar *name, GVariant *variant, guint timestamp) { @@ -404,11 +415,7 @@ month_changed_cb (DbusmenuMenuitem * menuitem, gchar *name, GVariant *variant, g user. */ dbusmenu_menuitem_property_remove(menuitem, CALENDAR_MENUITEM_PROP_MARKS); - GList * appointment; - for (appointment = appointments; appointment != NULL; appointment = g_list_next(appointment)) { - DbusmenuMenuitem * mi = DBUSMENU_MENUITEM(appointment->data); - dbusmenu_menuitem_property_set_bool(mi, DBUSMENU_MENUITEM_PROP_ENABLED, FALSE); - } + hide_all_appointments (); g_idle_add(update_appointment_menu_items_idle, NULL); return TRUE; @@ -439,11 +446,7 @@ day_selected_cb (DbusmenuMenuitem * menuitem, gchar *name, GVariant *variant, gu } } - GList * appointment; - for (appointment = appointments; appointment != NULL; appointment = g_list_next(appointment)) { - DbusmenuMenuitem * mi = DBUSMENU_MENUITEM(appointment->data); - dbusmenu_menuitem_property_set_bool(mi, DBUSMENU_MENUITEM_PROP_ENABLED, FALSE); - } + hide_all_appointments (); start_time_appointments = new_time; @@ -512,17 +515,7 @@ show_events_changed (void) } else { dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); dbusmenu_menuitem_property_set_bool(events_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); - /* Remove all of the previous appointments */ - if (appointments != NULL) { - g_debug("Hiding old appointments"); - GList * appointment; - for (appointment = appointments; appointment != NULL; appointment = g_list_next(appointment)) { - DbusmenuMenuitem * litem = DBUSMENU_MENUITEM(appointment->data); - g_debug("Hiding old appointment: %p", litem); - // Remove all the existing menu items which are in appointments. - dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(litem), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); - } - } + hide_all_appointments (); stop_ecal_timer(); } } @@ -537,12 +530,8 @@ calendar_app_is_usable (void) g_debug ("found calendar app: '%s'", evo); g_free (evo); - /* confirm that it's got an account set up... */ - GSList *accounts_list = gconf_client_get_list (gconf, "/apps/evolution/mail/accounts", GCONF_VALUE_STRING, NULL); - const guint n = g_slist_length (accounts_list); - g_debug ("found %u evolution accounts", n); - g_slist_free_full (accounts_list, g_free); - return n > 0; + /* see if there are any calendar sources */ + return appointment_sources > 0; } /* Looks for the calendar application and enables the item if @@ -555,19 +544,32 @@ check_for_calendar (gpointer user_data) dbusmenu_menuitem_property_set_bool(date, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); if (!get_greeter_mode () && calendar_app_is_usable()) { + + int i; + int pos = 2; g_signal_connect (G_OBJECT(date), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (activate_cb), "evolution -c calendar"); events_separator = dbusmenu_menuitem_new(); dbusmenu_menuitem_property_set(events_separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); - dbusmenu_menuitem_child_add_position(root, events_separator, 2); + dbusmenu_menuitem_child_add_position(root, events_separator, pos++); + + for (i=0; i<MAX_APPOINTMENT_MENUITEMS; i++) + { + DbusmenuMenuitem * item = dbusmenu_menuitem_new(); + dbusmenu_menuitem_property_set (item, DBUSMENU_MENUITEM_PROP_TYPE, APPOINTMENT_MENUITEM_TYPE); + dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); + dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); + appointments[i] = item; + dbusmenu_menuitem_child_add_position(root, item, pos++); + } + add_appointment = dbusmenu_menuitem_new(); dbusmenu_menuitem_property_set (add_appointment, DBUSMENU_MENUITEM_PROP_LABEL, _("Add Event…")); dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); g_signal_connect(G_OBJECT(add_appointment), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_cb), "evolution -c calendar"); - dbusmenu_menuitem_child_add_position (root, add_appointment, 3); - + dbusmenu_menuitem_child_add_position (root, add_appointment, pos++); if (g_settings_get_boolean(conf, SETTINGS_SHOW_EVENTS_S)) { dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); @@ -636,53 +638,29 @@ comp_instance_free (struct comp_instance* ci) } static gboolean -populate_appointment_instances (ECalClient * client, +populate_appointment_instances (ECalComponent * comp, time_t start, time_t end, gpointer data) { - GSList *ecalcomps, *comp_item; - - if (e_cal_client_get_object_list_as_comps_sync (client, - NULL, - &ecalcomps, - NULL, NULL)) { - - for (comp_item = ecalcomps; comp_item; comp_item = g_slist_next(comp_item)) { - ECalComponent *comp = comp_item->data; - - g_debug("Appending item %p", e_cal_component_get_as_string(comp)); - - ECalComponentVType vtype = e_cal_component_get_vtype (comp); - if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) return FALSE; - - icalproperty_status status; - e_cal_component_get_status (comp, &status); - if (status == ICAL_STATUS_COMPLETED || status == ICAL_STATUS_CANCELLED) return FALSE; - - g_object_ref(comp); - - ECalComponentDateTime datetime; - icaltimezone *appointment_zone = NULL; - icaltimezone *current_zone = NULL; - - if (vtype == E_CAL_COMPONENT_EVENT) - e_cal_component_get_dtstart (comp, &datetime); - else - e_cal_component_get_due (comp, &datetime); - - appointment_zone = icaltimezone_get_builtin_timezone_from_tzid(datetime.tzid); - current_zone = icaltimezone_get_builtin_timezone_from_tzid(current_timezone); - if (!appointment_zone || datetime.value->is_date) { // If it's today put in the current timezone? - appointment_zone = current_zone; - } + const ECalComponentVType vtype = e_cal_component_get_vtype (comp); + + if ((vtype == E_CAL_COMPONENT_EVENT) || (vtype == E_CAL_COMPONENT_TODO)) + { + icalproperty_status status; + e_cal_component_get_status (comp, &status); + + if ((status != ICAL_STATUS_COMPLETED) && (status != ICAL_STATUS_CANCELLED)) + { + gchar * str = e_cal_component_get_as_string (comp); + g_debug("Appending item %s", str); + struct comp_instance *ci = comp_instance_new (comp, start, end, E_SOURCE(data)); + comp_instances = g_list_append (comp_instances, ci); + g_free (str); + } + } - struct comp_instance *ci = comp_instance_new (comp, start, end, E_SOURCE(data)); - comp_instances = g_list_append (comp_instances, ci); - } - return TRUE; - } - return FALSE; + return TRUE; /* tell eds to keep iterating */ } /* Populate the menu with todays, next 5 appointments. @@ -691,7 +669,7 @@ populate_appointment_instances (ECalClient * client, * this is a problem mainly on the EDS side of things, not ours. */ static gboolean -update_appointment_menu_items (gpointer user_data) +update_appointment_menu_items (gpointer unused) { // FFR: we should take into account short term timers, for instance // tea timers, pomodoro timers etc... that people may add, this is hinted to in the spec. @@ -706,7 +684,6 @@ update_appointment_menu_items (gpointer user_data) GError *gerror = NULL; gint i; gint width = 0, height = 0; - ESourceRegistry * src_registry = NULL; GList * sources = NULL; // Get today & work out query times @@ -751,19 +728,10 @@ update_appointment_menu_items (gpointer user_data) g_list_free_full (comp_instances, (GDestroyNotify)comp_instance_free); comp_instances = NULL; - src_registry = e_source_registry_new_sync (NULL, &gerror); - if (!src_registry) { - g_debug("Failed to get access to source registry: %s\n", gerror->message); - return FALSE; - } - - sources = e_source_registry_list_sources(src_registry, E_SOURCE_EXTENSION_CALENDAR); - // Generate instances for all sources - for (s = g_list_first (sources); s; s = g_list_next (s)) { + for (s=appointment_sources; s!=NULL; s=s->next) { ESource *source = E_SOURCE (s->data); - g_signal_connect (G_OBJECT(source), "changed", G_CALLBACK (update_appointment_menu_items), NULL); ECalClient *ecal = e_cal_client_new(source, E_CAL_CLIENT_SOURCE_TYPE_EVENTS, &gerror); icaltimezone* current_zone = icaltimezone_get_builtin_timezone(current_timezone); @@ -785,31 +753,21 @@ update_appointment_menu_items (gpointer user_data) continue; } - e_cal_client_generate_instances (ecal, t1, t2, NULL, - (ECalRecurInstanceFn) populate_appointment_instances, - (gpointer) source, - NULL); + e_cal_client_generate_instances_sync (ecal, + t1, + t2, + populate_appointment_instances, + source); } g_object_unref(ecal); } - g_list_free_full (sources, g_object_unref); g_debug("Number of ECalComponents returned: %d", g_list_length(comp_instances)); GList *sorted_comp_instances = g_list_sort(comp_instances, compare_comp_instances); comp_instances = NULL; g_debug("Components sorted"); - - /* Hiding all of the previous appointments */ - if (appointments != NULL) { - g_debug("Hiding old appointments"); - GList * appointment; - for (appointment = appointments; appointment != NULL; appointment = g_list_next(appointment)) { - DbusmenuMenuitem * litem = DBUSMENU_MENUITEM(appointment->data); - g_debug("Hiding old appointment: %p", litem); - // Remove all the existing menu items which are in appointments. - dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(litem), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); - } - } + + hide_all_appointments (); gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); if (width <= 0) width = 12; @@ -834,7 +792,6 @@ update_appointment_menu_items (gpointer user_data) g_variant_builder_init (&markeddays, G_VARIANT_TYPE ("ai")); i = 0; - GList * cached_appointment = appointments; for (l = sorted_comp_instances; l; l = l->next) { struct comp_instance *ci = l->data; ECalComponent *ecalcomp = ci->comp; @@ -866,28 +823,18 @@ update_appointment_menu_items (gpointer user_data) } else if (vtype == E_CAL_COMPONENT_TODO) { if (ci->end < start_time_appointments) continue; } - - if (i >= 5) continue; - i++; - - if (cached_appointment == NULL) { - g_debug("Create menu item"); - - item = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (item, DBUSMENU_MENUITEM_PROP_TYPE, APPOINTMENT_MENUITEM_TYPE); + + if (i >= MAX_APPOINTMENT_MENUITEMS) + continue; - dbusmenu_menuitem_child_add_position (root, item, 2+i); - appointments = g_list_append (appointments, item); // Keep track of the items here to make them easy to remove - } else { - item = DBUSMENU_MENUITEM(cached_appointment->data); - cached_appointment = g_list_next(cached_appointment); + i++; + item = appointments[i]; - /* Remove the icon as we might not replace it on error */ - dbusmenu_menuitem_property_remove(item, APPOINTMENT_MENUITEM_PROP_ICON); + /* Remove the icon as we might not replace it on error */ + dbusmenu_menuitem_property_remove(item, APPOINTMENT_MENUITEM_PROP_ICON); - /* Remove the activate handler */ - g_signal_handlers_disconnect_matched(G_OBJECT(item), G_SIGNAL_MATCH_FUNC, 0, 0, NULL, G_CALLBACK(activate_cb), NULL); - } + /* Remove the activate handler */ + g_signal_handlers_disconnect_matched(G_OBJECT(item), G_SIGNAL_MATCH_FUNC, 0, 0, NULL, G_CALLBACK(activate_cb), NULL); dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); @@ -1416,6 +1363,34 @@ service_shutdown (IndicatorService * service, gpointer user_data) return; } +static void +free_appointment_sources (void) +{ + g_list_free_full (appointment_sources, g_object_unref); + appointment_sources = NULL; +} + +static void +init_appointment_sources (void) +{ + GList * l; + + appointment_sources = e_source_registry_list_sources (source_registry, E_SOURCE_EXTENSION_CALENDAR); + + for (l=appointment_sources; l!=NULL; l=l->next) + g_signal_connect (G_OBJECT(l->data), "changed", G_CALLBACK (update_appointment_menu_items), NULL); +} + +/* rebuilds both the appointment sources and menu */ +static void +update_appointments (void) +{ + free_appointment_sources (); + init_appointment_sources (); + + update_appointment_menu_items (NULL); +} + /* Function to build everything up. Entry point from asm. */ int main (int argc, char ** argv) @@ -1434,10 +1409,21 @@ main (int argc, char ** argv) /* Set up GSettings */ conf = g_settings_new(SETTINGS_INTERFACE); - /* Set up gconf for getting evolution enabled calendars */ - gconf = gconf_client_get_default(); // TODO Add a signal handler to catch gsettings changes and respond to them + /* Build our list of appointment calendar sources. + When a source changes, update our menu items. + When sources are added or removed, update our list and menu items. */ + source_registry = e_source_registry_new_sync (NULL, NULL); + g_object_connect (source_registry, + "signal::source-added", update_appointments, + "signal::source-removed", update_appointments, + "signal::source-changed", update_appointment_menu_items, + "signal::source-disabled", update_appointment_menu_items, + "signal::source-enabled", update_appointment_menu_items, + NULL); + init_appointment_sources (); + /* Building the base menu */ server = dbusmenu_server_new(MENU_OBJ); root = dbusmenu_menuitem_new(); @@ -1478,12 +1464,15 @@ main (int argc, char ** argv) mainloop = g_main_loop_new(NULL, FALSE); g_main_loop_run(mainloop); + free_appointment_sources(); + g_object_unref(G_OBJECT(conf)); g_object_unref(G_OBJECT(master)); g_object_unref(G_OBJECT(dbus)); g_object_unref(G_OBJECT(service)); g_object_unref(G_OBJECT(server)); g_object_unref(G_OBJECT(root)); + g_object_unref(G_OBJECT(source_registry)); icaltimezone_free_builtin_timezones(); |