aboutsummaryrefslogtreecommitdiff
path: root/src/datetime-service.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/datetime-service.c')
-rw-r--r--src/datetime-service.c446
1 files changed, 293 insertions, 153 deletions
diff --git a/src/datetime-service.c b/src/datetime-service.c
index 6303a98..3685c96 100644
--- a/src/datetime-service.c
+++ b/src/datetime-service.c
@@ -47,7 +47,6 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <libical/icaltime.h>
#include <cairo/cairo.h>
-
#include <oobs/oobs-timeconfig.h>
#include "datetime-interface.h"
@@ -73,6 +72,7 @@ static DatetimeInterface * dbus = NULL;
static DbusmenuMenuitem * date = NULL;
static DbusmenuMenuitem * calendar = NULL;
static DbusmenuMenuitem * settings = NULL;
+static DbusmenuMenuitem * events_separator = NULL;
static DbusmenuMenuitem * locations_separator = NULL;
static DbusmenuMenuitem * geo_location = NULL;
static DbusmenuMenuitem * current_location = NULL;
@@ -80,6 +80,8 @@ static DbusmenuMenuitem * current_location = NULL;
static DbusmenuMenuitem * add_appointment = NULL;
static GList * appointments = NULL;
static GList * dconflocations = NULL;
+static GList * comp_instances = NULL;
+static gboolean updating_appointments = FALSE;
GSettings *conf;
@@ -91,6 +93,13 @@ static GeoclueAddress * geo_address = NULL;
static gchar * current_timezone = NULL;
static gchar * geo_timezone = NULL;
+struct comp_instance {
+ ECalComponent *comp;
+ time_t start;
+ time_t end;
+ ESource *source;
+};
+
static void
set_timezone_label (DbusmenuMenuitem * mi, const gchar * location)
{
@@ -127,7 +136,7 @@ check_timezone_sync (void) {
} else {
g_debug("Timezones are different");
}
-
+
gboolean show = g_settings_get_boolean (conf, SETTINGS_SHOW_LOCATIONS_S);
if (geo_location != NULL && current_location != NULL) {
@@ -278,8 +287,50 @@ month_changed_cb (DbusmenuMenuitem * menuitem, GVariant *variant, guint timestam
return TRUE;
}
+static guint ecaltimer = 0;
+
+static void
+start_ecal_timer(void)
+{
+ if (ecaltimer != 0) g_source_remove(ecaltimer);
+ if (update_appointment_menu_items(NULL))
+ ecaltimer = g_timeout_add_seconds(60*5, update_appointment_menu_items, NULL);
+}
+
+static void
+stop_ecal_timer(void)
+{
+ if (ecaltimer != 0) g_source_remove(ecaltimer);
+}
+
+static void
+show_events_changed (void)
+{
+ if (g_settings_get_boolean(conf, SETTINGS_SHOW_EVENTS_S)) {
+ dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
+ dbusmenu_menuitem_property_set_bool(events_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
+ start_ecal_timer();
+ } else {
+ dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
+ dbusmenu_menuitem_property_set_bool(events_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
+ /* Remove all of the previous appointments */
+ if (appointments != NULL) {
+ g_debug("Freeing old appointments");
+ 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, litem);
+ dbusmenu_menuitem_child_delete(root, DBUSMENU_MENUITEM(litem));
+ g_object_unref(G_OBJECT(litem));
+ }
+ }
+ stop_ecal_timer();
+ }
+}
+
/* Looks for the calendar application and enables the item if
- we have one */
+ we have one, starts ecal timer if events are turned on */
static gboolean
check_for_calendar (gpointer user_data)
{
@@ -293,21 +344,26 @@ check_for_calendar (gpointer user_data)
dbusmenu_menuitem_property_set_bool(calendar, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
dbusmenu_menuitem_property_set_bool(calendar, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
- DbusmenuMenuitem * separator = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
- dbusmenu_menuitem_child_add_position(root, separator, 2);
-
+ events_separator = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_property_set(events_separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
+ dbusmenu_menuitem_child_add_position(root, events_separator, 2);
add_appointment = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set (add_appointment, DBUSMENU_MENUITEM_PROP_LABEL, _("Add Appointment"));
+ dbusmenu_menuitem_property_set (add_appointment, DBUSMENU_MENUITEM_PROP_LABEL, _("Add Appointment"));
dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
- 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, 3);
- // Update the calendar items every 5 minutes if it updates the first time
- if (update_appointment_menu_items(NULL))
- g_timeout_add_seconds(60*5, update_appointment_menu_items, NULL);
-
+
+ if (g_settings_get_boolean(conf, SETTINGS_SHOW_EVENTS_S)) {
+ dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
+ dbusmenu_menuitem_property_set_bool(events_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
+ start_ecal_timer();
+ } else {
+ dbusmenu_menuitem_property_set_bool(add_appointment, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
+ dbusmenu_menuitem_property_set_bool(events_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
+ stop_ecal_timer();
+ }
+
// Connect to event::month-changed
g_signal_connect(calendar, "event::month-changed", G_CALLBACK(month_changed_cb), NULL);
g_free(evo);
@@ -326,6 +382,7 @@ update_timezone_menu_items(gpointer user_data) {
g_debug("Updating timezone menu items");
gchar ** locations = g_settings_get_strv(conf, SETTINGS_LOCATIONS_S);
+
if (locations == NULL) {
g_debug("No locations configured (NULL)");
return FALSE;
@@ -381,7 +438,11 @@ update_timezone_menu_items(gpointer user_data) {
// Authentication function
static gchar *
-auth_func (ECal *ecal, const gchar *prompt, const gchar *key, gpointer user_data) {
+auth_func (ECal *ecal,
+ const gchar *prompt,
+ const gchar *key,
+ gpointer user_data)
+{
gboolean remember; // TODO: Is this useful? Should we be storing it somewhere?
ESource *source = e_cal_get_source (ecal);
gchar *auth_domain = e_source_get_duped_property (source, "auth-domain");
@@ -407,47 +468,92 @@ auth_func (ECal *ecal, const gchar *prompt, const gchar *key, gpointer user_data
return password;
}
+static gint
+compare_comp_instances (gconstpointer a,
+ gconstpointer b)
+{
+ const struct comp_instance *ci_a = a;
+ const struct comp_instance *ci_b = b;
+ time_t d = ci_a->start - ci_b->start;
+ if (d < 0) return -1;
+ else if (d > 0) return 1;
+ return 0;
+}
-// 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;
-
- if (a == NULL || b == NULL) return retval;
-
- ECalComponentVType vtype = e_cal_component_get_vtype (a);
+static gboolean
+populate_appointment_instances (ECalComponent *comp,
+ time_t instance_start,
+ time_t instance_end,
+ gpointer data)
+{
+ g_debug("Appending item %p", comp);
- if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) return -1;
+ ECalComponentVType vtype = e_cal_component_get_vtype (comp);
+ if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) return FALSE;
- 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);
+ icalproperty_status status;
+ e_cal_component_get_status (comp, &status);
+ if (status == ICAL_STATUS_COMPLETED || status == ICAL_STATUS_CANCELLED) return FALSE;
- vtype = e_cal_component_get_vtype (b);
- if (vtype != E_CAL_COMPONENT_EVENT && vtype != E_CAL_COMPONENT_TODO) return 1;
+ g_object_ref(comp);
+
+ ECalComponentDateTime datetime;
+ icaltimezone *appointment_zone = NULL;
+ icaltimezone *current_zone = NULL;
if (vtype == E_CAL_COMPONENT_EVENT)
- e_cal_component_get_dtstart (b, &datetime_b);
+ e_cal_component_get_dtstart (comp, &datetime);
else
- e_cal_component_get_due (b, &datetime_b);
- tm_b = icaltimetype_to_tm(datetime_b.value);
- t_b = mktime(&tm_b);
+ e_cal_component_get_due (comp, &datetime);
- // 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;
+ appointment_zone = icaltimezone_get_builtin_timezone_from_tzid(datetime.tzid);
+ current_zone = icaltimezone_get_builtin_timezone_from_tzid(current_timezone);
+ if (!appointment_zone || datetime.value->is_date) { // If it's today put in the current timezone?
+ appointment_zone = current_zone;
+ }
+
+ // TODO: Convert the timezone into a 3 letter abbreviation if it's different to current_timezone
+ // TODO: Add the appointment timezone to the list if it's not already there.
+
+ GSList *period_list = NULL, *l;
+ if (e_cal_component_has_recurrences (comp)) {
+ e_cal_component_get_rdate_list (comp, &period_list);
+ g_debug("ECalComponent has recurrences");
+ } else {
+ g_debug("ECalComponent doesn't have recurrences");
+ }
+
+ struct comp_instance *ci;
+ ci = g_new (struct comp_instance, 1);
+
+ // Do we get rdate_list?
+ if (period_list != NULL) {
+ g_debug("Got recurring periods");
+ for (l = period_list; l; l = l->next) {
+ ECalComponentPeriod *period = l->data;
+ struct tm tmp_tm = icaltimetype_to_tm_with_zone (&period->start, appointment_zone, current_zone);
+ time_t start = mktime(&tmp_tm);
+ g_debug("period time: %d", (int)start);
+
+ tmp_tm = icaltimetype_to_tm_with_zone (&period->u.end, appointment_zone, current_zone);
+ time_t end = mktime(&tmp_tm);
+
+ if (start >= instance_start && end < instance_end) {
+ ci->start = start;
+ ci->end = end;
+ }
+ }
+ } else {
+ ci->start = instance_start;
+ ci->end = instance_end;
+ g_debug("Got no recurring periods set time to start %s, end %s", ctime(&instance_start), ctime(&instance_end));
+ }
+
+ ci->comp = comp;
+ ci->source = E_SOURCE(data);
- e_cal_component_free_datetime (&datetime_a);
- e_cal_component_free_datetime (&datetime_b);
- return retval;
+ comp_instances = g_list_append(comp_instances, ci);
+ return TRUE;
}
/* Populate the menu with todays, next 5 appointments.
@@ -456,16 +562,19 @@ compare_appointment_items (ECalComponent *a,
* this is a problem mainly on the EDS side of things, not ours.
*/
static gboolean
-update_appointment_menu_items (gpointer user_data) {
+update_appointment_menu_items (gpointer 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.
if (calendar == NULL) return FALSE;
if (!g_settings_get_boolean(conf, SETTINGS_SHOW_EVENTS_S)) return FALSE;
+ if (updating_appointments) return TRUE;
+ updating_appointments = TRUE;
time_t t1, t2;
- gchar *query, *is, *ie, *ad;
- GList *objects = NULL, *l;
- GList *allobjects = NULL;
+ gchar *ad;
+ GList *l;
+ //GList *allobjects = NULL;
GSList *g;
GError *gerror = NULL;
gint i;
@@ -474,12 +583,7 @@ update_appointment_menu_items (gpointer user_data) {
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);
-
- gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
+ t2 += (time_t) (7 * 24 * 60 * 60); /* 7 days ahead of now, we actually need number_of_days_in_this_month */
/* Remove all of the previous appointments */
if (appointments != NULL) {
@@ -495,15 +599,23 @@ update_appointment_menu_items (gpointer user_data) {
}
// TODO Remove all highlights from the calendar widget
-
- // 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);
if (!e_cal_get_sources(&sources, E_CAL_SOURCE_TYPE_EVENT, &gerror)) {
g_debug("Failed to get ecal sources\n");
return FALSE;
}
-
+
+ // Free comp_instances if not NULL
+ if (comp_instances != NULL) {
+ g_debug("Freeing comp_instances: may be an overlap\n");
+ for (l = comp_instances; l; l = l->next) {
+ const struct comp_instance *ci = l->data;
+ g_object_unref(ci->comp);
+ g_list_free(comp_instances);
+ comp_instances = NULL;
+ }
+ }
+
// iterate the query for all sources
for (g = e_source_list_peek_groups (sources); g; g = g->next) {
ESourceGroup *group = E_SOURCE_GROUP (g->data);
@@ -511,7 +623,7 @@ update_appointment_menu_items (gpointer user_data) {
for (s = e_source_group_peek_sources (group); s; s = s->next) {
ESource *source = E_SOURCE (s->data);
- g_signal_connect (G_OBJECT(source), "changed", G_CALLBACK (update_appointment_menu_items), NULL);
+ //g_signal_connect (G_OBJECT(source), "changed", G_CALLBACK (update_appointment_menu_items), NULL);
ECal *ecal = e_cal_new(source, E_CAL_SOURCE_TYPE_EVENT);
e_cal_set_auth_func (ecal, (ECalAuthFunc) auth_func, NULL);
@@ -522,55 +634,35 @@ update_appointment_menu_items (gpointer user_data) {
continue;
}
- 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);
- gerror = NULL;
- continue;
- }
- g_debug("Number of objects returned: %d", g_list_length(objects));
-
- if (allobjects == NULL) {
- allobjects = objects;
- } else if (objects != NULL) {
- allobjects = g_list_concat(allobjects, objects);
- g_object_unref(objects);
- }
+ g_debug("Generating instances");
+ e_cal_generate_instances (ecal, t1, t2, (ECalRecurInstanceFn) populate_appointment_instances, (gpointer) source);
+ g_debug("Number of objects returned: %d", g_list_length(comp_instances));
}
}
-
- // Sort the list see above FIXME regarding queries
- g_debug("Sorting objects list");
- allobjects = g_list_sort(allobjects, (GCompareFunc) compare_appointment_items);
+ GList *sorted_comp_instances = g_list_sort(comp_instances, compare_comp_instances);
+ comp_instances = NULL;
i = 0;
- for (l = allobjects; l; l = l->next) {
- ECalComponent *ecalcomp = l->data;
+
+ gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
+ if (width == 0) width = 12;
+ if (height == 0) height = 12;
+ for (l = sorted_comp_instances; l; l = l->next) {
+ struct comp_instance *ci = l->data;
+ ECalComponent *ecalcomp = ci->comp;
ECalComponentText valuetext;
- ECalComponentDateTime datetime;
- icaltimezone *appointment_zone = NULL;
- icaltimezone *current_zone = NULL;
- icalproperty_status status;
+ //ECalComponentDateTime datetime;
gchar *summary, *cmd;
char right[20];
//const gchar *uri;
- struct tm tmp_tm;
DbusmenuMenuitem * item;
- g_debug("Start Object");
- 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;
-
+ g_debug("Start Object %p", ecalcomp);
+
+ // TODO Mark days
+
+ if (i >= 5) continue;
+ i++;
+
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);
@@ -584,97 +676,143 @@ update_appointment_menu_items (gpointer user_data) {
g_debug("Summary: %s", 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);
-
+ //appointment_zone = icaltimezone_get_builtin_timezone_from_tzid(datetime.tzid);
+ //current_zone = icaltimezone_get_builtin_timezone_from_tzid(current_timezone);
+ //if (!appointment_zone || datetime.value->is_date) { // If it's today put in the current timezone?
+ // appointment_zone = current_zone;
+ //}
// 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;
- }
-
- appointment_zone = icaltimezone_get_builtin_timezone_from_tzid(datetime.tzid);
- current_zone = icaltimezone_get_builtin_timezone_from_tzid(current_timezone);
- if (!appointment_zone || datetime.value->is_date) { // If it's today put in the current timezone?
- appointment_zone = current_zone;
- }
// TODO: Convert the timezone into a 3 letter abbreviation if it's different to current_timezone
// TODO: Add the appointment timezone to the list if it's not already there.
- tmp_tm = icaltimetype_to_tm_with_zone (datetime.value, appointment_zone, current_zone);
+ //tmp_tm = icaltimetype_to_tm_with_zone (datetime.value, appointment_zone, current_zone);
+
+ // Due text
+ ECalComponentVType vtype = e_cal_component_get_vtype (ecalcomp);
- g_debug("Generate time string");
// Get today
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);
+ struct tm *today = localtime(&curtime);
+
+ int mday = today->tm_mday;
+ int mon = today->tm_mon;
+ int year = today->tm_year;
+
+ struct tm *due;
+ g_debug("Start time %s", ctime(&ci->start));
+ if (vtype == E_CAL_COMPONENT_EVENT) due = localtime(&ci->start);
+ else if (vtype == E_CAL_COMPONENT_TODO) due = localtime(&ci->end);
+ else continue;
+
+ strftime(right, 20, "%a %l:%M %p", due);
+ g_debug("Start time %s -> %s", asctime(due), right);
+
+ int dmday = due->tm_mday;
+ int dmon = due->tm_mon;
+ int dyear = due->tm_year;
+
+ if ((mday == dmday) && (mon == dmon) && (year == dyear))
+ strftime(right, 20, "%l:%M %p", due);
else
- strftime(right, 20, "%a %l:%M %P", &tmp_tm);
+ strftime(right, 20, "%a %l:%M %p", due);
g_debug("Appointment time: %s", right);
- g_debug("Appointment timezone: %s", datetime.tzid);
- g_debug("Appointment timezone: %s", icaltimezone_get_tzid(appointment_zone)); // These two should be the same
+ //g_debug("Appointment timezone: %s", datetime.tzid);
+ //g_debug("Appointment timezone: %s", icaltimezone_get_tzid(appointment_zone)); // These two should be the same
//g_debug("Calendar timezone: %s", ecal_timezone);
dbusmenu_menuitem_property_set (item, APPOINTMENT_MENUITEM_PROP_RIGHT, right);
- e_cal_component_free_datetime (&datetime);
+ //e_cal_component_free_datetime (&datetime);
- ad = 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
// 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);
+ ad = isodate_from_time_t(mktime(due));
cmd = g_strconcat("evolution calendar:///?startdate=", ad, NULL);
g_signal_connect (G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
G_CALLBACK (activate_cb), cmd);
g_debug("Command to Execute: %s", cmd);
-
- // FIXME This is now more difficult to get right with more sources, as we need to keep track
- // of which ecal or source goes with each ECalComponent :/
-
- //ESource *source = e_cal_get_source (ecal);
- //e_source_get_color (source, &source_color); api has been changed
- const gchar *color_spec = NULL; //e_source_peek_color_spec(source);
+
+ const gchar *color_spec = e_source_peek_color_spec(ci->source);
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) {
+ // Fixme causes segfault, but we have colours now yay!
GdkColor color;
- 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_color_parse (color_spec, &color);
+
+ cairo_surface_t *surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, width, height );
+ // Width keeps becoming zero!!
+ if (width == 0) width = 12;
+ if (height == 0) height = 12;
+ cairo_t *cr = cairo_create(surface);
gdk_cairo_set_source_color(cr, &color);
- cairo_fill(cr);
-
- 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);
+ cairo_paint(cr);
+ cairo_set_source_rgba(cr, 0,0,0,0.5);
+ cairo_set_line_width(cr, 1);
+ cairo_rectangle (cr, 0.5, 0.5, width-1, height-1);
+ cairo_stroke(cr);
+ // Convert to pixbuf, in gtk3 this is done with gdk_pixbuf_get_from_surface
+ cairo_content_t content = cairo_surface_get_content (surface) | CAIRO_CONTENT_COLOR;
+ // Width keeps becoming zero!!
+ if (width == 0) width = 12;
+ if (height == 0) height = 12;
+ GdkPixbuf *pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
+ !!(content & CAIRO_CONTENT_ALPHA),
+ 8, width, height);
+ if (pixbuf != NULL) {
+ gint sstride = cairo_image_surface_get_stride( surface );
+ gint dstride = gdk_pixbuf_get_rowstride (pixbuf);
+ guchar *spixels = cairo_image_surface_get_data( surface );
+ guchar *dpixels = gdk_pixbuf_get_pixels (pixbuf);
+
+ int x, y;
+ for (y = 0; y < height; y++) {
+ guint32 *src = (guint32 *) spixels;
+
+ for (x = 0; x < width; x++) {
+ guint alpha = src[x] >> 24;
+
+ if (alpha == 0) {
+ dpixels[x * 4 + 0] = 0;
+ dpixels[x * 4 + 1] = 0;
+ dpixels[x * 4 + 2] = 0;
+ } else {
+ dpixels[x * 4 + 0] = (((src[x] & 0xff0000) >> 16) * 255 + alpha / 2) / alpha;
+ dpixels[x * 4 + 1] = (((src[x] & 0x00ff00) >> 8) * 255 + alpha / 2) / alpha;
+ dpixels[x * 4 + 2] = (((src[x] & 0x0000ff) >> 0) * 255 + alpha / 2) / alpha;
+ }
+ dpixels[x * 4 + 3] = alpha;
+ }
+ spixels += sstride;
+ dpixels += dstride;
+ }
+
+ cairo_surface_destroy (surface);
+ cairo_destroy(cr);
- dbusmenu_menuitem_property_set_image (item, APPOINTMENT_MENUITEM_PROP_ICON, pixbuf);
+ dbusmenu_menuitem_property_set_image (item, APPOINTMENT_MENUITEM_PROP_ICON, pixbuf);
+ }
}
- dbusmenu_menuitem_child_add_position (root, item, 3+i);
+ dbusmenu_menuitem_child_add_position (root, item, 2+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++;
}
if (gerror != NULL) g_error_free(gerror);
- g_object_unref(allobjects);
+ for (l = sorted_comp_instances; l; l = l->next) {
+ const struct comp_instance *ci = l->data;
+ g_object_unref(ci->comp);
+ g_list_free(sorted_comp_instances);
+ }
+
+ updating_appointments = FALSE;
g_debug("End of objects");
return TRUE;
}
@@ -756,6 +894,8 @@ build_menus (DbusmenuMenuitem * root)
check_timezone_sync();
g_signal_connect (conf, "changed::" SETTINGS_SHOW_LOCATIONS_S, G_CALLBACK (show_locations_changed), NULL);
+ g_signal_connect (conf, "changed::" SETTINGS_LOCATIONS_S, G_CALLBACK (show_locations_changed), NULL);
+ g_signal_connect (conf, "changed::" SETTINGS_SHOW_EVENTS_S, G_CALLBACK (show_events_changed), NULL);
DbusmenuMenuitem * separator = dbusmenu_menuitem_new();
dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);