/* (has-recurrences?)
 *
 * A boolean value for components that have/dont have recurrences.
 *
 * Returns: a boolean indicating whether the component has recurrences or not.
 */
static ESExpResult *
func_has_recurrences (ESExp *esexp,
                      gint argc,
                      ESExpResult **argv,
                      gpointer data)
{
	SearchContext *ctx = data;
	ESExpResult *result;

	/* Check argument types */

	if (argc != 0) {
		e_sexp_fatal_error (
			esexp, _("\"%s\" expects no arguments"),
			"has-recurrences");
		return NULL;
	}

	result = e_sexp_result_new (esexp, ESEXP_RES_BOOL);
	result->value.boolean =
		e_cal_component_has_recurrences (ctx->comp) ||
		e_cal_component_is_instance (ctx->comp);

	return result;
}
Пример #2
0
void
dates_edit_cb (GtkWidget *source, DatesData *d)
{
    if (d->read_only) return;
    /* TODO: Handle recurring events */
    if (e_cal_component_has_recurrences (d->comp)) return;
    dates_fill_details_dialog (d->view, d);
	dates_platform_details_dlg (d, TRUE);
}
Пример #3
0
/**
 * e_cal_util_get_component_occur_times:
 * @comp: an #ECalComponent
 * @start: (out): Location to store the start time
 * @end: (out): Location to store the end time
 * @tz_cb: (closure tz_cb_data) (scope call): The #ECalRecurResolveTimezoneFn to call
 * @tz_cb_data: (closure): User data to be passed to the @tz_cb callback
 * @default_timezone: The default timezone
 * @kind: the type of component, indicated with an icalcomponent_kind
 *
 * Find out when the component starts and stops, being careful about
 * recurrences.
 *
 * Since: 2.32
 **/
