aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/datetime-service.c178
-rw-r--r--src/indicator-datetime.c122
2 files changed, 180 insertions, 120 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;
}
diff --git a/src/indicator-datetime.c b/src/indicator-datetime.c
index e7a448e..44740a6 100644
--- a/src/indicator-datetime.c
+++ b/src/indicator-datetime.c
@@ -182,7 +182,7 @@ INDICATOR_SET_TYPE(INDICATOR_DATETIME_TYPE)
G_DEFINE_TYPE (IndicatorDatetime, indicator_datetime, INDICATOR_OBJECT_TYPE);
-static GtkSizeGroup * indicator_right_group = NULL;
+//static GtkSizeGroup * indicator_right_group = NULL;
static void
indicator_datetime_class_init (IndicatorDatetimeClass *klass)
@@ -1067,48 +1067,7 @@ generate_format_string (IndicatorDatetime * self)
/* Whenever we have a property change on a DbusmenuMenuitem
we need to be responsive to that. */
-static void
-indicator_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, gchar * value, indicator_item_t * mi_data)
-{
- if (!g_strcmp0(prop, APPOINTMENT_MENUITEM_PROP_LABEL)) {
- /* Set the main label */
- gtk_label_set_text(GTK_LABEL(mi_data->label), value);
- } else if (!g_strcmp0(prop, APPOINTMENT_MENUITEM_PROP_RIGHT)) {
- /* Set the right label */
- gtk_label_set_text(GTK_LABEL(mi_data->right), value);
- } else if (!g_strcmp0(prop, APPOINTMENT_MENUITEM_PROP_ICON)) {
- /* We don't use the value here, which is probably less efficient,
- but it's easier to use the easy function. And since th value
- is already cached, shouldn't be a big deal really. */
- GdkPixbuf * pixbuf = dbusmenu_menuitem_property_get_image(mi, APPOINTMENT_MENUITEM_PROP_ICON);
- if (pixbuf != NULL) {
- /* If we've got a pixbuf we need to make sure it's of a reasonable
- size to fit in the menu. If not, rescale it. */
- GdkPixbuf * resized_pixbuf;
- gint width, height;
- gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
- if (gdk_pixbuf_get_width(pixbuf) > width ||
- gdk_pixbuf_get_height(pixbuf) > height) {
- g_debug("Resizing icon from %dx%d to %dx%d", gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf), width, height);
- resized_pixbuf = gdk_pixbuf_scale_simple(pixbuf,
- width,
- height,
- GDK_INTERP_BILINEAR);
- } else {
- g_debug("Happy with icon sized %dx%d", gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf));
- resized_pixbuf = pixbuf;
- }
- gtk_image_set_from_pixbuf(GTK_IMAGE(mi_data->icon), resized_pixbuf);
- /* The other pixbuf should be free'd by the dbusmenu. */
- if (resized_pixbuf != pixbuf) {
- g_object_unref(resized_pixbuf);
- }
- }
- } else {
- g_warning("Indicator Item property '%s' unknown", prop);
- }
- return;
-}
+// indicator prop changed removed
/* We have a small little menuitem type that handles all
of the fun stuff for indicators. Mostly this is the
@@ -1116,76 +1075,8 @@ indicator_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, gchar * value, in
side text that'll be determined by the service.
Copied verbatim from an old revision (including comments) of indicator-messages
*/
-static gboolean
-new_appointment_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data)
-{
- g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
- g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
- /* Note: not checking parent, it's reasonable for it to be NULL */
+// new appointment item removed
- indicator_item_t * mi_data = g_new0(indicator_item_t, 1);
-
- GtkMenuItem * gmi = GTK_MENU_ITEM(gtk_menu_item_new());
-
- GtkWidget * hbox = gtk_hbox_new(FALSE, 4);
-
- /* Icon, probably someone's face or avatar on an IM */
- mi_data->icon = gtk_image_new();
- GdkPixbuf * pixbuf = dbusmenu_menuitem_property_get_image(newitem, APPOINTMENT_MENUITEM_PROP_ICON);
-
- if (pixbuf != NULL) {
- /* If we've got a pixbuf we need to make sure it's of a reasonable
- size to fit in the menu. If not, rescale it. */
- GdkPixbuf * resized_pixbuf;
- gint width, height;
- gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
- if (gdk_pixbuf_get_width(pixbuf) > width ||
- gdk_pixbuf_get_height(pixbuf) > height) {
- g_debug("Resizing icon from %dx%d to %dx%d", gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf), width, height);
- resized_pixbuf = gdk_pixbuf_scale_simple(pixbuf,
- width,
- height,
- GDK_INTERP_BILINEAR);
- } else {
- g_debug("Happy with icon sized %dx%d", gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf));
- resized_pixbuf = pixbuf;
- }
-
- gtk_image_set_from_pixbuf(GTK_IMAGE(mi_data->icon), resized_pixbuf);
-
- /* The other pixbuf should be free'd by the dbusmenu. */
- if (resized_pixbuf != pixbuf) {
- g_object_unref(resized_pixbuf);
- }
- }
- gtk_misc_set_alignment(GTK_MISC(mi_data->icon), 0.0, 0.5);
- gtk_box_pack_start(GTK_BOX(hbox), mi_data->icon, FALSE, FALSE, 0);
- gtk_widget_show(mi_data->icon);
-
- /* Label, probably a username, chat room or mailbox name */
- mi_data->label = gtk_label_new(dbusmenu_menuitem_property_get(newitem, APPOINTMENT_MENUITEM_PROP_LABEL));
- gtk_misc_set_alignment(GTK_MISC(mi_data->label), 0.0, 0.5);
- gtk_box_pack_start(GTK_BOX(hbox), mi_data->label, TRUE, TRUE, 0);
- gtk_widget_show(mi_data->label);
-
- /* Usually either the time or the count on the individual
- item. */
- mi_data->right = gtk_label_new(dbusmenu_menuitem_property_get(newitem, APPOINTMENT_MENUITEM_PROP_RIGHT));
- gtk_size_group_add_widget(indicator_right_group, mi_data->right);
- gtk_misc_set_alignment(GTK_MISC(mi_data->right), 1.0, 0.5);
- gtk_box_pack_start(GTK_BOX(hbox), mi_data->right, FALSE, FALSE, 0);
- gtk_widget_show(mi_data->right);
-
- gtk_container_add(GTK_CONTAINER(gmi), hbox);
- gtk_widget_show(hbox);
-
- dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, gmi, parent);
-
- g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(indicator_prop_change_cb), mi_data);
- g_signal_connect_swapped(G_OBJECT(newitem), "destroyed", G_CALLBACK(g_free), mi_data);
-
- return TRUE;
-}
static gboolean
new_calendar_item (DbusmenuMenuitem * newitem,
@@ -1213,7 +1104,7 @@ new_calendar_item (DbusmenuMenuitem * newitem,
return TRUE;
}
-
+/*
static gboolean
new_timezone_item(DbusmenuMenuitem * newitem,
DbusmenuMenuitem * parent,
@@ -1224,6 +1115,7 @@ new_timezone_item(DbusmenuMenuitem * newitem,
return TRUE;
}
+*/
/* Grabs the label. Creates it if it doesn't
exist already */
@@ -1264,8 +1156,8 @@ get_menu (IndicatorObject * io)
g_object_set_data (G_OBJECT (client), "indicator", io);
dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), DBUSMENU_CALENDAR_MENUITEM_TYPE, new_calendar_item);
- dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), APPOINTMENT_MENUITEM_TYPE, new_appointment_item);
- dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), TIMEZONE_MENUITEM_TYPE, new_timezone_item);
+ //dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), APPOINTMENT_MENUITEM_TYPE, new_appointment_item);
+ //dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), TIMEZONE_MENUITEM_TYPE, new_timezone_item);
return GTK_MENU(self->priv->menu);
}