diff options
Diffstat (limited to 'src/datetime-service.c')
-rw-r--r-- | src/datetime-service.c | 446 |
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); |