1 /*
2  * Evolution calendar - Data model for ETable
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11  * for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program; if not, see <http://www.gnu.org/licenses/>.
15  *
16  *
17  * Authors:
18  *		Rodrigo Moya <rodrigo@ximian.com>
19  *
20  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
21  *
22  */
23 
24 #include "evolution-config.h"
25 
26 #include <string.h>
27 #include <glib/gi18n.h>
28 #include "e-cal-model-calendar.h"
29 #include "e-cell-date-edit-text.h"
30 #include "itip-utils.h"
31 #include "misc.h"
32 #include "e-cal-dialogs.h"
33 
34 /* Forward Declarations */
35 static void	e_cal_model_calendar_table_model_init
36 					(ETableModelInterface *iface);
37 
38 static ETableModelInterface *table_model_parent_interface;
39 
G_DEFINE_TYPE_WITH_CODE(ECalModelCalendar,e_cal_model_calendar,E_TYPE_CAL_MODEL,G_IMPLEMENT_INTERFACE (E_TYPE_TABLE_MODEL,e_cal_model_calendar_table_model_init))40 G_DEFINE_TYPE_WITH_CODE (
41 	ECalModelCalendar,
42 	e_cal_model_calendar,
43 	E_TYPE_CAL_MODEL,
44 	G_IMPLEMENT_INTERFACE (
45 		E_TYPE_TABLE_MODEL,
46 		e_cal_model_calendar_table_model_init))
47 
48 static ECellDateEditValue *
49 get_dtend (ECalModelCalendar *model,
50            ECalModelComponent *comp_data)
51 {
52 	if (!comp_data->dtend) {
53 		comp_data->dtend = e_cal_model_util_get_datetime_value (E_CAL_MODEL (model), comp_data,
54 			I_CAL_DTEND_PROPERTY, i_cal_property_get_dtend);
55 	}
56 
57 	return e_cell_date_edit_value_copy (comp_data->dtend);
58 }
59 
60 static gpointer
get_location(ECalModelComponent * comp_data)61 get_location (ECalModelComponent *comp_data)
62 {
63 	ICalProperty *prop;
64 	const gchar *res = NULL;
65 
66 	prop = i_cal_component_get_first_property (comp_data->icalcomp, I_CAL_LOCATION_PROPERTY);
67 	if (prop) {
68 		res = i_cal_property_get_location (prop);
69 		g_clear_object (&prop);
70 	}
71 
72 	if (!res)
73 		res = "";
74 
75 	return (gpointer) res;
76 }
77 
78 static gpointer
get_transparency(ECalModelComponent * comp_data)79 get_transparency (ECalModelComponent *comp_data)
80 {
81 	ICalProperty *prop;
82 
83 	prop = i_cal_component_get_first_property (comp_data->icalcomp, I_CAL_TRANSP_PROPERTY);
84 	if (prop) {
85 		ICalPropertyTransp transp;
86 		const gchar *res = NULL;
87 
88 		transp = i_cal_property_get_transp (prop);
89 		if (transp == I_CAL_TRANSP_TRANSPARENT ||
90 		    transp == I_CAL_TRANSP_TRANSPARENTNOCONFLICT)
91 			res = _("Free");
92 		else if (transp == I_CAL_TRANSP_OPAQUE ||
93 			 transp == I_CAL_TRANSP_OPAQUENOCONFLICT)
94 			res = _("Busy");
95 
96 		g_clear_object (&prop);
97 
98 		return (gpointer) res;
99 	}
100 
101 	return NULL;
102 }
103 
104 static void
set_dtend(ECalModel * model,ECalModelComponent * comp_data,gconstpointer value)105 set_dtend (ECalModel *model,
106            ECalModelComponent *comp_data,
107            gconstpointer value)
108 {
109 	e_cal_model_update_comp_time (model, comp_data, value, I_CAL_DTEND_PROPERTY, i_cal_property_set_dtend, i_cal_property_new_dtend);
110 }
111 
112 static void
set_location(ECalModelComponent * comp_data,gconstpointer value)113 set_location (ECalModelComponent *comp_data,
114               gconstpointer value)
115 {
116 	ICalProperty *prop;
117 
118 	prop = i_cal_component_get_first_property (comp_data->icalcomp, I_CAL_LOCATION_PROPERTY);
119 
120 	if (string_is_empty (value)) {
121 		if (prop) {
122 			i_cal_component_remove_property (comp_data->icalcomp, prop);
123 			g_object_unref (prop);
124 		}
125 	} else {
126 		if (prop) {
127 			i_cal_property_set_location (prop, (const gchar *) value);
128 			g_object_unref (prop);
129 		} else {
130 			prop = i_cal_property_new_location ((const gchar *) value);
131 			i_cal_component_take_property (comp_data->icalcomp, prop);
132 		}
133 	}
134 }
135 
136 static void
set_transparency(ECalModelComponent * comp_data,gconstpointer value)137 set_transparency (ECalModelComponent *comp_data,
138                   gconstpointer value)
139 {
140 	ICalProperty *prop;
141 
142 	prop = i_cal_component_get_first_property (comp_data->icalcomp, I_CAL_TRANSP_PROPERTY);
143 
144 	if (string_is_empty (value)) {
145 		if (prop) {
146 			i_cal_component_remove_property (comp_data->icalcomp, prop);
147 			g_object_unref (prop);
148 		}
149 	} else {
150 		ICalPropertyTransp transp;
151 
152 		if (!g_ascii_strcasecmp (value, "FREE"))
153 			transp = I_CAL_TRANSP_TRANSPARENT;
154 		else if (!g_ascii_strcasecmp (value, "OPAQUE"))
155 			transp = I_CAL_TRANSP_OPAQUE;
156 		else {
157 			if (prop) {
158 				i_cal_component_remove_property (comp_data->icalcomp, prop);
159 				g_object_unref (prop);
160 			}
161 
162 			return;
163 		}
164 
165 		if (prop) {
166 			i_cal_property_set_transp (prop, transp);
167 			g_object_unref (prop);
168 		} else {
169 			prop = i_cal_property_new_transp (transp);
170 			i_cal_component_take_property (comp_data->icalcomp, prop);
171 		}
172 	}
173 }
174 
175 static void
cal_model_calendar_store_values_from_model(ECalModel * model,ETableModel * source_model,gint row,GHashTable * values)176 cal_model_calendar_store_values_from_model (ECalModel *model,
177 					    ETableModel *source_model,
178 					    gint row,
179 					    GHashTable *values)
180 {
181 	g_return_if_fail (E_IS_CAL_MODEL_CALENDAR (model));
182 	g_return_if_fail (E_IS_TABLE_MODEL (source_model));
183 	g_return_if_fail (values != NULL);
184 
185 	e_cal_model_util_set_value (values, source_model, E_CAL_MODEL_CALENDAR_FIELD_DTEND, row);
186 	e_cal_model_util_set_value (values, source_model, E_CAL_MODEL_CALENDAR_FIELD_LOCATION, row);
187 	e_cal_model_util_set_value (values, source_model, E_CAL_MODEL_CALENDAR_FIELD_TRANSPARENCY, row);
188 	e_cal_model_util_set_value (values, source_model, E_CAL_MODEL_CALENDAR_FIELD_STATUS, row);
189 }
190 
191 static void
cal_model_calendar_fill_component_from_values(ECalModel * model,ECalModelComponent * comp_data,GHashTable * values)192 cal_model_calendar_fill_component_from_values (ECalModel *model,
193 					       ECalModelComponent *comp_data,
194 					       GHashTable *values)
195 {
196 	g_return_if_fail (E_IS_CAL_MODEL_CALENDAR (model));
197 	g_return_if_fail (comp_data != NULL);
198 	g_return_if_fail (values != NULL);
199 
200 	set_dtend (model, comp_data, e_cal_model_util_get_value (values, E_CAL_MODEL_CALENDAR_FIELD_DTEND));
201 	set_location (comp_data, e_cal_model_util_get_value (values, E_CAL_MODEL_CALENDAR_FIELD_LOCATION));
202 	set_transparency (comp_data, e_cal_model_util_get_value (values, E_CAL_MODEL_CALENDAR_FIELD_TRANSPARENCY));
203 	e_cal_model_util_set_status (comp_data, e_cal_model_util_get_value (values, E_CAL_MODEL_CALENDAR_FIELD_STATUS));
204 }
205 
206 static gint
cal_model_calendar_column_count(ETableModel * etm)207 cal_model_calendar_column_count (ETableModel *etm)
208 {
209 	return E_CAL_MODEL_CALENDAR_FIELD_LAST;
210 }
211 
212 static gpointer
cal_model_calendar_value_at(ETableModel * etm,gint col,gint row)213 cal_model_calendar_value_at (ETableModel *etm,
214                              gint col,
215                              gint row)
216 {
217 	ECalModelComponent *comp_data;
218 	ECalModelCalendar *model = (ECalModelCalendar *) etm;
219 
220 	g_return_val_if_fail (E_IS_CAL_MODEL_CALENDAR (model), NULL);
221 
222 	g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_CALENDAR_FIELD_LAST, NULL);
223 	g_return_val_if_fail (row >= 0 && row < e_table_model_row_count (etm), NULL);
224 
225 	if (col < E_CAL_MODEL_FIELD_LAST)
226 		return table_model_parent_interface->value_at (etm, col, row);
227 
228 	comp_data = e_cal_model_get_component_at (E_CAL_MODEL (model), row);
229 	if (!comp_data)
230 		return (gpointer) "";
231 
232 	switch (col) {
233 	case E_CAL_MODEL_CALENDAR_FIELD_DTEND :
234 		return get_dtend (model, comp_data);
235 	case E_CAL_MODEL_CALENDAR_FIELD_LOCATION :
236 		return get_location (comp_data);
237 	case E_CAL_MODEL_CALENDAR_FIELD_TRANSPARENCY :
238 		return get_transparency (comp_data);
239 	case E_CAL_MODEL_CALENDAR_FIELD_STATUS:
240 		return e_cal_model_util_get_status (comp_data);
241 	}
242 
243 	return (gpointer) "";
244 }
245 
246 static void
cal_model_calendar_set_value_at(ETableModel * etm,gint col,gint row,gconstpointer value)247 cal_model_calendar_set_value_at (ETableModel *etm,
248                                  gint col,
249                                  gint row,
250                                  gconstpointer value)
251 {
252 	ECalModelComponent *comp_data;
253 	ECalObjModType mod = E_CAL_OBJ_MOD_ALL;
254 	ECalComponent *comp;
255 	ECalModelCalendar *model = (ECalModelCalendar *) etm;
256 
257 	g_return_if_fail (E_IS_CAL_MODEL_CALENDAR (model));
258 	g_return_if_fail (col >= 0 && col < E_CAL_MODEL_CALENDAR_FIELD_LAST);
259 	g_return_if_fail (row >= 0 && row < e_table_model_row_count (etm));
260 
261 	if (col < E_CAL_MODEL_FIELD_LAST) {
262 		table_model_parent_interface->set_value_at (etm, col, row, value);
263 		return;
264 	}
265 
266 	comp_data = e_cal_model_get_component_at (E_CAL_MODEL (model), row);
267 	if (!comp_data)
268 		return;
269 
270 	comp = e_cal_component_new_from_icalcomponent (i_cal_component_clone (comp_data->icalcomp));
271 	if (!comp) {
272 		return;
273 	}
274 
275 	/* ask about mod type */
276 	if (e_cal_component_is_instance (comp)) {
277 		if (!e_cal_dialogs_recur_component (comp_data->client, comp, &mod, NULL, FALSE)) {
278 			g_object_unref (comp);
279 			return;
280 		}
281 	}
282 
283 	switch (col) {
284 	case E_CAL_MODEL_CALENDAR_FIELD_DTEND :
285 		set_dtend ((ECalModel *) model, comp_data, value);
286 		break;
287 	case E_CAL_MODEL_CALENDAR_FIELD_LOCATION :
288 		set_location (comp_data, value);
289 		break;
290 	case E_CAL_MODEL_CALENDAR_FIELD_TRANSPARENCY :
291 		set_transparency (comp_data, value);
292 		break;
293 	case E_CAL_MODEL_CALENDAR_FIELD_STATUS:
294 		e_cal_model_util_set_status (comp_data, value);
295 		break;
296 	}
297 
298 	e_cal_model_modify_component (E_CAL_MODEL (model), comp_data, mod);
299 
300 	g_object_unref (comp);
301 }
302 
303 static gboolean
cal_model_calendar_is_cell_editable(ETableModel * etm,gint col,gint row)304 cal_model_calendar_is_cell_editable (ETableModel *etm,
305                                      gint col,
306                                      gint row)
307 {
308 	ECalModelCalendar *model = (ECalModelCalendar *) etm;
309 
310 	g_return_val_if_fail (E_IS_CAL_MODEL_CALENDAR (model), FALSE);
311 	g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_CALENDAR_FIELD_LAST, FALSE);
312 	g_return_val_if_fail (row >= -1 || (row >= 0 && row < e_table_model_row_count (etm)), FALSE);
313 
314 	if (col < E_CAL_MODEL_FIELD_LAST)
315 		return table_model_parent_interface->is_cell_editable (etm, col, row);
316 
317 	if (!e_cal_model_test_row_editable (E_CAL_MODEL (etm), row))
318 		return FALSE;
319 
320 	switch (col) {
321 	case E_CAL_MODEL_CALENDAR_FIELD_DTEND :
322 	case E_CAL_MODEL_CALENDAR_FIELD_LOCATION :
323 	case E_CAL_MODEL_CALENDAR_FIELD_TRANSPARENCY :
324 	case E_CAL_MODEL_CALENDAR_FIELD_STATUS:
325 		return TRUE;
326 	}
327 
328 	return FALSE;
329 }
330 
331 static gpointer
cal_model_calendar_duplicate_value(ETableModel * etm,gint col,gconstpointer value)332 cal_model_calendar_duplicate_value (ETableModel *etm,
333                                     gint col,
334                                     gconstpointer value)
335 {
336 	g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_CALENDAR_FIELD_LAST, NULL);
337 
338 	if (col < E_CAL_MODEL_FIELD_LAST)
339 		return table_model_parent_interface->duplicate_value (etm, col, value);
340 
341 	switch (col) {
342 	case E_CAL_MODEL_CALENDAR_FIELD_DTEND :
343 		return e_cell_date_edit_value_copy (value);
344 	case E_CAL_MODEL_CALENDAR_FIELD_LOCATION :
345 	case E_CAL_MODEL_CALENDAR_FIELD_TRANSPARENCY :
346 		return g_strdup (value);
347 	case E_CAL_MODEL_CALENDAR_FIELD_STATUS:
348 		return (gpointer) value;
349 	}
350 
351 	return NULL;
352 }
353 
354 static void
cal_model_calendar_free_value(ETableModel * etm,gint col,gpointer value)355 cal_model_calendar_free_value (ETableModel *etm,
356                                gint col,
357                                gpointer value)
358 {
359 	g_return_if_fail (col >= 0 && col < E_CAL_MODEL_CALENDAR_FIELD_LAST);
360 
361 	if (col < E_CAL_MODEL_FIELD_LAST) {
362 		table_model_parent_interface->free_value (etm, col, value);
363 		return;
364 	}
365 
366 	switch (col) {
367 	case E_CAL_MODEL_CALENDAR_FIELD_DTEND :
368 		e_cell_date_edit_value_free (value);
369 		break;
370 	case E_CAL_MODEL_CALENDAR_FIELD_LOCATION :
371 	case E_CAL_MODEL_CALENDAR_FIELD_TRANSPARENCY :
372 	case E_CAL_MODEL_CALENDAR_FIELD_STATUS:
373 		break;
374 	}
375 }
376 
377 static gpointer
cal_model_calendar_initialize_value(ETableModel * etm,gint col)378 cal_model_calendar_initialize_value (ETableModel *etm,
379                                      gint col)
380 {
381 	g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_CALENDAR_FIELD_LAST, NULL);
382 
383 	if (col < E_CAL_MODEL_FIELD_LAST)
384 		return table_model_parent_interface->initialize_value (etm, col);
385 
386 	switch (col) {
387 	case E_CAL_MODEL_CALENDAR_FIELD_DTEND :
388 		return NULL;
389 	case E_CAL_MODEL_CALENDAR_FIELD_LOCATION :
390 	case E_CAL_MODEL_CALENDAR_FIELD_TRANSPARENCY :
391 		return g_strdup ("");
392 	case E_CAL_MODEL_CALENDAR_FIELD_STATUS:
393 		return (gpointer) "";
394 	}
395 
396 	return NULL;
397 }
398 
399 static gboolean
cal_model_calendar_value_is_empty(ETableModel * etm,gint col,gconstpointer value)400 cal_model_calendar_value_is_empty (ETableModel *etm,
401                                    gint col,
402                                    gconstpointer value)
403 {
404 	g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_CALENDAR_FIELD_LAST, TRUE);
405 
406 	if (col < E_CAL_MODEL_FIELD_LAST)
407 		return table_model_parent_interface->value_is_empty (etm, col, value);
408 
409 	switch (col) {
410 	case E_CAL_MODEL_CALENDAR_FIELD_DTEND :
411 		return value ? FALSE : TRUE;
412 	case E_CAL_MODEL_CALENDAR_FIELD_LOCATION :
413 	case E_CAL_MODEL_CALENDAR_FIELD_TRANSPARENCY :
414 	case E_CAL_MODEL_CALENDAR_FIELD_STATUS:
415 		return string_is_empty (value);
416 	}
417 
418 	return TRUE;
419 }
420 
421 static gchar *
cal_model_calendar_value_to_string(ETableModel * etm,gint col,gconstpointer value)422 cal_model_calendar_value_to_string (ETableModel *etm,
423                                     gint col,
424                                     gconstpointer value)
425 {
426 	g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_CALENDAR_FIELD_LAST, g_strdup (""));
427 
428 	if (col < E_CAL_MODEL_FIELD_LAST)
429 		return table_model_parent_interface->value_to_string (etm, col, value);
430 
431 	switch (col) {
432 	case E_CAL_MODEL_CALENDAR_FIELD_DTEND :
433 		return e_cal_model_date_value_to_string (E_CAL_MODEL (etm), value);
434 	case E_CAL_MODEL_CALENDAR_FIELD_LOCATION :
435 	case E_CAL_MODEL_CALENDAR_FIELD_TRANSPARENCY :
436 	case E_CAL_MODEL_CALENDAR_FIELD_STATUS:
437 		return g_strdup (value);
438 	}
439 
440 	return g_strdup ("");
441 }
442 
443 static void
e_cal_model_calendar_class_init(ECalModelCalendarClass * class)444 e_cal_model_calendar_class_init (ECalModelCalendarClass *class)
445 {
446 	ECalModelClass *model_class;
447 
448 	model_class = E_CAL_MODEL_CLASS (class);
449 	model_class->store_values_from_model = cal_model_calendar_store_values_from_model;
450 	model_class->fill_component_from_values = cal_model_calendar_fill_component_from_values;
451 }
452 
453 static void
e_cal_model_calendar_table_model_init(ETableModelInterface * iface)454 e_cal_model_calendar_table_model_init (ETableModelInterface *iface)
455 {
456 	table_model_parent_interface =
457 		g_type_interface_peek_parent (iface);
458 
459 	iface->column_count = cal_model_calendar_column_count;
460 	iface->value_at = cal_model_calendar_value_at;
461 	iface->set_value_at = cal_model_calendar_set_value_at;
462 	iface->is_cell_editable = cal_model_calendar_is_cell_editable;
463 	iface->duplicate_value = cal_model_calendar_duplicate_value;
464 	iface->free_value = cal_model_calendar_free_value;
465 	iface->initialize_value = cal_model_calendar_initialize_value;
466 	iface->value_is_empty = cal_model_calendar_value_is_empty;
467 	iface->value_to_string = cal_model_calendar_value_to_string;
468 }
469 
470 static void
e_cal_model_calendar_init(ECalModelCalendar * model)471 e_cal_model_calendar_init (ECalModelCalendar *model)
472 {
473 	e_cal_model_set_component_kind (
474 		E_CAL_MODEL (model), I_CAL_VEVENT_COMPONENT);
475 }
476 
477 ECalModel *
e_cal_model_calendar_new(ECalDataModel * data_model,ESourceRegistry * registry,EShell * shell)478 e_cal_model_calendar_new (ECalDataModel *data_model,
479 			  ESourceRegistry *registry,
480 			  EShell *shell)
481 {
482 	g_return_val_if_fail (E_IS_CAL_DATA_MODEL (data_model), NULL);
483 	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
484 	g_return_val_if_fail (E_IS_SHELL (shell), NULL);
485 
486 	return g_object_new (
487 		E_TYPE_CAL_MODEL_CALENDAR,
488 		"data-model", data_model,
489 		"registry", registry,
490 		"shell", shell,
491 		NULL);
492 }
493 
494