void
e_cal_util_get_component_occur_times (ECalComponent *comp,
                                      time_t *start,
                                      time_t *end,
                                      ECalRecurResolveTimezoneFn tz_cb,
                                      gpointer tz_cb_data,
                                      const icaltimezone *default_timezone,
                                      icalcomponent_kind kind)
{
	struct icalrecurrencetype ir;
	ECalComponentDateTime dt_start, dt_end;

	g_return_if_fail (comp != NULL);
	g_return_if_fail (start != NULL);
	g_return_if_fail (end != NULL);

	e_cal_recur_ensure_end_dates (comp, FALSE, tz_cb, tz_cb_data);

	/* Get dtstart of the component and convert it to UTC */
	e_cal_component_get_dtstart (comp, &dt_start);

	if ((*start = componenttime_to_utc_timet (&dt_start, tz_cb, tz_cb_data, default_timezone)) == -1)
		*start = _TIME_MIN;

	e_cal_component_free_datetime (&dt_start);

	/* find out end date of component */
	*end = _TIME_MAX;

	if (kind == ICAL_VTODO_COMPONENT) {
		/* max from COMPLETED and DUE properties */
		struct icaltimetype *tt = NULL;
		time_t completed_time = -1, due_time = -1, max_time;
		ECalComponentDateTime dt_due;

		e_cal_component_get_completed (comp, &tt);
		if (tt) {
			/* COMPLETED must be in UTC. */
			completed_time = icaltime_as_timet_with_zone (
				*tt, icaltimezone_get_utc_timezone ());
			e_cal_component_free_icaltimetype (tt);
		}

		e_cal_component_get_due (comp, &dt_due);
		if (dt_due.value != NULL)
			due_time = componenttime_to_utc_timet (
				&dt_due, tz_cb, tz_cb_data,
				default_timezone);

		e_cal_component_free_datetime (&dt_due);

		max_time = MAX (completed_time, due_time);

		if (max_time != -1)
			*end = max_time;

	} else {
		/* ALARMS, EVENTS: DTEND and reccurences */

		if (e_cal_component_has_recurrences (comp)) {
			GSList *rrules = NULL;
			GSList *exrules = NULL;
			GSList *elem;
			GSList *rdates = NULL;

			/* Do the RRULEs, EXRULEs and RDATEs*/
			e_cal_component_get_rrule_property_list (comp, &rrules);
			e_cal_component_get_exrule_property_list (comp, &exrules);
			e_cal_component_get_rdate_list (comp, &rdates);

			for (elem = rrules; elem; elem = elem->next) {
				time_t rule_end;
				icaltimezone *utc_zone;
				icalproperty *prop = elem->data;
				ir = icalproperty_get_rrule (prop);

				utc_zone = icaltimezone_get_utc_timezone ();
				rule_end = e_cal_recur_obtain_enddate (
					&ir, prop, utc_zone, TRUE);

				if (rule_end == -1) /* repeats forever */
					*end = _TIME_MAX;
				else if (rule_end > *end) /* new maximum */
					*end = rule_end;
			}

			/* Do the EXRULEs. */
			for (elem = exrules; elem; elem = elem->next) {
				icalproperty *prop = elem->data;
				time_t rule_end;
				icaltimezone *utc_zone;
				ir = icalproperty_get_exrule (prop);

				utc_zone = icaltimezone_get_utc_timezone ();
				rule_end = e_cal_recur_obtain_enddate (
					&ir, prop, utc_zone, TRUE);

				if (rule_end == -1) /* repeats forever */
					*end = _TIME_MAX;
				else if (rule_end > *end)
					*end = rule_end;
			}

			/* Do the RDATEs */
			for (elem = rdates; elem; elem = elem->next) {
				ECalComponentPeriod *p = elem->data;
				time_t rdate_end = _TIME_MAX;

				/* FIXME: We currently assume RDATEs are in the same timezone
				 * as DTSTART. We should get the RDATE timezone and convert
				 * to the DTSTART timezone first. */

				/* Check if the end date or duration is set, libical seems to set
				 * second to -1 to denote an unset time */
				if (p->type != E_CAL_COMPONENT_PERIOD_DATETIME || p->u.end.second != -1)
					rdate_end = icaltime_as_timet (icaltime_add (p->start, p->u.duration));
				else
					rdate_end = icaltime_as_timet (p->u.end);

				if (rdate_end == -1) /* repeats forever */
					*end = _TIME_MAX;
				else if (rdate_end > *end)
					*end = rdate_end;
			}

			e_cal_component_free_period_list (rdates);
		}

		/* Get dtend of the component and convert it to UTC */
		e_cal_component_get_dtend (comp, &dt_end);

		if (dt_end.value) {
			time_t dtend_time;

			dtend_time = componenttime_to_utc_timet (
				&dt_end, tz_cb, tz_cb_data, default_timezone);

			if (dtend_time == -1 || (dtend_time > *end))
				*end = dtend_time;
		}

		e_cal_component_free_datetime (&dt_end);
	}
}
Пример #4
0
static void
process_meeting (ECalendarView *cal_view, icalparameter_partstat status)
{
	GList *selected;
	icalcomponent *clone;

	selected = e_calendar_view_get_selected_events (cal_view);
	if (selected) {
		ECalendarViewEvent *event = (ECalendarViewEvent *) selected->data;
		ECalComponent *comp = e_cal_component_new ();
		ReceiveData *r_data = g_new0 (ReceiveData, 1);
		gboolean recurring = FALSE;
		GThread *thread = NULL;
		GError *error = NULL;
		char *address = NULL;

		e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (event->comp_data->icalcomp));
		address = itip_get_comp_attendee (comp, event->comp_data->client);

		if (e_cal_component_has_recurrences (comp) || e_cal_component_is_instance (comp))
			recurring = TRUE;

		/* Free comp */
		g_object_unref (comp);
		comp = NULL;

		clone = icalcomponent_new_clone (event->comp_data->icalcomp);
		change_status (clone, address, status);

		r_data->ecal = g_object_ref (event->comp_data->client);
		r_data->icalcomp = clone;

		if (recurring) {
			gint response;
			const char *arg;

			if (status == ICAL_PARTSTAT_ACCEPTED || status == ICAL_PARTSTAT_TENTATIVE)
				arg = "accept";
			else
				arg = "decline";

			response = e_error_run (NULL, "org.gnome.evolution.mail_shared_folder:recurrence", arg, NULL);
			if (response == GTK_RESPONSE_YES) {
				icalproperty *prop;
				const char *uid = icalcomponent_get_uid (r_data->icalcomp);

				prop = icalproperty_new_x ("All");
				icalproperty_set_x_name (prop, "X-GW-RECUR-INSTANCES-MOD-TYPE");
				icalcomponent_add_property (r_data->icalcomp, prop);

				prop = icalproperty_new_x (uid);
				icalproperty_set_x_name (prop, "X-GW-RECURRENCE-KEY");
				icalcomponent_add_property (r_data->icalcomp, prop);

			} else if (response == GTK_RESPONSE_CANCEL) {
				finalize_receive_data (r_data);
				return;
			}
		}

		thread = g_thread_create ((GThreadFunc) receive_objects, r_data , FALSE, &error);
		if (!thread) {
			g_warning (G_STRLOC ": %s", error->message);
			g_error_free (error);
		}
	}
}
Пример #5
0
static void
week_view_event_item_draw_icons (EWeekViewEventItem *event_item,
                                 cairo_t *cr,
                                 gint icon_x,
                                 gint icon_y,
                                 gint x2,
                                 gboolean right_align,
                                 cairo_region_t *draw_region)
{
	EWeekView *week_view;
	EWeekViewEvent *event;
	ECalComponent *comp;
	GnomeCanvas *canvas;
	GtkWidget *parent;
	gint num_icons = 0, icon_x_inc;
	gboolean draw_reminder_icon = FALSE, draw_recurrence_icon = FALSE;
	gboolean draw_timezone_icon = FALSE, draw_attach_icon = FALSE;
	gboolean draw_meeting_icon = FALSE;
	GSList *categories_pixbufs = NULL, *pixbufs;

	canvas = GNOME_CANVAS_ITEM (event_item)->canvas;
	parent = gtk_widget_get_parent (GTK_WIDGET (canvas));
	week_view = E_WEEK_VIEW (parent);

	if (!is_array_index_in_bounds (week_view->events, event_item->priv->event_num))
		return;

	event = &g_array_index (week_view->events, EWeekViewEvent,
				event_item->priv->event_num);

	if (!is_comp_data_valid (event))
		return;

	comp = e_cal_component_new ();
	e_cal_component_set_icalcomponent (
		comp, icalcomponent_new_clone (event->comp_data->icalcomp));

	if (e_cal_component_has_alarms (comp)) {
		draw_reminder_icon = TRUE;
		num_icons++;
	}

	if (e_cal_component_has_recurrences (comp) || e_cal_component_is_instance (comp)) {
		draw_recurrence_icon = TRUE;
		num_icons++;
	}

	if (e_cal_component_has_attachments (comp)) {
		draw_attach_icon = TRUE;
		num_icons++;
	}

	if (e_cal_component_has_attendees (comp)) {
		draw_meeting_icon = TRUE;
		num_icons++;
	}

	if (event->different_timezone) {
		draw_timezone_icon = TRUE;
		num_icons++;
	}

	num_icons += cal_comp_util_get_n_icons (comp, &categories_pixbufs);

	icon_x_inc = E_WEEK_VIEW_ICON_WIDTH + E_WEEK_VIEW_ICON_X_PAD;

	if (right_align)
		icon_x -= icon_x_inc * num_icons;

	#define draw_pixbuf(pf)							\
		if (can_draw_in_region (draw_region, icon_x, icon_y,		\
		    E_WEEK_VIEW_ICON_WIDTH, E_WEEK_VIEW_ICON_HEIGHT)) {		\
			cairo_save (cr);					\
			gdk_cairo_set_source_pixbuf (cr, pf, icon_x, icon_y);	\
			cairo_paint (cr);					\
			cairo_restore (cr);					\
		}								\
										\
		icon_x += icon_x_inc;

	if (draw_reminder_icon && icon_x + E_WEEK_VIEW_ICON_WIDTH <= x2) {
		draw_pixbuf (week_view->reminder_icon);
	}

	if (draw_attach_icon && icon_x + E_WEEK_VIEW_ICON_WIDTH <= x2) {
		draw_pixbuf (week_view->attach_icon);
	}

	if (draw_recurrence_icon && icon_x + E_WEEK_VIEW_ICON_WIDTH <= x2) {
		draw_pixbuf (week_view->recurrence_icon);
	}

	if (draw_timezone_icon && icon_x + E_WEEK_VIEW_ICON_WIDTH <= x2) {
		draw_pixbuf (week_view->timezone_icon);
	}

	if (draw_meeting_icon && icon_x + E_WEEK_VIEW_ICON_WIDTH <= x2) {
		draw_pixbuf (week_view->meeting_icon);
	}

	/* draw categories icons */
	for (pixbufs = categories_pixbufs;
	     pixbufs;
	     pixbufs = pixbufs->next) {
		GdkPixbuf *pixbuf = pixbufs->data;

		draw_pixbuf (pixbuf);
	}

	#undef draw_pixbuf

	g_slist_foreach (categories_pixbufs, (GFunc) g_object_unref, NULL);
	g_slist_free (categories_pixbufs);

	g_object_unref (comp);
}
static void
set_itip_view (SunOneInvitationList *list, int row)
{
	SunOneInvitationListPrivate *priv = list->priv;
	ECalComponent *comp;
	ECalComponentText text;
	const char *string;
	ECalComponentDateTime datetime;
	GString *gstring = NULL;
	GSList *description_list, *l;

	SunOneItipView *itip_view;
	ECalComponentOrganizer organizer;

	if (row == -1) {
		if (GTK_WIDGET_VISIBLE (priv->control))
			gtk_widget_hide (priv->control);
		return;
	}
	comp = sunone_invitation_list_model_get_comp (priv->model, row);
	if (!comp)
		return;

	itip_view  = (SunOneItipView *)priv->control;

	sunone_itip_view_set_mode (itip_view, SUNONE_ITIP_VIEW_MODE_REQUEST);
	sunone_itip_view_set_item_type (itip_view, E_CAL_SOURCE_TYPE_EVENT);

	e_cal_component_get_organizer (comp, &organizer);
	sunone_itip_view_set_organizer (itip_view, organizer.cn ? organizer.cn : itip_strip_mailto (organizer.value));
	sunone_itip_view_set_sentby (itip_view, organizer.sentby);

	e_cal_component_get_summary (comp, &text);
	sunone_itip_view_set_summary (itip_view, text.value ? text.value : _("None"));

	e_cal_component_get_location (comp, &string);
	sunone_itip_view_set_location (itip_view, string);

	e_cal_component_get_description_list (comp, &description_list);
	for (l = description_list; l; l = l->next) {
		ECalComponentText *text = l->data;
		
		if (!gstring && text->value)
			gstring = g_string_new (text->value);
		else if (text->value)
			g_string_append_printf (gstring, "\n\n%s", text->value);
	}
	e_cal_component_free_text_list (description_list);

	if (gstring) {
		sunone_itip_view_set_description (itip_view, gstring->str);
		g_string_free (gstring, TRUE);
	} else
		sunone_itip_view_set_description (itip_view, NULL);
	
	
	e_cal_component_get_dtstart (comp, &datetime);
	if (datetime.value) {
		struct tm start_tm;
		
		start_tm = icaltimetype_to_tm_with_zone (datetime.value, icaltimezone_get_utc_timezone (), priv->model->zone);

		sunone_itip_view_set_start (itip_view, &start_tm);
	}
	e_cal_component_free_datetime (&datetime);

	e_cal_component_get_dtend (comp, &datetime);
	if (datetime.value) {
		struct tm end_tm;

		end_tm = icaltimetype_to_tm_with_zone (datetime.value, icaltimezone_get_utc_timezone (), priv->model->zone);
		
		sunone_itip_view_set_end (itip_view, &end_tm);
	}
	e_cal_component_free_datetime (&datetime);

	/* Recurrence info */
	sunone_itip_view_clear_upper_info_items (itip_view);
	if (e_cal_component_has_recurrences (comp)) {
		sunone_itip_view_add_upper_info_item (itip_view, SUNONE_ITIP_VIEW_INFO_ITEM_TYPE_INFO, "This meeting recurs");
	}

	sunone_itip_view_set_status (itip_view, NULL);
	sunone_itip_view_set_comment (itip_view, NULL);
	sunone_itip_view_set_show_rsvp (itip_view, FALSE);

	if (!GTK_WIDGET_VISIBLE (priv->control))
		gtk_widget_show (priv->control);
}
Пример #7
0
static void
preview_comp (EWebViewPreview *preview,
              ECalComponent *comp)
{
	ECalComponentText text = { 0 };
	ECalComponentDateTime dt;
	ECalComponentClassification classif;
	const gchar *str;
	gchar *tmp;
	gint percent;
	gboolean have;
	GHashTable *timezones;
	icaltimezone *users_zone;
	GSList *slist, *l;

	g_return_if_fail (preview != NULL);
	g_return_if_fail (comp != NULL);

	timezones = g_object_get_data (G_OBJECT (preview), "iCalImp-timezones");
	users_zone = g_object_get_data (G_OBJECT (preview), "iCalImp-userszone");

	str = NULL;
	switch (e_cal_component_get_vtype (comp)) {
	case E_CAL_COMPONENT_EVENT:
		str = e_cal_component_has_attendees (comp) ? C_("iCalImp", "Meeting") : C_("iCalImp", "Event");
		break;
	case E_CAL_COMPONENT_TODO:
		str = C_("iCalImp", "Task");
		break;
	case E_CAL_COMPONENT_JOURNAL:
		str = C_("iCalImp", "Memo");
		break;
	default:
		str = "??? Other ???";
		break;
	}

	have = FALSE;
	if (e_cal_component_has_recurrences (comp)) {
		e_web_view_preview_add_section (preview, have ? NULL : str, C_("iCalImp", "has recurrences"));
		have = TRUE;
	}

	if (e_cal_component_is_instance (comp)) {
		e_web_view_preview_add_section (preview, have ? NULL : str, C_("iCalImp", "is an instance"));
		have = TRUE;
	}

	if (e_cal_component_has_alarms (comp)) {
		e_web_view_preview_add_section (preview, have ? NULL : str, C_("iCalImp", "has reminders"));
		have = TRUE;
	}

	if (e_cal_component_has_attachments (comp)) {
		e_web_view_preview_add_section (preview, have ? NULL : str, C_("iCalImp", "has attachments"));
		have = TRUE;
	}

	if (!have) {
		e_web_view_preview_add_section (preview, str, "");
	}

	str = NULL;
	classif = E_CAL_COMPONENT_CLASS_NONE;
	e_cal_component_get_classification (comp, &classif);
	if (classif == E_CAL_COMPONENT_CLASS_PUBLIC) {
		/* Translators: Appointment's classification */
		str = C_("iCalImp", "Public");
	} else if (classif == E_CAL_COMPONENT_CLASS_PRIVATE) {
		/* Translators: Appointment's classification */
		str = C_("iCalImp", "Private");
	} else if (classif == E_CAL_COMPONENT_CLASS_CONFIDENTIAL) {
		/* Translators: Appointment's classification */
		str = C_("iCalImp", "Confidential");
	}
	if (str)
		/* Translators: Appointment's classification section name */
		e_web_view_preview_add_section (preview, C_("iCalImp", "Classification"), str);

	e_cal_component_get_summary (comp, &text);
	if ((text.value && *text.value) || (text.altrep && *text.altrep))
		/* Translators: Appointment's summary */
		e_web_view_preview_add_section (preview, C_("iCalImp", "Summary"), (text.value && *text.value) ? text.value : text.altrep);

	str = NULL;
	e_cal_component_get_location (comp, &str);
	if (str && *str)
		/* Translators: Appointment's location */
		e_web_view_preview_add_section (preview, C_("iCalImp", "Location"), str);

	dt.value = NULL;
	e_cal_component_get_dtstart (comp, &dt);
	if (dt.value) {
		tmp = format_dt (&dt, timezones, users_zone);
		if (tmp)
			/* Translators: Appointment's start time */
			e_web_view_preview_add_section (preview, C_("iCalImp", "Start"), tmp);
		g_free (tmp);
	}
	e_cal_component_free_datetime (&dt);

	dt.value = NULL;
	e_cal_component_get_due (comp, &dt);
	if (dt.value) {
		tmp = format_dt (&dt, timezones, users_zone);
		if (tmp)
			/* Translators: 'Due' like the time due a task should be finished */
			e_web_view_preview_add_section (preview, C_("iCalImp", "Due"), tmp);
		g_free (tmp);
	} else {
		e_cal_component_free_datetime (&dt);

		dt.value = NULL;
		e_cal_component_get_dtend (comp, &dt);
		if (dt.value) {
			tmp = format_dt (&dt, timezones, users_zone);

			if (tmp)
				/* Translators: Appointment's end time */
				e_web_view_preview_add_section (preview, C_("iCalImp", "End"), tmp);
			g_free (tmp);
		}
	}
	e_cal_component_free_datetime (&dt);

	str = NULL;
	e_cal_component_get_categories (comp, &str);
	if (str && *str)
		/* Translators: Appointment's categories */
		e_web_view_preview_add_section (preview, C_("iCalImp", "Categories"), str);

	percent = e_cal_component_get_percent_as_int (comp);
	if (percent >= 0) {
		tmp = NULL;
		if (percent == 100) {
			icaltimetype *completed = NULL;

			e_cal_component_get_completed (comp, &completed);

			if (completed) {
				dt.tzid = "UTC";
				dt.value = completed;

				tmp = format_dt (&dt, timezones, users_zone);

				e_cal_component_free_icaltimetype (completed);
			}
		}

		if (!tmp)
			tmp = g_strdup_printf ("%d%%", percent);

		/* Translators: Appointment's complete value (either percentage, or a date/time of a completion) */
		e_web_view_preview_add_section (preview, C_("iCalImp", "Completed"), tmp);
		g_free (tmp);
	}

	str = NULL;
	e_cal_component_get_url (comp, &str);
	if (str && *str)
		/* Translators: Appointment's URL */
		e_web_view_preview_add_section (preview, C_("iCalImp", "URL"), str);

	if (e_cal_component_has_organizer (comp)) {
		ECalComponentOrganizer organizer = { 0 };

		e_cal_component_get_organizer (comp, &organizer);

		if (organizer.value && *organizer.value) {
			if (organizer.cn && *organizer.cn) {
				tmp = g_strconcat (organizer.cn, " <", strip_mailto (organizer.value), ">", NULL);
				/* Translators: Appointment's organizer */
				e_web_view_preview_add_section (preview, C_("iCalImp", "Organizer"), tmp);
				g_free (tmp);
			} else {
				e_web_view_preview_add_section (preview, C_("iCalImp", "Organizer"), strip_mailto (organizer.value));
			}
		}
	}

	if (e_cal_component_has_attendees (comp)) {
		GSList *attendees = NULL, *a;
		have = FALSE;

		e_cal_component_get_attendee_list (comp, &attendees);

		for (a = attendees; a; a = a->next) {
			ECalComponentAttendee *attnd = a->data;

			if (!attnd || !attnd->value || !*attnd->value)
				continue;

			if (attnd->cn && *attnd->cn) {
				tmp = g_strconcat (attnd->cn, " <", strip_mailto (attnd->value), ">", NULL);
				/* Translators: Appointment's attendees */
				e_web_view_preview_add_section (preview, have ? NULL : C_("iCalImp", "Attendees"), tmp);
				g_free (tmp);
			} else {
				e_web_view_preview_add_section (preview, have ? NULL : C_("iCalImp", "Attendees"), strip_mailto (attnd->value));
			}

			have = TRUE;
		}

		e_cal_component_free_attendee_list (attendees);
	}

	slist = NULL;
	e_cal_component_get_description_list (comp, &slist);
	for (l = slist; l; l = l->next) {
		ECalComponentText *txt = l->data;

		e_web_view_preview_add_section (preview, l != slist ? NULL : C_("iCalImp", "Description"), (txt && txt->value) ? txt->value : "");
	}

	e_cal_component_free_text_list (slist);
}