From feb60b1977c1fe3fa45452bc40f6635f56b0e39f Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Tue, 11 Jan 2011 12:21:36 +0000 Subject: Added initial support for ecal (untested) --- src/datetime-service.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++ src/dbus-shared.h | 4 ++ src/indicator-datetime.c | 78 ++++++++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+) diff --git a/src/datetime-service.c b/src/datetime-service.c index 8a31940..1e4404d 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -33,6 +33,13 @@ with this program. If not, see . #include #include +#include +#include +#include +// Other users of ecal seem to also include these, not sure why they should be included by the above +#include +#include + #include #include "datetime-interface.h" @@ -53,6 +60,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 gchar * ecal_timezone = NULL; /* Geoclue trackers */ static GeoclueMasterClient * geo_master = NULL; @@ -225,6 +235,98 @@ check_for_calendar (gpointer user_data) return FALSE; } +/* Populate the menu with todays, next 5 appointments. We probably want to shift this off to an idle-add + */ +static gboolean +update_calendar_menu_items (gpointer user_data) { + ecal = e_cal_new_system_calendar(); + if (!ecal) { + g_debug("e_cal_new_system_calendar failed"); + ecal = NULL; + return FALSE; + } + if (!e_cal_open(ecal, FALSE, &gerror) ) { + g_debug("e_cal_open: %s\n", gerror->message); + g_free(ecal); + ecal = NULL; + return FALSE; + } + + if (!e_cal_get_timezone(ecal, "UTC", &tzone, &gerror) { + g_debug("failed to get time zone\n"); + g_free(ecal); + ecal = NULL; + return FALSE; + } + + ecal_timezone = icaltimezone_get_tzid(tzone); + + time_t t1, t2; + gchar *query, *is, *ie; + GList *objects = NULL, *l; + GError *gerror = NULL; + DbusmenuMenuitem * item = NULL; + gint i; + + // TODO: Remove all the existing menu items which are appointments. + + time(&t1); + time(&t2); + t2 += (time_t) (24 * 60 * 60); /* 1 day 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? + query = g_strdup_printf("(occur-in-time-range? (make-time\"%s\") (make-time\"%s\"))", is, ie); + + if (!e_cal_get_object_list(ecal, query, &objects, &gerror);) { + g_debug("Failed to get objects\n"); + g_free(ecal); + ecal = NULL; + return TRUE; + } + i = 0; + gint width, height; + gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); + + for (l = objects; l; l = l->next) { + icalcomponent *icalcomp = l->data; + icalproperty* p; + icalvalue *v; + gchar *name, due; + p = icalcomponent_get_first_property(icalcomp, ICAL_NAME_PROPERTY); + v = icalproperty_get_value(p); + name = icalvalue_get_string(v); + + p = icalcomponent_get_first_property(icalcomp, ICAL_DUE_PROPERTY); + v = icalproperty_get_value(p); + due = icalvalue_get_string(v); + + + // TODO: now we pull out the URI for the calendar event and try to create a URI that'll work when we execute evolution + + //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); + + // TODO: 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, "type", INDICATOR_MENUITEM_TYPE); + dbusmenu_menuitem_property_set (item, APPOINTMENT_MENUITEM_PROP_LABEL, name); + //dbusmenu_menuitem_property_set_image (item, APPOINTMENT_MENUITEM_PROP_ICON, pixbuf); + dbusmenu_menuitem_property_set (item, APPOINTMENT_MENUITEM_PROP_RIGHT, due); + dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); + dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); + dbusmenu_menuitem_child_append (root, item); + + if (i == 4) break; // See above FIXME regarding query result limit + i++; + } +} + /* Looks for the time and date admin application and enables the item we have one */ static gboolean diff --git a/src/dbus-shared.h b/src/dbus-shared.h index 357beb5..4ecd64b 100644 --- a/src/dbus-shared.h +++ b/src/dbus-shared.h @@ -29,3 +29,7 @@ with this program. If not, see . #define DBUSMENU_CALENDAR_MENUITEM_TYPE "x-canonical-calendar-item" +#define APPOINTMENT_MENUITEM_TYPE "indicator-item" +#define APPOINTMENT_MENUITEM_PROP_LABEL "indicator-label" +#define APPOINTMENT_MENUITEM_PROP_ICON "indicator-icon" +#define APPOINTMENT_MENUITEM_PROP_RIGHT "right-side-text" diff --git a/src/indicator-datetime.c b/src/indicator-datetime.c index acdc340..4c3b315 100644 --- a/src/indicator-datetime.c +++ b/src/indicator-datetime.c @@ -923,6 +923,83 @@ generate_format_string (IndicatorDatetime * self) return g_strdup_printf(_("%s, %s"), date_string, time_string); } +/* We have a small little menuitem type that handles all + of the fun stuff for indicators. Mostly this is the + shifting over and putting the icon in with some right + 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) +{ + 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 */ + + 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, INDICATOR_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, INDICATOR_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, INDICATOR_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(G_OBJECT(newitem), "destroyed", G_CALLBACK(g_free), mi_data); + + return TRUE; +} + static gboolean new_calendar_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, @@ -986,6 +1063,7 @@ 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_indicator_item); return GTK_MENU(self->priv->menu); } -- cgit v1.2.3 From ed67c38fc82ed34fc7fe7afeb94a5af56f963c52 Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Tue, 11 Jan 2011 15:48:58 +0000 Subject: Updated some minor things, the last commit wasn't exactly great, still untested, looking for a way to pull the evolution URI out of the events. --- src/datetime-service.c | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/src/datetime-service.c b/src/datetime-service.c index 1e4404d..cd8ca92 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -236,9 +236,19 @@ check_for_calendar (gpointer user_data) } /* Populate the menu with todays, next 5 appointments. We probably want to shift this off to an idle-add + * the problem is the inserting order of items and updating them might be difficult. + * we should hook into the ABOUT TO SHOW signal and use that to update the appointments. */ static gboolean -update_calendar_menu_items (gpointer user_data) { +update_appointment_menu_items (gpointer user_data) { + + time_t t1, t2; + gchar *query, *is, *ie; + GList *objects = NULL, *l; + GError *gerror = NULL; + DbusmenuMenuitem * item = NULL; + gint i; + ecal = e_cal_new_system_calendar(); if (!ecal) { g_debug("e_cal_new_system_calendar failed"); @@ -261,13 +271,6 @@ update_calendar_menu_items (gpointer user_data) { ecal_timezone = icaltimezone_get_tzid(tzone); - time_t t1, t2; - gchar *query, *is, *ie; - GList *objects = NULL, *l; - GError *gerror = NULL; - DbusmenuMenuitem * item = NULL; - gint i; - // TODO: Remove all the existing menu items which are appointments. time(&t1); @@ -283,7 +286,7 @@ update_calendar_menu_items (gpointer user_data) { g_debug("Failed to get objects\n"); g_free(ecal); ecal = NULL; - return TRUE; + return FALSE; } i = 0; gint width, height; @@ -293,7 +296,7 @@ update_calendar_menu_items (gpointer user_data) { icalcomponent *icalcomp = l->data; icalproperty* p; icalvalue *v; - gchar *name, due; + gchar *name, *due, *uri; p = icalcomponent_get_first_property(icalcomp, ICAL_NAME_PROPERTY); v = icalproperty_get_value(p); name = icalvalue_get_string(v); @@ -302,7 +305,6 @@ update_calendar_menu_items (gpointer user_data) { v = icalproperty_get_value(p); due = icalvalue_get_string(v); - // TODO: now we pull out the URI for the calendar event and try to create a URI that'll work when we execute evolution //cairo_surface_t *cs = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); @@ -321,10 +323,14 @@ update_calendar_menu_items (gpointer user_data) { dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); dbusmenu_menuitem_child_append (root, item); + //g_signal_connect (G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + // G_CALLBACK (activate_cb), "evolution %s", uri); if (i == 4) break; // See above FIXME regarding query result limit i++; } + 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; } /* Looks for the time and date admin application and enables the @@ -374,8 +380,17 @@ build_menus (DbusmenuMenuitem * root) g_idle_add(check_for_calendar, NULL); } + DbusmenuMenuitem * separator; + + separator = dbusmenu_menuitem_new(); + dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); + dbusmenu_menuitem_child_append(root, separator); + + // This just populates the items on startup later we want to be able to update the appointments before + // presenting the menu. + update_appointment_menu_items(NULL); - DbusmenuMenuitem * separator = dbusmenu_menuitem_new(); + separator = dbusmenu_menuitem_new(); dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); dbusmenu_menuitem_child_append(root, separator); -- cgit v1.2.3 From 038f58b53b51ee65cd170809b96fccd55766f531 Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Wed, 12 Jan 2011 09:36:05 +0000 Subject: Updated configure with ecal/ical --- configure.ac | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index dc0448c..c248853 100644 --- a/configure.ac +++ b/configure.ac @@ -59,18 +59,24 @@ GIO_REQUIRED_VERSION=2.25.11 INDICATOR_DISPLAY_OBJECTS=0.1.10 GEOCLUE_REQUIRED_VERSION=0.12.0 OOBS_REQUIRED_VERSION=2.31.0 +ECAL_REQUIRED_VERSION=2.30 +ICAL_REQUIRED_VERSION=0.44 AS_IF([test "x$with_gtk" = x3], [PKG_CHECK_MODULES(INDICATOR, indicator3 >= $INDICATOR_REQUIRED_VERSION dbusmenu-glib >= $DBUSMENUGLIB_REQUIRED_VERSION dbusmenu-gtk3 >= $DBUSMENUGTK_REQUIRED_VERSION - libido3-0.1 >= $INDICATOR_DISPLAY_OBJECTS) + libido3-0.1 >= $INDICATOR_DISPLAY_OBJECTS, + libecal >= $ECAL_REQUIRED_VERSION, + libical >= $ICAL_REQUIRED_VERSION) ], [test "x$with_gtk" = x2], [PKG_CHECK_MODULES(INDICATOR, indicator >= $INDICATOR_REQUIRED_VERSION dbusmenu-glib >= $DBUSMENUGLIB_REQUIRED_VERSION dbusmenu-gtk >= $DBUSMENUGTK_REQUIRED_VERSION - libido-0.1 >= $INDICATOR_DISPLAY_OBJECTS) + libido-0.1 >= $INDICATOR_DISPLAY_OBJECTS, + libecal >= $ECAL_REQUIRED_VERSION, + libical >= $ICAL_REQUIRED_VERSION) ], [AC_MSG_FAILURE([Value for --with-gtk was neither 2 nor 3])] ) -- cgit v1.2.3 From afdb696699f886959a92476cf76f30718f097838 Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Wed, 12 Jan 2011 09:49:16 +0000 Subject: Added most likely broken URI callback, but at least our debugging messages will show us something :) --- src/datetime-service.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/datetime-service.c b/src/datetime-service.c index cd8ca92..814c9c6 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -296,7 +296,7 @@ update_appointment_menu_items (gpointer user_data) { icalcomponent *icalcomp = l->data; icalproperty* p; icalvalue *v; - gchar *name, *due, *uri; + gchar *name, *due, *uri, *cmd; p = icalcomponent_get_first_property(icalcomp, ICAL_NAME_PROPERTY); v = icalproperty_get_value(p); name = icalvalue_get_string(v); @@ -306,6 +306,11 @@ update_appointment_menu_items (gpointer user_data) { due = icalvalue_get_string(v); // TODO: now we pull out the URI for the calendar event and try to create a URI that'll work when we execute evolution + // not sure if the ical URL property is actually an evolution compatible URI and no real way to tell other than testing + p = icalcomponent_get_first_property(icalcomp, ICAL_URL_PROPERTY); + v = icalproperty_get_value(p); + uri = icalvalue_get_string(v); + cmd = g_strconcat("evolution ", uri, NULL); //cairo_surface_t *cs = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); //cairo_t *cr = cairo_create(cs); @@ -323,8 +328,8 @@ update_appointment_menu_items (gpointer user_data) { dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); dbusmenu_menuitem_child_append (root, item); - //g_signal_connect (G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - // G_CALLBACK (activate_cb), "evolution %s", uri); + g_signal_connect (G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK (activate_cb), cmd); if (i == 4) break; // See above FIXME regarding query result limit i++; -- cgit v1.2.3 From b54626d404eccdc07b2bac09301d5e28dcc838f2 Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Wed, 12 Jan 2011 11:25:04 +0000 Subject: Added missing stuff, getting it ready to be buildable --- configure.ac | 8 +++--- src/datetime-service.c | 1 + src/indicator-datetime.c | 63 +++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 64 insertions(+), 8 deletions(-) diff --git a/configure.ac b/configure.ac index c248853..10ea46b 100644 --- a/configure.ac +++ b/configure.ac @@ -66,16 +66,16 @@ AS_IF([test "x$with_gtk" = x3], [PKG_CHECK_MODULES(INDICATOR, indicator3 >= $INDICATOR_REQUIRED_VERSION dbusmenu-glib >= $DBUSMENUGLIB_REQUIRED_VERSION dbusmenu-gtk3 >= $DBUSMENUGTK_REQUIRED_VERSION - libido3-0.1 >= $INDICATOR_DISPLAY_OBJECTS, - libecal >= $ECAL_REQUIRED_VERSION, + libido3-0.1 >= $INDICATOR_DISPLAY_OBJECTS + libecal >= $ECAL_REQUIRED_VERSION libical >= $ICAL_REQUIRED_VERSION) ], [test "x$with_gtk" = x2], [PKG_CHECK_MODULES(INDICATOR, indicator >= $INDICATOR_REQUIRED_VERSION dbusmenu-glib >= $DBUSMENUGLIB_REQUIRED_VERSION dbusmenu-gtk >= $DBUSMENUGTK_REQUIRED_VERSION - libido-0.1 >= $INDICATOR_DISPLAY_OBJECTS, - libecal >= $ECAL_REQUIRED_VERSION, + libido-0.1 >= $INDICATOR_DISPLAY_OBJECTS + libecal >= $ECAL_REQUIRED_VERSION libical >= $ICAL_REQUIRED_VERSION) ], [AC_MSG_FAILURE([Value for --with-gtk was neither 2 nor 3])] diff --git a/src/datetime-service.c b/src/datetime-service.c index 814c9c6..33c8f30 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -307,6 +307,7 @@ update_appointment_menu_items (gpointer user_data) { // TODO: now we pull out the URI for the calendar event and try to create a URI that'll work when we execute evolution // not sure if the ical URL property is actually an evolution compatible URI and no real way to tell other than testing + // We may need to change this to ecalcomponenets to get something closer to the evolution URI p = icalcomponent_get_first_property(icalcomp, ICAL_URL_PROPERTY); v = icalproperty_get_value(p); uri = icalvalue_get_string(v); diff --git a/src/indicator-datetime.c b/src/indicator-datetime.c index 4c3b315..364c7b4 100644 --- a/src/indicator-datetime.c +++ b/src/indicator-datetime.c @@ -40,6 +40,7 @@ with this program. If not, see . /* DBusMenu */ #include #include +#include #include "dbus-shared.h" @@ -99,6 +100,13 @@ enum { PROP_CUSTOM_TIME_FORMAT }; +typedef struct _indicator_item_t indicator_item_t; +struct _indicator_item_t { + GtkWidget * icon; + GtkWidget * label; + GtkWidget * right; +}; + #define PROP_TIME_FORMAT_S "time-format" #define PROP_SHOW_SECONDS_S "show-seconds" #define PROP_SHOW_DAY_S "show-day" @@ -150,6 +158,8 @@ INDICATOR_SET_TYPE(INDICATOR_DATETIME_TYPE) G_DEFINE_TYPE (IndicatorDatetime, indicator_datetime, INDICATOR_OBJECT_TYPE); +static GtkSizeGroup * indicator_right_group = NULL; + static void indicator_datetime_class_init (IndicatorDatetimeClass *klass) { @@ -923,6 +933,51 @@ generate_format_string (IndicatorDatetime * self) return g_strdup_printf(_("%s, %s"), date_string, time_string); } +/* 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; +} + /* We have a small little menuitem type that handles all of the fun stuff for indicators. Mostly this is the shifting over and putting the icon in with some right @@ -944,7 +999,7 @@ new_appointment_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbu /* Icon, probably someone's face or avatar on an IM */ mi_data->icon = gtk_image_new(); - GdkPixbuf * pixbuf = dbusmenu_menuitem_property_get_image(newitem, INDICATOR_MENUITEM_PROP_ICON); + 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 @@ -976,14 +1031,14 @@ new_appointment_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbu 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, INDICATOR_MENUITEM_PROP_LABEL)); + 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, INDICATOR_MENUITEM_PROP_RIGHT)); + 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); @@ -1063,7 +1118,7 @@ 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_indicator_item); + dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), APPOINTMENT_MENUITEM_TYPE, new_appointment_item); return GTK_MENU(self->priv->menu); } -- cgit v1.2.3 From add30ba3ce73f5b10f592cc1cd23132a9c04d980 Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Wed, 19 Jan 2011 15:21:14 +0000 Subject: Updated the eds code to use ecalcomponents rather than ical so we get colours etc... --- src/datetime-service.c | 168 ++++++++++++++++++++++++++++++++++++----------- src/indicator-datetime.c | 10 +++ 2 files changed, 141 insertions(+), 37 deletions(-) diff --git a/src/datetime-service.c b/src/datetime-service.c index 33c8f30..e06b76d 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -36,10 +36,14 @@ with this program. If not, see . #include #include #include +#include +#include +#include // Other users of ecal seem to also include these, not sure why they should be included by the above #include #include + #include #include "datetime-interface.h" @@ -235,21 +239,37 @@ check_for_calendar (gpointer user_data) return FALSE; } -/* Populate the menu with todays, next 5 appointments. We probably want to shift this off to an idle-add - * the problem is the inserting order of items and updating them might be difficult. - * we should hook into the ABOUT TO SHOW signal and use that to update the appointments. +static gboolean +timezone_clicked_cb() { + + return FALSE; +} + +static gboolean +update_timezone_menu_items(gpointer user_data) { + + return FALSE; +} + +/* Populate the menu with todays, next 5 appointments. + * we should hook into the ABOUT TO SHOW signal and use that to update the appointments. + * Experience has shown that caldav's and webcals can be slow to load from eds + * this is a problem mainly on the EDS side of things, not ours. */ 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; gchar *query, *is, *ie; GList *objects = NULL, *l; GError *gerror = NULL; DbusmenuMenuitem * item = NULL; gint i; + gint width, height; ecal = e_cal_new_system_calendar(); + if (!ecal) { g_debug("e_cal_new_system_calendar failed"); ecal = NULL; @@ -269,50 +289,119 @@ update_appointment_menu_items (gpointer user_data) { 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); - // TODO: Remove all the existing menu items which are appointments. - time(&t1); time(&t2); - t2 += (time_t) (24 * 60 * 60); /* 1 day ahead of now */ + 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? + // 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); - if (!e_cal_get_object_list(ecal, query, &objects, &gerror);) { + 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; } - i = 0; - gint width, height; gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); + if (appointments != NULL) { + for (l = appointments; l; l = l->next) { + item = l->data; + // TODO: Remove all the existing menu items which are in appointments. + + // pop it out of the dbus menu + // remove it from the appointments glist + // free it + } + appointments = NULL; + } + + i = 0; for (l = objects; l; l = l->next) { - icalcomponent *icalcomp = l->data; - icalproperty* p; - icalvalue *v; - gchar *name, *due, *uri, *cmd; - p = icalcomponent_get_first_property(icalcomp, ICAL_NAME_PROPERTY); - v = icalproperty_get_value(p); - name = icalvalue_get_string(v); + ECalComponent *ecalcomp = l->data; + ECalComponentText valuetext; + ECalComponentDateTime datetime; + icaltimezone *appointment_zone; + time_t appointment_time, ti; + icalproperty_status status; + gchar *summary, right[20], *cmd; + const gchar *uri; + struct tm *tmp_tm, *tm_today; + + vtype = e_cal_component_get_vtype (comp); + + // 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, "type", INDICATOR_MENUITEM_TYPE); + dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); + dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); - p = icalcomponent_get_first_property(icalcomp, ICAL_DUE_PROPERTY); - v = icalproperty_get_value(p); - due = icalvalue_get_string(v); + // Label text + e_cal_component_get_summary (ecalcomp, &valuetext); + summary = g_strdup (valuetext.value); + e_cal_component_free_text (&valuetext); + dbusmenu_menuitem_property_set (item, APPOINTMENT_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); + + if (datetime.value) { + appointment_zone = get_zone_from_tzid (client, datetime.tzid); + if (!appointment_zone || datetime.value->is_date) + appointment_zone = ecal_timezone; + appointment_time = icaltime_as_timet_with_zone (*datetime.value, appointment_zone); + } + e_cal_component_free_datetime (&datetime); + tmp_tm = convert_timet_to_struct_tm (appointment_time, appointment_zone); - // TODO: now we pull out the URI for the calendar event and try to create a URI that'll work when we execute evolution - // not sure if the ical URL property is actually an evolution compatible URI and no real way to tell other than testing - // We may need to change this to ecalcomponenets to get something closer to the evolution URI - p = icalcomponent_get_first_property(icalcomp, ICAL_URL_PROPERTY); - v = icalproperty_get_value(p); - uri = icalvalue_get_string(v); + // Get today + time(&ti); + tm_today = convert_timet_to_struct_tm (ti, appointment_zone); + if (tm_today->mday == tmp_tm->mday && tm_today->mon == tmp_tm->mon && tm_today->year == tmp_tm->year) + 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); + + // 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); @@ -320,17 +409,10 @@ update_appointment_menu_items (gpointer user_data) { //GdkPixbuf * pixbuf = gdk_pixbuf_get_from_drawable(NULL, (GdkDrawable*)cs, 0,0,0,0, width, height); - // TODO: 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, "type", INDICATOR_MENUITEM_TYPE); - dbusmenu_menuitem_property_set (item, APPOINTMENT_MENUITEM_PROP_LABEL, name); //dbusmenu_menuitem_property_set_image (item, APPOINTMENT_MENUITEM_PROP_ICON, pixbuf); - dbusmenu_menuitem_property_set (item, APPOINTMENT_MENUITEM_PROP_RIGHT, due); - dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); - dbusmenu_menuitem_property_set_bool (item, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); + dbusmenu_menuitem_child_append (root, item); - g_signal_connect (G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK (activate_cb), cmd); + 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++; @@ -395,7 +477,19 @@ build_menus (DbusmenuMenuitem * root) // This just populates the items on startup later we want to be able to update the appointments before // presenting the menu. update_appointment_menu_items(NULL); - + if (calendar != NULL) { + // TODO Create "Add appointment" menu item + } + // TODO Create FFR? "Add timer" menu item + + separator = dbusmenu_menuitem_new(); + dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); + dbusmenu_menuitem_child_append(root, separator); + + update_timezone_menu_items(NULL); + // TODO Create "detected location" menu item? (defaults to the geoclue location) + // TODO Create "Add location" menu item + separator = dbusmenu_menuitem_new(); dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); dbusmenu_menuitem_child_append(root, separator); diff --git a/src/indicator-datetime.c b/src/indicator-datetime.c index 364c7b4..c6dc2c1 100644 --- a/src/indicator-datetime.c +++ b/src/indicator-datetime.c @@ -1081,6 +1081,16 @@ new_calendar_item (DbusmenuMenuitem * newitem, return TRUE; } +static gboolean +new_timezone_item(DbusmenuMenuitem * newitem, + DbusmenuMenuitem * parent, + DbusmenuClient * client) +{ + // Menu item with a radio button and a right aligned time + + return TRUE; +} + /* Grabs the label. Creates it if it doesn't exist already */ static GtkLabel * -- cgit v1.2.3 From d747c851dcf9a7bb034551fcc30ff062d479023c Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Thu, 20 Jan 2011 09:36:56 +0000 Subject: Minor fix from blotted out version numbers --- configure.ac | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index bcfd968..2feb744 100644 --- a/configure.ac +++ b/configure.ac @@ -64,16 +64,16 @@ ICAL_REQUIRED_VERSION=0.44 AS_IF([test "x$with_gtk" = x3], [PKG_CHECK_MODULES(INDICATOR, indicator3 >= $INDICATOR_REQUIRED_VERSION - dbusmenu-glib >= $DBUSMENUGLIB_REQUIRED_VERSION - dbusmenu-gtk3 >= $DBUSMENUGTK_REQUIRED_VERSION + dbusmenu-glib-0.4 >= $DBUSMENUGLIB_REQUIRED_VERSION + dbusmenu-gtk3-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION libido3-0.1 >= $INDICATOR_DISPLAY_OBJECTS libecal >= $ECAL_REQUIRED_VERSION libical >= $ICAL_REQUIRED_VERSION) ], [test "x$with_gtk" = x2], [PKG_CHECK_MODULES(INDICATOR, indicator >= $INDICATOR_REQUIRED_VERSION - dbusmenu-glib >= $DBUSMENUGLIB_REQUIRED_VERSION - dbusmenu-gtk >= $DBUSMENUGTK_REQUIRED_VERSION + dbusmenu-glib-0.4 >= $DBUSMENUGLIB_REQUIRED_VERSION + dbusmenu-gtk-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION libido-0.1 >= $INDICATOR_DISPLAY_OBJECTS libecal >= $ECAL_REQUIRED_VERSION libical >= $ICAL_REQUIRED_VERSION) -- cgit v1.2.3 From 665f9ece45a30a255c85aab6b9a855dda8a56b1d Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Mon, 24 Jan 2011 17:22:35 +0000 Subject: Final few fixes making it buildable --- configure.ac | 12 +++----- src/datetime-service.c | 80 +++++++++++++++++++++++------------------------- src/dbus-shared.h | 13 +++++--- src/indicator-datetime.c | 1 + 4 files changed, 53 insertions(+), 53 deletions(-) diff --git a/configure.ac b/configure.ac index 2feb744..09ea542 100644 --- a/configure.ac +++ b/configure.ac @@ -66,17 +66,13 @@ AS_IF([test "x$with_gtk" = x3], [PKG_CHECK_MODULES(INDICATOR, indicator3 >= $INDICATOR_REQUIRED_VERSION dbusmenu-glib-0.4 >= $DBUSMENUGLIB_REQUIRED_VERSION dbusmenu-gtk3-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION - libido3-0.1 >= $INDICATOR_DISPLAY_OBJECTS - libecal >= $ECAL_REQUIRED_VERSION - libical >= $ICAL_REQUIRED_VERSION) + libido3-0.1 >= $INDICATOR_DISPLAY_OBJECTS) ], [test "x$with_gtk" = x2], [PKG_CHECK_MODULES(INDICATOR, indicator >= $INDICATOR_REQUIRED_VERSION dbusmenu-glib-0.4 >= $DBUSMENUGLIB_REQUIRED_VERSION dbusmenu-gtk-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION - libido-0.1 >= $INDICATOR_DISPLAY_OBJECTS - libecal >= $ECAL_REQUIRED_VERSION - libical >= $ICAL_REQUIRED_VERSION) + libido-0.1 >= $INDICATOR_DISPLAY_OBJECTS) ], [AC_MSG_FAILURE([Value for --with-gtk was neither 2 nor 3])] ) @@ -86,7 +82,9 @@ PKG_CHECK_MODULES(SERVICE, indicator >= $INDICATOR_REQUIRED_VERSION libido-0.1 >= $INDICATOR_DISPLAY_OBJECTS gio-2.0 >= $GIO_REQUIRED_VERSION geoclue >= $GEOCLUE_REQUIRED_VERSION - liboobs-1 >= $OOBS_REQUIRED_VERSION) + liboobs-1 >= $OOBS_REQUIRED_VERSION + libecal-1.2 >= $ECAL_REQUIRED_VERSION + libical >= $ICAL_REQUIRED_VERSION) AC_SUBST(INDICATOR_CFLAGS) AC_SUBST(INDICATOR_LIBS) diff --git a/src/datetime-service.c b/src/datetime-service.c index e06b76d..020371f 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -23,6 +23,7 @@ with this program. If not, see . #include #include +#include #include #include @@ -36,11 +37,9 @@ with this program. If not, see . #include #include #include -#include #include #include // Other users of ecal seem to also include these, not sure why they should be included by the above -#include #include @@ -66,7 +65,7 @@ static DbusmenuMenuitem * settings = NULL; static DbusmenuMenuitem * tzchange = NULL; static GList * appointments = NULL; static ECal * ecal = NULL; -static gchar * ecal_timezone = NULL; +static const gchar * ecal_timezone = NULL; /* Geoclue trackers */ static GeoclueMasterClient * geo_master = NULL; @@ -239,15 +238,9 @@ check_for_calendar (gpointer user_data) return FALSE; } -static gboolean -timezone_clicked_cb() { - - return FALSE; -} - static gboolean update_timezone_menu_items(gpointer user_data) { - + // Get the location preferences and the current location, highlight the current location somehow return FALSE; } @@ -261,6 +254,7 @@ 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; @@ -268,7 +262,8 @@ update_appointment_menu_items (gpointer user_data) { gint i; gint width, height; - ecal = e_cal_new_system_calendar(); + if (!ecal) + ecal = e_cal_new_system_calendar(); if (!ecal) { g_debug("e_cal_new_system_calendar failed"); @@ -282,7 +277,7 @@ update_appointment_menu_items (gpointer user_data) { return FALSE; } - if (!e_cal_get_timezone(ecal, "UTC", &tzone, &gerror) { + if (!e_cal_get_timezone(ecal, "UTC", &tzone, &gerror)) { g_debug("failed to get time zone\n"); g_free(ecal); ecal = NULL; @@ -305,22 +300,20 @@ update_appointment_menu_items (gpointer user_data) { // 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); - if (!e_cal_get_object_list_as_comp(ecal, query, &objects, &gerror);) { + 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; } gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); - if (appointments != NULL) { for (l = appointments; l; l = l->next) { item = l->data; - // TODO: Remove all the existing menu items which are in appointments. - - // pop it out of the dbus menu - // remove it from the appointments glist - // free it + // 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; } @@ -330,14 +323,13 @@ update_appointment_menu_items (gpointer user_data) { ECalComponent *ecalcomp = l->data; ECalComponentText valuetext; ECalComponentDateTime datetime; - icaltimezone *appointment_zone; - time_t appointment_time, ti; + icaltimezone *appointment_zone = NULL; icalproperty_status status; gchar *summary, right[20], *cmd; const gchar *uri; - struct tm *tmp_tm, *tm_today; - - vtype = e_cal_component_get_vtype (comp); + 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 @@ -352,15 +344,16 @@ update_appointment_menu_items (gpointer user_data) { // 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, "type", INDICATOR_MENUITEM_TYPE); + 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 e_cal_component_get_summary (ecalcomp, &valuetext); summary = g_strdup (valuetext.value); - e_cal_component_free_text (&valuetext); + dbusmenu_menuitem_property_set (item, APPOINTMENT_MENUITEM_PROP_LABEL, summary); + g_free (summary); // Due text @@ -369,23 +362,26 @@ update_appointment_menu_items (gpointer user_data) { else e_cal_component_get_due (ecalcomp, &datetime); - if (datetime.value) { - appointment_zone = get_zone_from_tzid (client, datetime.tzid); - if (!appointment_zone || datetime.value->is_date) - appointment_zone = ecal_timezone; - appointment_time = icaltime_as_timet_with_zone (*datetime.value, appointment_zone); + // FIXME need to get the timezone of the above datetime, + // and get the icaltimezone of the geoclue timezone/selected timezone (whichever is preferred) + if (!datetime.value) { + g_free(item); + continue; } + + 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); + e_cal_component_free_datetime (&datetime); - tmp_tm = convert_timet_to_struct_tm (appointment_time, appointment_zone); // Get today - time(&ti); - tm_today = convert_timet_to_struct_tm (ti, appointment_zone); - if (tm_today->mday == tmp_tm->mday && tm_today->mon == tmp_tm->mon && tm_today->year == tmp_tm->year) - strftime(&right, sizeof(right), "%X", tmp_tm); + 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); + strftime(right, sizeof(right), "%a %X", &tmp_tm); + dbusmenu_menuitem_property_set (item, APPOINTMENT_MENUITEM_PROP_RIGHT, right); // 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); @@ -395,12 +391,13 @@ update_appointment_menu_items (gpointer user_data) { // Get the colour E_CAL_COMPONENT_FIELD_COLOR // Get the icon, either EVENT or MEMO or TODO? - gdouble red, blue, green; + /*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); @@ -412,7 +409,7 @@ update_appointment_menu_items (gpointer user_data) { //dbusmenu_menuitem_property_set_image (item, APPOINTMENT_MENUITEM_PROP_ICON, pixbuf); dbusmenu_menuitem_child_append (root, item); - appointments = g_list_append(appointments, item); // Keep track of the items here to make them east to remove + 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++; @@ -487,7 +484,6 @@ build_menus (DbusmenuMenuitem * root) dbusmenu_menuitem_child_append(root, separator); update_timezone_menu_items(NULL); - // TODO Create "detected location" menu item? (defaults to the geoclue location) // TODO Create "Add location" menu item separator = dbusmenu_menuitem_new(); diff --git a/src/dbus-shared.h b/src/dbus-shared.h index 4ecd64b..1f90ca7 100644 --- a/src/dbus-shared.h +++ b/src/dbus-shared.h @@ -29,7 +29,12 @@ with this program. If not, see . #define DBUSMENU_CALENDAR_MENUITEM_TYPE "x-canonical-calendar-item" -#define APPOINTMENT_MENUITEM_TYPE "indicator-item" -#define APPOINTMENT_MENUITEM_PROP_LABEL "indicator-label" -#define APPOINTMENT_MENUITEM_PROP_ICON "indicator-icon" -#define APPOINTMENT_MENUITEM_PROP_RIGHT "right-side-text" +#define APPOINTMENT_MENUITEM_TYPE "appointment-item" +#define APPOINTMENT_MENUITEM_PROP_LABEL "appointment-label" +#define APPOINTMENT_MENUITEM_PROP_ICON "appointment-icon" +#define APPOINTMENT_MENUITEM_PROP_RIGHT "appointment-time" + +#define TIMEZONE_MENUITEM_TYPE "timezone-item" +#define TIMEZONE_MENUITEM_PROP_LABEL "timezone-label" +#define TIMEZONE_MENUITEM_PROP_RADIO "timezone-radio" +#define TIMEZONE_MENUITEM_PROP_RIGHT "timezone-time" diff --git a/src/indicator-datetime.c b/src/indicator-datetime.c index 5d92296..a07e667 100644 --- a/src/indicator-datetime.c +++ b/src/indicator-datetime.c @@ -1263,6 +1263,7 @@ get_menu (IndicatorObject * 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); return GTK_MENU(self->priv->menu); } -- cgit v1.2.3 From c023a16ebdef8c0bdbd10cdfe9cf753afad1191b Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Wed, 26 Jan 2011 11:12:48 -0500 Subject: fix some crashes --- src/datetime-service.c | 1 + src/indicator-datetime.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/datetime-service.c b/src/datetime-service.c index 020371f..d80fc18 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -415,6 +415,7 @@ update_appointment_menu_items (gpointer user_data) { i++; } 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. + ecal = NULL; return TRUE; } diff --git a/src/indicator-datetime.c b/src/indicator-datetime.c index a07e667..288ab26 100644 --- a/src/indicator-datetime.c +++ b/src/indicator-datetime.c @@ -340,7 +340,7 @@ service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data) } if (error != NULL) { - g_error("Could not grab DBus proxy for %s: %s", SERVICE_NAME, error->message); + g_warning("Could not grab DBus proxy for %s: %s", SERVICE_NAME, error->message); g_error_free(error); return; } @@ -1182,7 +1182,7 @@ new_appointment_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbu 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(G_OBJECT(newitem), "destroyed", G_CALLBACK(g_free), mi_data); + g_signal_connect_swapped(G_OBJECT(newitem), "destroyed", G_CALLBACK(g_free), mi_data); return TRUE; } -- cgit v1.2.3 From e0718f3613ae3a39a58e87cf1f4b2c4c00b76117 Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Mon, 31 Jan 2011 17:30:19 +0000 Subject: Removed all buggy code from the datetime-service to push for A2 --- src/datetime-service.c | 178 +++++++++++++++++++++++++++++++++++++++++++++-- src/indicator-datetime.c | 122 ++------------------------------ 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); } -- cgit v1.2.3 From 5734c96d1e10bbc78532b07cb3fe127c609a7e16 Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Wed, 2 Feb 2011 11:14:26 +0000 Subject: Getting the menu working almost correctly --- src/datetime-service.c | 50 +++++++++++-------- src/indicator-datetime.c | 123 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 145 insertions(+), 28 deletions(-) diff --git a/src/datetime-service.c b/src/datetime-service.c index 5961df8..85fcc2d 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -261,6 +261,7 @@ update_appointment_menu_items (gpointer user_data) { DbusmenuMenuitem * item = NULL; gint i; gint width, height; + g_debug("Setting up ecal."); if (!ecal) ecal = e_cal_new_system_calendar(); @@ -309,7 +310,7 @@ update_appointment_menu_items (gpointer user_data) { } g_debug("Number of objects returned: %d", g_list_length(objects)); gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); - /*if (appointments != NULL) { + if (appointments != NULL) { for (l = appointments; l; l = l->next) { item = l->data; // Remove all the existing menu items which are in appointments. @@ -318,8 +319,8 @@ update_appointment_menu_items (gpointer user_data) { g_free(item); } appointments = NULL; - }*/ - + } + i = 0; for (l = objects; l; l = l->next) { ECalComponent *ecalcomp = l->data; @@ -328,6 +329,7 @@ update_appointment_menu_items (gpointer user_data) { icaltimezone *appointment_zone = NULL; icalproperty_status status; gchar *summary, *cmd; + char right[20]; const gchar *uri; struct tm tmp_tm; @@ -345,17 +347,19 @@ update_appointment_menu_items (gpointer user_data) { 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, "type", APPOINTMENT_MENUITEM_TYPE); + 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, TRUE); - + + g_debug("Start Object"); // 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); + dbusmenu_menuitem_property_set (item, APPOINTMENT_MENUITEM_PROP_LABEL, summary); + g_debug("Summary: %s", summary); g_free (summary); // Due text @@ -367,36 +371,40 @@ update_appointment_menu_items (gpointer user_data) { // 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 + //g_debug("Check for a datetime."); // Should always have one if (!datetime.value) { g_free(item); continue; } - g_debug("Set appointment zone."); + //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); + g_debug("Generate strings"); + if (datetime.value->is_date) // Is today - not working :/ + strftime(right, 20, "%l:%M %P", &tmp_tm); else - strftime(right, sizeof(right), "%a %X", &tmp_tm);*/ - //dbusmenu_menuitem_property_set (item, APPOINTMENT_MENUITEM_PROP_RIGHT, right); + strftime(right, 20, "%a %l:%M %P", &tmp_tm); + + g_debug("Appointment time: %s", right); + dbusmenu_menuitem_property_set (item, APPOINTMENT_MENUITEM_PROP_RIGHT, right); + + //g_debug("Free datetime."); + e_cal_component_free_datetime (&datetime); - 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); + e_cal_component_get_uid(ecalcomp, &uri); + cmd = g_strconcat("evolution calendar://", uri, NULL); g_signal_connect (G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (activate_cb), cmd); + g_debug("Command to Execute: %s", cmd); + // Get the colour E_CAL_COMPONENT_FIELD_COLOR // Get the icon, either EVENT or MEMO or TODO? /*gdouble red, blue, green; @@ -415,14 +423,14 @@ update_appointment_menu_items (gpointer user_data) { //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."); + g_debug("End of objects"); 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. } diff --git a/src/indicator-datetime.c b/src/indicator-datetime.c index 44740a6..7748a8c 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,7 +1067,48 @@ generate_format_string (IndicatorDatetime * self) /* Whenever we have a property change on a DbusmenuMenuitem we need to be responsive to that. */ -// indicator prop changed removed +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; +} /* We have a small little menuitem type that handles all of the fun stuff for indicators. Mostly this is the @@ -1075,7 +1116,76 @@ generate_format_string (IndicatorDatetime * self) side text that'll be determined by the service. Copied verbatim from an old revision (including comments) of indicator-messages */ -// new appointment item removed +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 */ + + 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 @@ -1104,7 +1214,7 @@ new_calendar_item (DbusmenuMenuitem * newitem, return TRUE; } -/* + static gboolean new_timezone_item(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, @@ -1115,7 +1225,6 @@ new_timezone_item(DbusmenuMenuitem * newitem, return TRUE; } -*/ /* Grabs the label. Creates it if it doesn't exist already */ @@ -1156,8 +1265,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); } -- cgit v1.2.3 From 9c3aeee0b80f691a468812b097fda30332676e20 Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Fri, 4 Feb 2011 12:26:38 +0000 Subject: Updated the service, better memory handling, menu item sorting, triggered by about to show signal, discovered a new bug in dbusmenu https://bugs.launchpad.net/dbusmenu/+bug/713041 --- src/datetime-service.c | 169 +++++++++++++++++++++++++++++++------------------ 1 file changed, 107 insertions(+), 62 deletions(-) diff --git a/src/datetime-service.c b/src/datetime-service.c index 85fcc2d..736e89e 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -66,6 +66,7 @@ static DbusmenuMenuitem * tzchange = NULL; static GList * appointments = NULL; static ECal * ecal = NULL; static const gchar * ecal_timezone = NULL; +static icaltimezone *tzone; /* Geoclue trackers */ static GeoclueMasterClient * geo_master = NULL; @@ -244,6 +245,41 @@ update_timezone_menu_items(gpointer user_data) { return FALSE; } +// Compare function for g_list_sort of ECalComponent objects +static gint +compare_appointment_items (ECalComponent *a, + ECalComponent *b) { + + ECalComponentDateTime datetime_a, datetime_b; + struct tm tm_a, tm_b; + time_t t_a, t_b; + gint retval = 0; + + ECalComponentVType vtype = e_cal_component_get_vtype (a); + if (vtype == E_CAL_COMPONENT_EVENT) + e_cal_component_get_dtstart (a, &datetime_a); + else + e_cal_component_get_due (a, &datetime_a); + tm_a = icaltimetype_to_tm(datetime_a.value); + t_a = mktime(&tm_a); + + vtype = e_cal_component_get_vtype (b); + if (vtype == E_CAL_COMPONENT_EVENT) + e_cal_component_get_dtstart (b, &datetime_b); + else + e_cal_component_get_due (b, &datetime_b); + tm_b = icaltimetype_to_tm(datetime_b.value); + t_b = mktime(&tm_b); + + // Compare datetime_a and datetime_b, newest first in this sort. + if (t_a > t_b) retval = 1; + else if (t_a < t_b) retval = -1; + + e_cal_component_free_datetime (&datetime_a); + e_cal_component_free_datetime (&datetime_b); + return retval; +} + /* Populate the menu with todays, next 5 appointments. * we should hook into the ABOUT TO SHOW signal and use that to update the appointments. * Experience has shown that caldav's and webcals can be slow to load from eds @@ -251,55 +287,25 @@ update_timezone_menu_items(gpointer user_data) { */ static gboolean update_appointment_menu_items (gpointer user_data) { + if (!ecal) return FALSE; // 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; + gchar *query, *is, *ie, *ad; GList *objects = NULL, *l; - GError *gerror = NULL; DbusmenuMenuitem * item = NULL; + GError *gerror = NULL; gint 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? + + // FIXME can we put a limit on the number of results? Or if not complete, or is event/todo? Or sort it by date? 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)) { @@ -311,16 +317,21 @@ update_appointment_menu_items (gpointer user_data) { g_debug("Number of objects returned: %d", g_list_length(objects)); gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); if (appointments != NULL) { + g_debug("Freeing old appointments"); for (l = appointments; l; l = l->next) { + g_debug("Freeing old appointment"); 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); + dbusmenu_menuitem_child_delete(root, DBUSMENU_MENUITEM(item)); + //g_free(item); freeing makes it crash :/ is that a double free from child delete? + item = NULL; } appointments = NULL; } + // Sort the list see above FIXME regarding queries + objects = g_list_sort(objects, (GCompareFunc) compare_appointment_items); i = 0; for (l = objects; l; l = l->next) { ECalComponent *ecalcomp = l->data; @@ -330,7 +341,7 @@ update_appointment_menu_items (gpointer user_data) { icalproperty_status status; gchar *summary, *cmd; char right[20]; - const gchar *uri; + //const gchar *uri; struct tm tmp_tm; ECalComponentVType vtype = e_cal_component_get_vtype (ecalcomp); @@ -346,8 +357,6 @@ update_appointment_menu_items (gpointer user_data) { 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_bool (item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); @@ -370,23 +379,23 @@ update_appointment_menu_items (gpointer user_data) { // 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("Generate time string"); // Get today - g_debug("Generate strings"); - if (datetime.value->is_date) // Is today - not working :/ + time_t curtime = time(NULL); + struct tm* today = localtime(&curtime); + if (today->tm_mday == tmp_tm.tm_mday && + today->tm_mon == tmp_tm.tm_mon && + today->tm_year == tmp_tm.tm_year) strftime(right, 20, "%l:%M %P", &tmp_tm); else strftime(right, 20, "%a %l:%M %P", &tmp_tm); @@ -394,12 +403,15 @@ update_appointment_menu_items (gpointer user_data) { g_debug("Appointment time: %s", right); dbusmenu_menuitem_property_set (item, APPOINTMENT_MENUITEM_PROP_RIGHT, right); - //g_debug("Free datetime."); e_cal_component_free_datetime (&datetime); + ad = is = isodate_from_time_t(mktime(&tmp_tm)); + // 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_uid(ecalcomp, &uri); - cmd = g_strconcat("evolution calendar://", uri, NULL); + // FIXME Because the URI stuff is really broken, we're going to open the calendar at todays date instead + + //e_cal_component_get_uid(ecalcomp, &uri); + cmd = g_strconcat("evolution calendar:///?startdate=", ad, NULL); g_signal_connect (G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (activate_cb), cmd); @@ -407,33 +419,34 @@ update_appointment_menu_items (gpointer user_data) { // 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); - }*/ - + // needs EDS, ecal component colours are broken... + //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); + //} + //g_debug("Colour to use: %s", ecalcomp->color); //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. - + // For now we'll create a circle + + //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); - dbusmenu_menuitem_child_append (root, item); + dbusmenu_menuitem_child_add_position (root, item, 4+i); 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_list_free(objects); g_debug("End of objects"); - 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; } @@ -492,8 +505,39 @@ build_menus (DbusmenuMenuitem * root) // This just populates the items on startup later we want to be able to update the appointments before // presenting the menu. - update_appointment_menu_items(NULL); if (calendar != NULL) { + GError *gerror = NULL; + // TODO: In reality we should iterate sources of calendar, but getting the local one doens't lag for > a minute + 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; + } + 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; + } + 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; + } + + /* 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. + */ + if (ecal) ecal_timezone = icaltimezone_get_tzid(tzone); + + g_signal_connect(root, DBUSMENU_MENUITEM_SIGNAL_ABOUT_TO_SHOW, G_CALLBACK(update_appointment_menu_items), NULL); + update_appointment_menu_items(NULL); // TODO Create "Add appointment" menu item } // TODO Create FFR? "Add timer" menu item @@ -751,6 +795,7 @@ main (int argc, char ** argv) server = dbusmenu_server_new(MENU_OBJ); root = dbusmenu_menuitem_new(); dbusmenu_server_set_root(server, root); + build_menus(root); /* Setup geoclue */ -- cgit v1.2.3 From 85ace9f8b921ba8ffde95510953f008f92d8ac61 Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Fri, 4 Feb 2011 14:57:29 +0000 Subject: Added the timezone/location menu item code. --- src/indicator-datetime.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/src/indicator-datetime.c b/src/indicator-datetime.c index 7748a8c..20485e5 100644 --- a/src/indicator-datetime.c +++ b/src/indicator-datetime.c @@ -105,6 +105,7 @@ enum { typedef struct _indicator_item_t indicator_item_t; struct _indicator_item_t { + GtkWidget * radio; GtkWidget * icon; GtkWidget * label; GtkWidget * right; @@ -175,6 +176,7 @@ static void update_time (IndicatorDatetime * self); static void receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name, GVariant * parameters, gpointer user_data); static void service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data); static gint generate_strftime_bitmask (const char *time_str); +static GSList *location_group = NULL; /* Indicator Module Config */ INDICATOR_SET_VERSION @@ -1221,9 +1223,50 @@ new_timezone_item(DbusmenuMenuitem * newitem, 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 */ + // Menu item with a radio button and a right aligned time + 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); + + mi_data->radio = gtk_radio_button_new(location_group); + if (location_group == NULL) + location_group = gtk_radio_button_get_group(mi_data->radio); + + gtk_toggle_button_set_active(mi_data->radio, + dbusmenu_menuitem_property_get_bool(newitem, TIMEZONE_MENUITEM_PROP_RADIO)); - return TRUE; + gtk_box_pack_start(GTK_BOX(hbox), mi_data->radio, FALSE, FALSE, 0); + gtk_widget_show(mi_data->radio); + + /* 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; } /* Grabs the label. Creates it if it doesn't -- cgit v1.2.3 From b4f0c229fe3f6b1c74bff1caf3aca774a1c0e0f6 Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Fri, 4 Feb 2011 16:15:47 +0000 Subject: Added ESource Colours a circle drawn onto a cairo surface, however this code has one caveat, it's un-testable with evolution as evolutions color peek is currently broken. However I've used a very similar method of exchanging GdkDrawables and cairo_surface_t before and it worked... Lets see this time :/ --- src/datetime-service.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/datetime-service.c b/src/datetime-service.c index 736e89e..3f5aa80 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -24,9 +24,12 @@ with this program. If not, see . #include #include +#include #include #include +#include +#include #include #include #include @@ -41,6 +44,7 @@ with this program. If not, see . #include // Other users of ecal seem to also include these, not sure why they should be included by the above #include +#include #include @@ -417,28 +421,29 @@ update_appointment_menu_items (gpointer user_data) { g_debug("Command to Execute: %s", cmd); - // Get the colour E_CAL_COMPONENT_FIELD_COLOR - // Get the icon, either EVENT or MEMO or TODO? - // needs EDS, ecal component colours are broken... - //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); - //} - //g_debug("Colour to use: %s", ecalcomp->color); - - //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. + ESource *source = e_cal_get_source (ecal); + //e_source_get_color (source, &source_color); api has been changed + const gchar *color_spec = e_source_peek_color_spec(source); + GdkColor color; + g_debug("Colour to use: %s", color_spec); + + // Draw the correct icon for the appointment type and then tint it using mask fill. // For now we'll create a circle + if (color_spec != NULL) { + gdk_color_parse (color_spec, &color); + + cairo_surface_t *cs = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); + cairo_t *cr = cairo_create(cs); + cairo_arc (cr, width/2, height/2, width/2, 0, 2 * M_PI); + gdk_cairo_set_source_color(cr, &color); + cairo_fill(cr); - - //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); - + GdkPixbuf * pixbuf = gdk_pixbuf_get_from_drawable(NULL, (GdkDrawable*)cs, + gdk_colormap_new(gdk_drawable_get_visual((GdkDrawable*)cs), TRUE), 0,0,0,0, width, height); + cairo_destroy(cr); + + dbusmenu_menuitem_property_set_image (item, APPOINTMENT_MENUITEM_PROP_ICON, pixbuf); + } dbusmenu_menuitem_child_add_position (root, item, 4+i); appointments = g_list_append (appointments, item); // Keep track of the items here to make them east to remove -- cgit v1.2.3 From 6da530ab489871e8da45db87d7ba922fdb9e4a56 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 4 Feb 2011 15:32:22 -0600 Subject: Removing a ref on the item --- src/datetime-service.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/datetime-service.c b/src/datetime-service.c index 736e89e..624bbbf 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -325,6 +325,7 @@ update_appointment_menu_items (gpointer user_data) { appointments = g_list_remove(appointments, item); dbusmenu_menuitem_child_delete(root, DBUSMENU_MENUITEM(item)); //g_free(item); freeing makes it crash :/ is that a double free from child delete? + g_object_unref(G_OBJECT(item)); item = NULL; } appointments = NULL; -- cgit v1.2.3 From 6076c79d0634fd5729c0a4279e16439f2156bb38 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 4 Feb 2011 15:39:51 -0600 Subject: Removing comment --- src/datetime-service.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/datetime-service.c b/src/datetime-service.c index 624bbbf..cfb0304 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -324,7 +324,6 @@ update_appointment_menu_items (gpointer user_data) { // Remove all the existing menu items which are in appointments. appointments = g_list_remove(appointments, item); dbusmenu_menuitem_child_delete(root, DBUSMENU_MENUITEM(item)); - //g_free(item); freeing makes it crash :/ is that a double free from child delete? g_object_unref(G_OBJECT(item)); item = NULL; } -- cgit v1.2.3 From 8855894205bae81b1423a2004caf2c421e720229 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 4 Feb 2011 15:51:40 -0600 Subject: Reshuffle some code and add a couple of debug statements --- src/datetime-service.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/datetime-service.c b/src/datetime-service.c index cfb0304..c8194a4 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -293,7 +293,6 @@ update_appointment_menu_items (gpointer user_data) { time_t t1, t2; gchar *query, *is, *ie, *ad; GList *objects = NULL, *l; - DbusmenuMenuitem * item = NULL; GError *gerror = NULL; gint i; gint width, height; @@ -316,18 +315,18 @@ update_appointment_menu_items (gpointer user_data) { } g_debug("Number of objects returned: %d", g_list_length(objects)); gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); + + /* Remove all of the previous appointments */ if (appointments != NULL) { g_debug("Freeing old appointments"); - for (l = appointments; l; l = l->next) { - g_debug("Freeing old appointment"); - item = l->data; + while (appointments != NULL) { + DbusmenuMenuitem * litem = DBUSMENU_MENUITEM(appointments->data); + g_debug("Freeing old appointment: %p", litem); // Remove all the existing menu items which are in appointments. - appointments = g_list_remove(appointments, item); - dbusmenu_menuitem_child_delete(root, DBUSMENU_MENUITEM(item)); - g_object_unref(G_OBJECT(item)); - item = NULL; + appointments = g_list_remove(appointments, litem); + dbusmenu_menuitem_child_delete(root, DBUSMENU_MENUITEM(litem)); + g_object_unref(G_OBJECT(litem)); } - appointments = NULL; } // Sort the list see above FIXME regarding queries @@ -343,6 +342,7 @@ update_appointment_menu_items (gpointer user_data) { char right[20]; //const gchar *uri; struct tm tmp_tm; + DbusmenuMenuitem * item; ECalComponentVType vtype = e_cal_component_get_vtype (ecalcomp); @@ -441,6 +441,7 @@ update_appointment_menu_items (gpointer user_data) { dbusmenu_menuitem_child_add_position (root, item, 4+i); appointments = g_list_append (appointments, item); // Keep track of the items here to make them east to remove + g_debug("Adding appointment: %p", item); if (i == 4) break; // See above FIXME regarding query result limit i++; -- cgit v1.2.3 From 2b9d7908ec2117de20887ebda1baca1049a54e87 Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Mon, 7 Feb 2011 10:35:58 +0000 Subject: Updated datetime service slightly to draw coloured dots for evolution colours, evolution is still slightly broken at doing it's part here and returns null colours. Updated configure.ac (hope this doesn't break merge), and added the radio menu item with a right aligned time to the indicator so we can have location/timezone entries. --- configure.ac | 42 ++++++++++++++----- src/datetime-service.c | 102 ++++++++++++++++++++++++++--------------------- src/indicator-datetime.c | 4 +- 3 files changed, 91 insertions(+), 57 deletions(-) diff --git a/configure.ac b/configure.ac index cc96999..4f35d38 100644 --- a/configure.ac +++ b/configure.ac @@ -60,7 +60,10 @@ INDICATOR_DISPLAY_OBJECTS=0.1.10 GEOCLUE_REQUIRED_VERSION=0.12.0 OOBS_REQUIRED_VERSION=2.31.0 ECAL_REQUIRED_VERSION=2.30 +EDS_REQUIRED_VERSION=2.30 ICAL_REQUIRED_VERSION=0.44 +CAIRO_REQUIRED_VERSION=1.10 +GDK_REQUIRED_VERSION=2.22 AS_IF([test "x$with_gtk" = x3], [PKG_CHECK_MODULES(INDICATOR, indicator3 >= $INDICATOR_REQUIRED_VERSION @@ -77,15 +80,36 @@ AS_IF([test "x$with_gtk" = x3], [AC_MSG_FAILURE([Value for --with-gtk was neither 2 nor 3])] ) -PKG_CHECK_MODULES(SERVICE, indicator >= $INDICATOR_REQUIRED_VERSION - dbusmenu-glib-0.4 >= $DBUSMENUGLIB_REQUIRED_VERSION - libido-0.1 >= $INDICATOR_DISPLAY_OBJECTS - gio-2.0 >= $GIO_REQUIRED_VERSION - geoclue >= $GEOCLUE_REQUIRED_VERSION - liboobs-1 >= $OOBS_REQUIRED_VERSION - libecal-1.2 >= $ECAL_REQUIRED_VERSION - libical >= $ICAL_REQUIRED_VERSION) - +AS_IF([test "x$with_gtk" = x3], + [PKG_CHECK_MODULES(SERVICE, indicator >= $INDICATOR_REQUIRED_VERSION + dbusmenu-glib-0.4 >= $DBUSMENUGLIB_REQUIRED_VERSION + dbusmenu-gtk3-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION + libido-0.1 >= $INDICATOR_DISPLAY_OBJECTS + gio-2.0 >= $GIO_REQUIRED_VERSION + geoclue >= $GEOCLUE_REQUIRED_VERSION + liboobs-1 >= $OOBS_REQUIRED_VERSION + libecal-1.2 >= $ECAL_REQUIRED_VERSION + libical >= $ICAL_REQUIRED_VERSION + libedataserver-1.2 >= EDS_REQUIRED_VERSION + cairo >= CAIRO_REQUIRED_VERSION + gdk-2.0 >= GDK_REQUIRED_VERSION) + ], + [test "x$with_gtk" = x2], + [PKG_CHECK_MODULES(SERVICE, indicator >= $INDICATOR_REQUIRED_VERSION + dbusmenu-glib-0.4 >= $DBUSMENUGLIB_REQUIRED_VERSION + dbusmenu-gtk-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION + libido-0.1 >= $INDICATOR_DISPLAY_OBJECTS + gio-2.0 >= $GIO_REQUIRED_VERSION + geoclue >= $GEOCLUE_REQUIRED_VERSION + liboobs-1 >= $OOBS_REQUIRED_VERSION + libecal-1.2 >= $ECAL_REQUIRED_VERSION + libical >= $ICAL_REQUIRED_VERSION + libedataserver-1.2 >= EDS_REQUIRED_VERSION + cairo >= CAIRO_REQUIRED_VERSION + gdk-2.0 >= GDK_REQUIRED_VERSION) + ], + [AC_MSG_FAILURE([Value for --with-gtk was neither 2 nor 3])] +) AC_SUBST(INDICATOR_CFLAGS) AC_SUBST(INDICATOR_LIBS) diff --git a/src/datetime-service.c b/src/datetime-service.c index 3f5aa80..3aa6acf 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -53,6 +53,7 @@ with this program. If not, see . #include "dbus-shared.h" static void geo_create_client (GeoclueMaster * master, GeoclueMasterClient * client, gchar * path, GError * error, gpointer user_data); +static gboolean update_appointment_menu_items (gpointer user_data); static void setup_timer (void); static IndicatorService * service = NULL; @@ -67,6 +68,8 @@ static DbusmenuMenuitem * date = NULL; static DbusmenuMenuitem * calendar = NULL; static DbusmenuMenuitem * settings = NULL; static DbusmenuMenuitem * tzchange = NULL; +static DbusmenuMenuitem * add_appointment = NULL; +static DbusmenuMenuitem * add_location = NULL; static GList * appointments = NULL; static ECal * ecal = NULL; static const gchar * ecal_timezone = NULL; @@ -234,10 +237,47 @@ check_for_calendar (gpointer user_data) g_debug("Found the calendar application: %s", evo); dbusmenu_menuitem_property_set_bool(calendar, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); dbusmenu_menuitem_property_set_bool(calendar, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); + dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); + dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); + + GError *gerror = NULL; + // TODO: In reality we should iterate sources of calendar, but getting the local one doens't lag for > a minute + 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; + } + 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; + } + 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; + } + + /* 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. + */ + if (ecal) ecal_timezone = icaltimezone_get_tzid(tzone); + + update_appointment_menu_items(NULL); + g_signal_connect(root, DBUSMENU_MENUITEM_SIGNAL_ABOUT_TO_SHOW, G_CALLBACK(update_appointment_menu_items), NULL); + g_free(evo); } else { g_debug("Unable to find calendar app."); dbusmenu_menuitem_property_set_bool(calendar, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); + dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); } return FALSE; @@ -245,7 +285,12 @@ check_for_calendar (gpointer user_data) static gboolean update_timezone_menu_items(gpointer user_data) { - // Get the location preferences and the current location, highlight the current location somehow + // Get the current location as specified by the user as a place name and time and add it, + // Get the location from geoclue as a place and time and add it, + // Get the evolution calendar timezone as a place and time and add it, + // Get the current timezone that the clock uses and select that + // Iterate over configured places and add any which aren't already listed + // Hook up each of these to setting the time/current timezone return FALSE; } @@ -508,51 +553,12 @@ build_menus (DbusmenuMenuitem * root) dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); dbusmenu_menuitem_child_append(root, separator); - // This just populates the items on startup later we want to be able to update the appointments before - // presenting the menu. - if (calendar != NULL) { - GError *gerror = NULL; - // TODO: In reality we should iterate sources of calendar, but getting the local one doens't lag for > a minute - 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; - } - 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; - } - 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; - } - - /* 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. - */ - if (ecal) ecal_timezone = icaltimezone_get_tzid(tzone); - - g_signal_connect(root, DBUSMENU_MENUITEM_SIGNAL_ABOUT_TO_SHOW, G_CALLBACK(update_appointment_menu_items), NULL); - update_appointment_menu_items(NULL); - // TODO Create "Add appointment" menu item - } - // TODO Create FFR? "Add timer" menu item - - separator = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); - dbusmenu_menuitem_child_append(root, separator); - - update_timezone_menu_items(NULL); - // TODO Create "Add location" menu item + add_appointment = dbusmenu_menuitem_new(); + dbusmenu_menuitem_property_set (add_appointment, DBUSMENU_MENUITEM_PROP_LABEL, _("Add Appointment")); + dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_ENABLED, FALSE); + dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, 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, 4); separator = dbusmenu_menuitem_new(); dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); @@ -565,6 +571,10 @@ build_menus (DbusmenuMenuitem * root) dbusmenu_menuitem_child_append(root, tzchange); check_timezone_sync(); + separator = dbusmenu_menuitem_new(); + dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); + dbusmenu_menuitem_child_append(root, separator); + settings = dbusmenu_menuitem_new(); dbusmenu_menuitem_property_set (settings, DBUSMENU_MENUITEM_PROP_LABEL, _("Time & Date Settings...")); /* insensitive until we check for available apps */ diff --git a/src/indicator-datetime.c b/src/indicator-datetime.c index 20485e5..1f61864 100644 --- a/src/indicator-datetime.c +++ b/src/indicator-datetime.c @@ -1236,9 +1236,9 @@ new_timezone_item(DbusmenuMenuitem * newitem, mi_data->radio = gtk_radio_button_new(location_group); if (location_group == NULL) - location_group = gtk_radio_button_get_group(mi_data->radio); + location_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(mi_data->radio)); - gtk_toggle_button_set_active(mi_data->radio, + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mi_data->radio), dbusmenu_menuitem_property_get_bool(newitem, TIMEZONE_MENUITEM_PROP_RADIO)); gtk_box_pack_start(GTK_BOX(hbox), mi_data->radio, FALSE, FALSE, 0); -- cgit v1.2.3 From d59aaf9c31b2db87b517095caff818a9ff50343a Mon Sep 17 00:00:00 2001 From: karl-qdh Date: Tue, 8 Feb 2011 16:21:32 +0000 Subject: Re-adding tedg's changes --- src/datetime-service.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/datetime-service.c b/src/datetime-service.c index 3aa6acf..eb280dc 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -342,7 +342,6 @@ update_appointment_menu_items (gpointer user_data) { time_t t1, t2; gchar *query, *is, *ie, *ad; GList *objects = NULL, *l; - DbusmenuMenuitem * item = NULL; GError *gerror = NULL; gint i; gint width, height; @@ -365,18 +364,18 @@ update_appointment_menu_items (gpointer user_data) { } g_debug("Number of objects returned: %d", g_list_length(objects)); gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); + + /* Remove all of the previous appointments */ if (appointments != NULL) { g_debug("Freeing old appointments"); - for (l = appointments; l; l = l->next) { - g_debug("Freeing old appointment"); - item = l->data; + while (appointments != NULL) { + DbusmenuMenuitem * litem = DBUSMENU_MENUITEM(appointments->data); + g_debug("Freeing old appointment: %p", litem); // Remove all the existing menu items which are in appointments. - appointments = g_list_remove(appointments, item); - dbusmenu_menuitem_child_delete(root, DBUSMENU_MENUITEM(item)); - //g_free(item); freeing makes it crash :/ is that a double free from child delete? - item = NULL; + appointments = g_list_remove(appointments, litem); + dbusmenu_menuitem_child_delete(root, DBUSMENU_MENUITEM(litem)); + g_object_unref(G_OBJECT(litem)); } - appointments = NULL; } // Sort the list see above FIXME regarding queries @@ -392,6 +391,7 @@ update_appointment_menu_items (gpointer user_data) { char right[20]; //const gchar *uri; struct tm tmp_tm; + DbusmenuMenuitem * item; ECalComponentVType vtype = e_cal_component_get_vtype (ecalcomp); @@ -491,6 +491,7 @@ update_appointment_menu_items (gpointer user_data) { } dbusmenu_menuitem_child_add_position (root, item, 4+i); appointments = g_list_append (appointments, item); // Keep track of the items here to make them east to remove + g_debug("Adding appointment: %p", item); if (i == 4) break; // See above FIXME regarding query result limit i++; -- cgit v1.2.3 From a0328a7ca5a8aad4a8713ee53ff3b790fa958c86 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 8 Feb 2011 13:40:26 -0600 Subject: Changing warning. --- src/datetime-service.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/datetime-service.c b/src/datetime-service.c index 7d35a38..e7b20fb 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -513,7 +513,10 @@ geo_create_client (GeoclueMaster * master, GeoclueMasterClient * client, gchar * geo_master = client; - g_return_if_fail(geo_master != NULL); + if (geo_master != NULL) { + g_warning("Unable to get a GeoClue client! Geolocation based timezone support will not be available."); + return; + } g_object_ref(G_OBJECT(geo_master)); -- cgit v1.2.3 From c721c1d4d5d63e5765898aab2b8906b3187b3e93 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 8 Feb 2011 13:46:45 -0600 Subject: Made translatable as it's a user focused message. --- src/datetime-service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/datetime-service.c b/src/datetime-service.c index e7b20fb..7484144 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -514,7 +514,7 @@ geo_create_client (GeoclueMaster * master, GeoclueMasterClient * client, gchar * geo_master = client; if (geo_master != NULL) { - g_warning("Unable to get a GeoClue client! Geolocation based timezone support will not be available."); + g_warning(_("Unable to get a GeoClue client! Geolocation based timezone support will not be available.")); return; } -- cgit v1.2.3 From 088c1f4ccd34ee463c9aa414cda870af260bdb55 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 8 Feb 2011 22:18:56 -0600 Subject: Commenting out unused code for now --- src/datetime-service.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/datetime-service.c b/src/datetime-service.c index 9e3e938..129d93e 100644 --- a/src/datetime-service.c +++ b/src/datetime-service.c @@ -71,7 +71,7 @@ static DbusmenuMenuitem * calendar = NULL; static DbusmenuMenuitem * settings = NULL; static DbusmenuMenuitem * tzchange = NULL; static DbusmenuMenuitem * add_appointment = NULL; -static DbusmenuMenuitem * add_location = NULL; +// static DbusmenuMenuitem * add_location = NULL; static GList * appointments = NULL; static ECal * ecal = NULL; static const gchar * ecal_timezone = NULL; @@ -285,6 +285,7 @@ check_for_calendar (gpointer user_data) return FALSE; } +/* static gboolean update_timezone_menu_items(gpointer user_data) { // Get the current location as specified by the user as a place name and time and add it, @@ -295,6 +296,7 @@ update_timezone_menu_items(gpointer user_data) { // Hook up each of these to setting the time/current timezone return FALSE; } +*/ // Compare function for g_list_sort of ECalComponent objects static gint -- cgit v1.2.3