diff options
Diffstat (limited to 'src/datetime-service.c')
-rw-r--r-- | src/datetime-service.c | 178 |
1 files changed, 173 insertions, 5 deletions
diff --git a/src/datetime-service.c b/src/datetime-service.c index 3fe6ebb..5961df8 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -63,6 +63,9 @@ static DbusmenuMenuitem * date = NULL; static DbusmenuMenuitem * calendar = NULL; static DbusmenuMenuitem * settings = NULL; static DbusmenuMenuitem * tzchange = NULL; +static GList * appointments = NULL; +static ECal * ecal = NULL; +static const gchar * ecal_timezone = NULL; /* Geoclue trackers */ static GeoclueMasterClient * geo_master = NULL; @@ -248,15 +251,180 @@ update_timezone_menu_items(gpointer user_data) { */ static gboolean update_appointment_menu_items (gpointer user_data) { + // 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. + time_t t1, t2; + icaltimezone *tzone; + gchar *query, *is, *ie; + GList *objects = NULL, *l; + GError *gerror = NULL; DbusmenuMenuitem * item = NULL; - gint i; - for (i = 0; i < 5; i++) { + gint width, height; + g_debug("Setting up ecal."); + if (!ecal) + ecal = e_cal_new_system_calendar(); + + if (!ecal) { + g_debug("e_cal_new_system_calendar failed"); + ecal = NULL; + return FALSE; + } + g_debug("Open calendar."); + if (!e_cal_open(ecal, FALSE, &gerror) ) { + g_debug("e_cal_open: %s\n", gerror->message); + g_free(ecal); + ecal = NULL; + return FALSE; + } + g_debug("Get calendar timezone."); + if (!e_cal_get_timezone(ecal, "UTC", &tzone, &gerror)) { + g_debug("failed to get time zone\n"); + g_free(ecal); + ecal = NULL; + return FALSE; + } + + /* This timezone represents the timezone of the calendar, this might be different to the current UTC offset. + * this means we'll have some geoclue interaction going on, and possibly the user will be involved in setting + * their location manually, case in point: trains have satellite links which often geoclue to sweden, + * this shouldn't automatically set the location and mess up all the appointments for the user. + */ + ecal_timezone = icaltimezone_get_tzid(tzone); + + time(&t1); + time(&t2); + t2 += (time_t) (7 * 24 * 60 * 60); /* 7 days ahead of now */ + + is = isodate_from_time_t(t1); + ie = isodate_from_time_t(t2); + // FIXME can we put a limit on the number of results? Or if not complete, or is event/todo? + query = g_strdup_printf("(occur-in-time-range? (make-time\"%s\") (make-time\"%s\"))", is, ie); + g_debug("Getting objects with query: %s", query); + if (!e_cal_get_object_list_as_comp(ecal, query, &objects, &gerror)) { + g_debug("Failed to get objects\n"); + g_free(ecal); + ecal = NULL; + return FALSE; + } + g_debug("Number of objects returned: %d", g_list_length(objects)); + gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); + /*if (appointments != NULL) { + for (l = appointments; l; l = l->next) { + item = l->data; + // Remove all the existing menu items which are in appointments. + dbusmenu_menuitem_child_delete(root, DBUSMENU_MENUITEM(item)); + appointments = g_list_remove(appointments, item); + g_free(item); + } + appointments = NULL; + }*/ + + i = 0; + for (l = objects; l; l = l->next) { + ECalComponent *ecalcomp = l->data; + ECalComponentText valuetext; + ECalComponentDateTime datetime; + icaltimezone *appointment_zone = NULL; + icalproperty_status status; + gchar *summary, *cmd; + const gchar *uri; + struct tm tmp_tm; + + ECalComponentVType vtype = e_cal_component_get_vtype (ecalcomp); + + // See above FIXME regarding query result + // If it's not an event or todo, continue no-increment + if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) + continue; + + // See above FIXME regarding query result + // if the status is completed, continue no-increment + e_cal_component_get_status (ecalcomp, &status); + if (status == ICAL_STATUS_COMPLETED || status == ICAL_STATUS_CANCELLED) + continue; + + // INPROGRESS: Create a menu item for each of them, try to include helpful metadata e.g. colours, due time item = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (item, DBUSMENU_MENUITEM_PROP_TYPE, APPOINTMENT_MENUITEM_TYPE); - dbusmenu_menuitem_property_set (item, APPOINTMENT_MENUITEM_PROP_LABEL, "fake summary"); - dbusmenu_menuitem_property_set (item, APPOINTMENT_MENUITEM_PROP_RIGHT, "9:00pm"); + //dbusmenu_menuitem_property_set (item, "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, TRUE); + + // Label text + g_debug("Label Summary."); + e_cal_component_get_summary (ecalcomp, &valuetext); + summary = g_strdup (valuetext.value); + + dbusmenu_menuitem_property_set (item, DBUSMENU_MENUITEM_PROP_LABEL, summary); + g_free (summary); + + // Due text + if (vtype == E_CAL_COMPONENT_EVENT) + e_cal_component_get_dtstart (ecalcomp, &datetime); + else + e_cal_component_get_due (ecalcomp, &datetime); + + // FIXME need to get the timezone of the above datetime, + // and get the icaltimezone of the geoclue timezone/selected timezone (whichever is preferred) + + g_debug("Check for a datetime."); // Should always have one + if (!datetime.value) { + g_free(item); + continue; + } + + g_debug("Set appointment zone."); + if (!appointment_zone || datetime.value->is_date) { // If it's today put in the current timezone? + appointment_zone = tzone; + } + tmp_tm = icaltimetype_to_tm_with_zone (datetime.value, appointment_zone, tzone); + + g_debug("Free datetime."); + e_cal_component_free_datetime (&datetime); + + // Get today + /*g_debug("Generate strings"); + if (datetime.value->is_date) + strftime(right, sizeof(right), "%X", &tmp_tm); + else + strftime(right, sizeof(right), "%a %X", &tmp_tm);*/ + //dbusmenu_menuitem_property_set (item, APPOINTMENT_MENUITEM_PROP_RIGHT, right); + + g_debug("Set callback"); + // Now we pull out the URI for the calendar event and try to create a URI that'll work when we execute evolution + e_cal_component_get_url(ecalcomp, &uri); + cmd = g_strconcat("evolution ", uri, NULL); + g_signal_connect (G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK (activate_cb), cmd); + + // Get the colour E_CAL_COMPONENT_FIELD_COLOR + // Get the icon, either EVENT or MEMO or TODO? + /*gdouble red, blue, green; + ECalSource *source = e_cal_get_source (ecalcomp->client); + if (!ecalcomp->color && e_source_get_color (source, &source_color)) { + g_free (comp_data->color); + ecalcomp->color = g_strdup_printf ("#%06x", source_color & 0xffffff); + }*/ + + + //cairo_surface_t *cs = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); + //cairo_t *cr = cairo_create(cs); + + // TODO: Draw the correct icon for the appointment type and then tint it using mask fill. + + //GdkPixbuf * pixbuf = gdk_pixbuf_get_from_drawable(NULL, (GdkDrawable*)cs, 0,0,0,0, width, height); + + //dbusmenu_menuitem_property_set_image (item, APPOINTMENT_MENUITEM_PROP_ICON, pixbuf); + g_debug("Add to menu."); dbusmenu_menuitem_child_append (root, item); + appointments = g_list_append (appointments, item); // Keep track of the items here to make them east to remove + + if (i == 4) break; // See above FIXME regarding query result limit + i++; + } + g_debug("Free-ing ecal."); + if (ecal) { + //g_free(ecal); // Really we should do the setup somewhere where we know it'll only run once, right now, we'll do it every time and free it. } return TRUE; } |