evolution-3.6.4/calendar/gui/tag-calendar.c

No issues found

  1 /*
  2  *
  3  * Evolution calendar - Utilities for tagging ECalendar widgets
  4  *
  5  * This program is free software; you can redistribute it and/or
  6  * modify it under the terms of the GNU Lesser General Public
  7  * License as published by the Free Software Foundation; either
  8  * version 2 of the License, or (at your option) version 3.
  9  *
 10  * This program is distributed in the hope that it will be useful,
 11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  * Lesser General Public License for more details.
 14  *
 15  * You should have received a copy of the GNU Lesser General Public
 16  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 17  *
 18  *
 19  * Authors:
 20  *		Damon Chaplin <damon@ximian.com>
 21  *      Federico Mena-Quintero <federico@ximian.com>
 22  *
 23  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 24  *
 25  */
 26 
 27 #ifdef HAVE_CONFIG_H
 28 #include <config.h>
 29 #endif
 30 
 31 #include "shell/e-shell.h"
 32 #include "shell/e-shell-settings.h"
 33 #include "calendar-config.h"
 34 #include "tag-calendar.h"
 35 
 36 struct calendar_tag_closure {
 37 	ECalendarItem *calitem;
 38 	icaltimezone *zone;
 39 	time_t start_time;
 40 	time_t end_time;
 41 
 42 	gboolean skip_transparent_events;
 43 	gboolean recur_events_italic;
 44 };
 45 
 46 /* Clears all the tags in a calendar and fills a closure structure with the
 47  * necessary information for iterating over occurrences.  Returns FALSE if
 48  * the calendar has no dates shown.  */
 49 static gboolean
 50 prepare_tag (ECalendar *ecal,
 51              struct calendar_tag_closure *closure,
 52              icaltimezone *zone,
 53              gboolean clear_first)
 54 {
 55 	gint start_year, start_month, start_day;
 56 	gint end_year, end_month, end_day;
 57 	struct icaltimetype start_tt = icaltime_null_time ();
 58 	struct icaltimetype end_tt = icaltime_null_time ();
 59 
 60 	if (clear_first)
 61 		e_calendar_item_clear_marks (ecal->calitem);
 62 
 63 	if (!e_calendar_item_get_date_range (
 64 		ecal->calitem,
 65 		&start_year, &start_month, &start_day,
 66 		&end_year, &end_month, &end_day))
 67 		return FALSE;
 68 
 69 	start_tt.year = start_year;
 70 	start_tt.month = start_month + 1;
 71 	start_tt.day = start_day;
 72 
 73 	end_tt.year = end_year;
 74 	end_tt.month = end_month + 1;
 75 	end_tt.day = end_day;
 76 
 77 	icaltime_adjust (&end_tt, 1, 0, 0, 0);
 78 
 79 	closure->calitem = ecal->calitem;
 80 
 81 	if (zone != NULL)
 82 		closure->zone = zone;
 83 	else
 84 		closure->zone = calendar_config_get_icaltimezone ();
 85 
 86 	closure->start_time =
 87 		icaltime_as_timet_with_zone (start_tt, closure->zone);
 88 	closure->end_time =
 89 		icaltime_as_timet_with_zone (end_tt, closure->zone);
 90 
 91 	return TRUE;
 92 }
 93 
 94 /* Marks the specified range in an ECalendar;
 95  * called from e_cal_generate_instances() */
 96 static gboolean
 97 tag_calendar_cb (ECalComponent *comp,
 98                  time_t istart,
 99                  time_t iend,
100                  struct calendar_tag_closure *closure)
101 {
102 	struct icaltimetype start_tt, end_tt;
103 	ECalComponentTransparency transparency;
104 	guint8 style = 0;
105 
106 	/* If we are skipping TRANSPARENT events, return if the event is
107 	 * transparent. */
108 	e_cal_component_get_transparency (comp, &transparency);
109 	if (transparency == E_CAL_COMPONENT_TRANSP_TRANSPARENT) {
110 		if (closure->skip_transparent_events)
111 			return TRUE;
112 
113 		style = E_CALENDAR_ITEM_MARK_ITALIC;
114 	} else if (closure->recur_events_italic && e_cal_component_is_instance (comp)) {
115 		style = E_CALENDAR_ITEM_MARK_ITALIC;
116 	} else {
117 		style = E_CALENDAR_ITEM_MARK_BOLD;
118 	}
119 
120 	start_tt = icaltime_from_timet_with_zone (istart, FALSE, closure->zone);
121 	end_tt = icaltime_from_timet_with_zone (iend - 1, FALSE, closure->zone);
122 
123 	e_calendar_item_mark_days (
124 		closure->calitem,
125 		start_tt.year, start_tt.month - 1, start_tt.day,
126 		end_tt.year, end_tt.month - 1, end_tt.day,
127 		style, TRUE);
128 
129 	return TRUE;
130 }
131 
132 static gboolean
133 get_recur_events_italic (void)
134 {
135 	EShell *shell;
136 	EShellSettings *shell_settings;
137 
138 	shell = e_shell_get_default ();
139 	shell_settings = e_shell_get_shell_settings (shell);
140 
141 	return e_shell_settings_get_boolean (
142 		shell_settings, "cal-recur-events-italic");
143 }
144 
145 /**
146  * tag_calendar_by_client:
147  * @ecal: Calendar widget to tag.
148  * @client: A calendar client object.
149  * @cancellable: A #GCancellable; can be %NULL
150  *
151  * Tags an #ECalendar widget with the events that occur in its current time
152  * range.  The occurrences are extracted from the specified calendar @client.
153  **/
154 void
155 tag_calendar_by_client (ECalendar *ecal,
156                         ECalClient *client,
157                         GCancellable *cancellable)
158 {
159 	struct calendar_tag_closure *closure;
160 
161 	g_return_if_fail (E_IS_CALENDAR (ecal));
162 	g_return_if_fail (E_IS_CAL_CLIENT (client));
163 
164 	/* If the ECalendar isn't visible, we just return. */
165 	if (!gtk_widget_get_visible (GTK_WIDGET (ecal)))
166 		return;
167 
168 	if (!e_client_is_opened (E_CLIENT (client)))
169 		return;
170 
171 	closure = g_new0 (struct calendar_tag_closure, 1);
172 
173 	if (!prepare_tag (ecal, closure, NULL, TRUE)) {
174 		g_free (closure);
175 		return;
176 	}
177 
178 	closure->skip_transparent_events = TRUE;
179 	closure->recur_events_italic = get_recur_events_italic ();
180 
181 	e_cal_client_generate_instances (
182 		client, closure->start_time, closure->end_time, cancellable,
183 		(ECalRecurInstanceFn) tag_calendar_cb,
184 		closure, (GDestroyNotify) g_free);
185 }
186 
187 /* Resolves TZIDs for the recurrence generator, for when the comp is not on
188  * the server. We need to try to use builtin timezones first, as they may not
189  * be added to the server yet. */
190 static icaltimezone *
191 resolve_tzid_cb (const gchar *tzid,
192                  ECalClient *client)
193 {
194 	icaltimezone *zone = NULL;
195 
196 	/* Try to find the builtin timezone first. */
197 	zone = icaltimezone_get_builtin_timezone_from_tzid (tzid);
198 
199 	if (!zone && tzid) {
200 		/* FIXME: Handle errors. */
201 		GError *error = NULL;
202 
203 		e_cal_client_get_timezone_sync (
204 			client, tzid, &zone, NULL, &error);
205 
206 		if (error != NULL) {
207 			g_warning (
208 				"%s: Failed to get timezone '%s': %s",
209 				G_STRFUNC, tzid, error->message);
210 			g_error_free (error);
211 		}
212 	}
213 
214 	return zone;
215 }
216 
217 /**
218  * tag_calendar_by_comp:
219  * @ecal: Calendar widget to tag.
220  * @comp: A calendar component object.
221  * @clear_first: Whether the #ECalendar should be cleared of any marks first.
222  *
223  * Tags an #ECalendar widget with any occurrences of a specific calendar
224  * component that occur within the calendar's current time range.
225  * Note that TRANSPARENT events are also tagged here.
226  *
227  * If comp_is_on_server is FALSE, it will try to resolve TZIDs using builtin
228  * timezones first, before querying the server, since the timezones may not
229  * have been added to the calendar on the server yet.
230  **/
231 void
232 tag_calendar_by_comp (ECalendar *ecal,
233                       ECalComponent *comp,
234                       ECalClient *client,
235                       icaltimezone *display_zone,
236                       gboolean clear_first,
237                       gboolean comp_is_on_server,
238                       gboolean can_recur_events_italic,
239                       GCancellable *cancellable)
240 {
241 	struct calendar_tag_closure closure;
242 
243 	g_return_if_fail (E_IS_CALENDAR (ecal));
244 	g_return_if_fail (E_IS_CAL_COMPONENT (comp));
245 
246 	/* If the ECalendar isn't visible, we just return. */
247 	if (!gtk_widget_get_visible (GTK_WIDGET (ecal)))
248 		return;
249 
250 	if (!prepare_tag (ecal, &closure, display_zone, clear_first))
251 		return;
252 
253 	closure.skip_transparent_events = FALSE;
254 	closure.recur_events_italic =
255 		can_recur_events_italic && get_recur_events_italic ();
256 
257 	if (comp_is_on_server) {
258 		struct calendar_tag_closure *alloced_closure;
259 
260 		alloced_closure = g_new0 (struct calendar_tag_closure, 1);
261 
262 		*alloced_closure = closure;
263 
264 		e_cal_client_generate_instances_for_object (
265 			client, e_cal_component_get_icalcomponent (comp),
266 			closure.start_time, closure.end_time, cancellable,
267 			(ECalRecurInstanceFn) tag_calendar_cb,
268 			alloced_closure, (GDestroyNotify) g_free);
269 	} else
270 		e_cal_recur_generate_instances (
271 			comp, closure.start_time, closure.end_time,
272 			(ECalRecurInstanceFn) tag_calendar_cb,
273 			&closure,
274 			(ECalRecurResolveTimezoneFn) resolve_tzid_cb,
275 			client, closure.zone);
276 }