diff options
Diffstat (limited to 'calendar/gui/e-meeting-time-sel.c')
-rw-r--r-- | calendar/gui/e-meeting-time-sel.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/calendar/gui/e-meeting-time-sel.c b/calendar/gui/e-meeting-time-sel.c index 69d9e27ffb..3747a7be1d 100644 --- a/calendar/gui/e-meeting-time-sel.c +++ b/calendar/gui/e-meeting-time-sel.c @@ -196,6 +196,12 @@ static void e_meeting_time_selector_update_end_date_edit (EMeetingTimeSelector * static void e_meeting_time_selector_ensure_meeting_time_shown (EMeetingTimeSelector *mts); static void e_meeting_time_selector_update_dates_shown (EMeetingTimeSelector *mts); static gboolean e_meeting_time_selector_on_canvas_scroll_event (GtkWidget *widget, GdkEventScroll *event, EMeetingTimeSelector *mts); +static gboolean e_meeting_time_selector_on_canvas_query_tooltip (GtkWidget *widget, + gint x, + gint y, + gboolean keyboard_mode, + GtkTooltip *tooltip, + gpointer user_data); static void row_inserted_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data); static void row_changed_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data); @@ -522,6 +528,15 @@ e_meeting_time_selector_construct (EMeetingTimeSelector *mts, g_signal_connect ( mts->display_main, "scroll-event", G_CALLBACK (e_meeting_time_selector_on_canvas_scroll_event), mts); + /* used for displaying extended free/busy (XFB) display when hovering + * over a busy period which carries XFB information */ + g_signal_connect (mts->display_main, + "query-tooltip", + G_CALLBACK (e_meeting_time_selector_on_canvas_query_tooltip), + mts); + g_object_set (G_OBJECT (mts->display_main), + "has-tooltip", TRUE, + NULL); scrollable = GTK_SCROLLABLE (mts->display_main); @@ -2660,6 +2675,135 @@ e_meeting_time_selector_on_canvas_scroll_event (GtkWidget *widget, return return_val; } +/* Sets a tooltip for the busy periods canvas. If the mouse pointer + * hovers over a busy period for which extended free/busy (XFB) data + * could be extracted from the vfreebusy calendar object, the tooltip + * will be shown (currently displays the summary and the location of + * for the busy period, if available). See EMeetingXfbData for a reference. + * + */ +static gboolean +e_meeting_time_selector_on_canvas_query_tooltip (GtkWidget *widget, + gint x, + gint y, + gboolean keyboard_mode, + GtkTooltip *tooltip, + gpointer user_data) +{ + EMeetingTimeSelector *mts = NULL; + EMeetingAttendee *attendee = NULL; + EMeetingFreeBusyPeriod *period = NULL; + EMeetingXfbData *xfb = NULL; + GtkScrollable *scrollable = NULL; + GtkAdjustment *adjustment = NULL; + const GArray *periods = NULL; + gint scroll_x = 0; + gint scroll_y = 0; + gint mouse_x = 0; + gint row = 0; + gint first_idx = 0; + gint ii = 0; + gchar *tt_text = NULL; + + g_return_val_if_fail (GNOME_IS_CANVAS (widget), FALSE); + g_return_val_if_fail (GTK_IS_TOOLTIP (tooltip), FALSE); + g_return_val_if_fail (E_IS_MEETING_TIME_SELECTOR (user_data), FALSE); + + mts = E_MEETING_TIME_SELECTOR (user_data); + + scrollable = GTK_SCROLLABLE (widget); + adjustment = gtk_scrollable_get_hadjustment (scrollable); + scroll_x = (gint) gtk_adjustment_get_value (adjustment); + adjustment = gtk_scrollable_get_vadjustment (scrollable); + scroll_y = (gint) gtk_adjustment_get_value (adjustment); + + /* calculate the attendee index (row) we're at */ + row = (scroll_y + y) / mts->row_height; + + /* no tooltip if we have no attendee in the row */ + if (row > e_meeting_store_count_actual_attendees (mts->model) - 1) + return FALSE; + + /* no tooltip if attendee has no calendar info */ + attendee = e_meeting_store_find_attendee_at_row (mts->model, row); + g_return_val_if_fail (E_IS_MEETING_ATTENDEE (attendee), FALSE); + if (!e_meeting_attendee_get_has_calendar_info (attendee)) + return FALSE; + + /* get the attendee's busy times array */ + periods = e_meeting_attendee_get_busy_periods (attendee); + g_return_val_if_fail (periods != NULL, FALSE); + g_return_val_if_fail (periods->len > 0, FALSE); + + /* no tooltip if no busy period reaches into the current canvas area */ + first_idx = e_meeting_attendee_find_first_busy_period (attendee, + &(mts->first_date_shown)); + if (first_idx < 0) + return FALSE; + + /* calculate the mouse tip x position in the canvas area */ + mouse_x = x + scroll_x; + + /* find out whether mouse_x lies inside a busy + * period (we start with the index of the first + * one reaching into the current canvas area) + */ + for (ii = first_idx; ii < periods->len; ii++) { + EMeetingFreeBusyPeriod *p = NULL; + gint sx = 0; + gint ex = 0; + + p = &(g_array_index (periods, + EMeetingFreeBusyPeriod, + ii)); + /* meeting start time x position */ + sx = e_meeting_time_selector_calculate_time_position (mts, + &(p->start)); + /* meeting end time x position */ + ex = e_meeting_time_selector_calculate_time_position (mts, + &(p->end)); + if ((mouse_x >= sx) && (mouse_x <= ex)) { + /* found busy period the mouse tip is over */ + period = p; + break; + } + } + + /* no tooltip if we did not find a busy period under + * the mouse pointer + */ + if (period == NULL) + return FALSE; + + /* get the extended free/busy data + * (no tooltip if none available) + */ + xfb = &(period->xfb); + if ((xfb->summary == NULL) && (xfb->location == NULL)) + return FALSE; + + /* Create the tooltip text. The data sent by the server will + * have been validated for UTF-8 conformance (and possibly + * forced into) as well as length-limited by a call to the + * e_meeting_xfb_utf8_string_new_from_ical() function in + * process_free_busy_comp_get_xfb() (e-meeting-store.c) + */ + if (xfb->summary && xfb->location) + tt_text = g_strdup_printf (_("Summary: %s\nLocation: %s"), xfb->summary, xfb->location); + else if (xfb->summary) + tt_text = g_strdup_printf (_("Summary: %s"), xfb->summary); + else if (xfb->location) + tt_text = g_strdup_printf (_("Location: %s"), xfb->location); + else + g_return_val_if_reached (FALSE); + + /* set XFB information as tooltip text */ + gtk_tooltip_set_text (tooltip, tt_text); + g_free (tt_text); + + return TRUE; +} + /* This updates the canvas scroll regions according to the number of attendees. * If the total height needed is less than the height of the canvas, we must * use the height of the canvas, or it causes problems. */ |