aboutsummaryrefslogtreecommitdiff
path: root/src/datetime-service.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/datetime-service.c')
-rw-r--r--src/datetime-service.c178
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;
}