No issues found
1 /*
2 * e-cal-source-config.c
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with the program; if not, see <http://www.gnu.org/licenses/>
16 *
17 */
18
19 #include "e-cal-source-config.h"
20
21 #include <config.h>
22 #include <glib/gi18n-lib.h>
23
24 #include <e-util/e-util.h>
25
26 #define E_CAL_SOURCE_CONFIG_GET_PRIVATE(obj) \
27 (G_TYPE_INSTANCE_GET_PRIVATE \
28 ((obj), E_TYPE_CAL_SOURCE_CONFIG, ECalSourceConfigPrivate))
29
30 struct _ECalSourceConfigPrivate {
31 ECalClientSourceType source_type;
32 GtkWidget *color_button;
33 GtkWidget *default_button;
34 };
35
36 enum {
37 PROP_0,
38 PROP_SOURCE_TYPE
39 };
40
41 G_DEFINE_TYPE (
42 ECalSourceConfig,
43 e_cal_source_config,
44 E_TYPE_SOURCE_CONFIG)
45
46 static ESource *
47 cal_source_config_ref_default (ESourceConfig *config)
48 {
49 ECalSourceConfigPrivate *priv;
50 ESourceRegistry *registry;
51
52 priv = E_CAL_SOURCE_CONFIG_GET_PRIVATE (config);
53 registry = e_source_config_get_registry (config);
54
55 if (priv->source_type == E_CAL_CLIENT_SOURCE_TYPE_EVENTS)
56 return e_source_registry_ref_default_calendar (registry);
57 else if (priv->source_type == E_CAL_CLIENT_SOURCE_TYPE_MEMOS)
58 return e_source_registry_ref_default_memo_list (registry);
59 else if (priv->source_type == E_CAL_CLIENT_SOURCE_TYPE_TASKS)
60 return e_source_registry_ref_default_task_list (registry);
61
62 g_return_val_if_reached (NULL);
63 }
64
65 static void
66 cal_source_config_set_default (ESourceConfig *config,
67 ESource *source)
68 {
69 ECalSourceConfigPrivate *priv;
70 ESourceRegistry *registry;
71
72 priv = E_CAL_SOURCE_CONFIG_GET_PRIVATE (config);
73 registry = e_source_config_get_registry (config);
74
75 if (priv->source_type == E_CAL_CLIENT_SOURCE_TYPE_EVENTS)
76 e_source_registry_set_default_calendar (registry, source);
77 else if (priv->source_type == E_CAL_CLIENT_SOURCE_TYPE_MEMOS)
78 e_source_registry_set_default_memo_list (registry, source);
79 else if (priv->source_type == E_CAL_CLIENT_SOURCE_TYPE_TASKS)
80 e_source_registry_set_default_task_list (registry, source);
81 }
82
83 static void
84 cal_source_config_set_source_type (ECalSourceConfig *config,
85 ECalClientSourceType source_type)
86 {
87 config->priv->source_type = source_type;
88 }
89
90 static void
91 cal_source_config_set_property (GObject *object,
92 guint property_id,
93 const GValue *value,
94 GParamSpec *pspec)
95 {
96 switch (property_id) {
97 case PROP_SOURCE_TYPE:
98 cal_source_config_set_source_type (
99 E_CAL_SOURCE_CONFIG (object),
100 g_value_get_enum (value));
101 return;
102 }
103
104 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
105 }
106
107 static void
108 cal_source_config_get_property (GObject *object,
109 guint property_id,
110 GValue *value,
111 GParamSpec *pspec)
112 {
113 switch (property_id) {
114 case PROP_SOURCE_TYPE:
115 g_value_set_enum (
116 value,
117 e_cal_source_config_get_source_type (
118 E_CAL_SOURCE_CONFIG (object)));
119 return;
120 }
121
122 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
123 }
124
125 static void
126 cal_source_config_dispose (GObject *object)
127 {
128 ECalSourceConfigPrivate *priv;
129
130 priv = E_CAL_SOURCE_CONFIG_GET_PRIVATE (object);
131
132 if (priv->color_button != NULL) {
133 g_object_unref (priv->color_button);
134 priv->color_button = NULL;
135 }
136
137 if (priv->default_button != NULL) {
138 g_object_unref (priv->default_button);
139 priv->default_button = NULL;
140 }
141
142 /* Chain up to parent's dispose() method. */
143 G_OBJECT_CLASS (e_cal_source_config_parent_class)->dispose (object);
144 }
145
146 static void
147 cal_source_config_constructed (GObject *object)
148 {
149 ECalSourceConfigPrivate *priv;
150 ESource *default_source;
151 ESource *original_source;
152 ESourceConfig *config;
153 GObjectClass *class;
154 GtkWidget *widget;
155 const gchar *label;
156
157 /* Chain up to parent's constructed() method. */
158 class = G_OBJECT_CLASS (e_cal_source_config_parent_class);
159 class->constructed (object);
160
161 config = E_SOURCE_CONFIG (object);
162 priv = E_CAL_SOURCE_CONFIG_GET_PRIVATE (object);
163
164 widget = gtk_color_button_new ();
165 priv->color_button = g_object_ref_sink (widget);
166 gtk_widget_show (widget);
167
168 switch (priv->source_type) {
169 case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
170 label = _("Mark as default calendar");
171 break;
172 case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
173 label = _("Mark as default task list");
174 break;
175 case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
176 label = _("Mark as default memo list");
177 break;
178 default:
179 /* No need to translate this string. */
180 label = "Invalid ECalSourceType value";
181 g_warn_if_reached ();
182 }
183
184 widget = gtk_check_button_new_with_label (label);
185 priv->default_button = g_object_ref_sink (widget);
186 gtk_widget_show (widget);
187
188 default_source = cal_source_config_ref_default (config);
189 original_source = e_source_config_get_original_source (config);
190
191 if (original_source != NULL) {
192 gboolean active;
193
194 active = e_source_equal (original_source, default_source);
195 g_object_set (priv->default_button, "active", active, NULL);
196 }
197
198 g_object_unref (default_source);
199
200 e_source_config_insert_widget (
201 config, NULL, _("Color:"), priv->color_button);
202
203 e_source_config_insert_widget (
204 config, NULL, NULL, priv->default_button);
205 }
206
207 static const gchar *
208 cal_source_config_get_backend_extension_name (ESourceConfig *config)
209 {
210 ECalSourceConfig *cal_config;
211 const gchar *extension_name;
212
213 cal_config = E_CAL_SOURCE_CONFIG (config);
214
215 switch (e_cal_source_config_get_source_type (cal_config)) {
216 case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
217 extension_name = E_SOURCE_EXTENSION_CALENDAR;
218 break;
219 case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
220 extension_name = E_SOURCE_EXTENSION_TASK_LIST;
221 break;
222 case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
223 extension_name = E_SOURCE_EXTENSION_MEMO_LIST;
224 break;
225 default:
226 g_return_val_if_reached (NULL);
227 }
228
229 return extension_name;
230 }
231
232 static GList *
233 cal_source_config_list_eligible_collections (ESourceConfig *config)
234 {
235 GQueue trash = G_QUEUE_INIT;
236 GList *list, *link;
237
238 /* Chain up to parent's list_eligible_collections() method. */
239 list = E_SOURCE_CONFIG_CLASS (e_cal_source_config_parent_class)->
240 list_eligible_collections (config);
241
242 for (link = list; link != NULL; link = g_list_next (link)) {
243 ESource *source = E_SOURCE (link->data);
244 ESourceCollection *extension;
245 const gchar *extension_name;
246
247 extension_name = E_SOURCE_EXTENSION_COLLECTION;
248 extension = e_source_get_extension (source, extension_name);
249
250 if (!e_source_collection_get_calendar_enabled (extension))
251 g_queue_push_tail (&trash, link);
252 }
253
254 /* Remove ineligible collections from the list. */
255 while ((link = g_queue_pop_head (&trash)) != NULL) {
256 g_object_unref (link->data);
257 list = g_list_delete_link (list, link);
258 }
259
260 return list;
261 }
262
263 static void
264 cal_source_config_init_candidate (ESourceConfig *config,
265 ESource *scratch_source)
266 {
267 ECalSourceConfigPrivate *priv;
268 ESourceConfigClass *class;
269 ESourceExtension *extension;
270 const gchar *extension_name;
271
272 /* Chain up to parent's init_candidate() method. */
273 class = E_SOURCE_CONFIG_CLASS (e_cal_source_config_parent_class);
274 class->init_candidate (config, scratch_source);
275
276 priv = E_CAL_SOURCE_CONFIG_GET_PRIVATE (config);
277
278 extension_name = e_source_config_get_backend_extension_name (config);
279 extension = e_source_get_extension (scratch_source, extension_name);
280
281 g_object_bind_property_full (
282 extension, "color",
283 priv->color_button, "color",
284 G_BINDING_BIDIRECTIONAL |
285 G_BINDING_SYNC_CREATE,
286 e_binding_transform_string_to_color,
287 e_binding_transform_color_to_string,
288 NULL, (GDestroyNotify) NULL);
289 }
290
291 static void
292 cal_source_config_commit_changes (ESourceConfig *config,
293 ESource *scratch_source)
294 {
295 ECalSourceConfigPrivate *priv;
296 GtkToggleButton *toggle_button;
297 ESourceConfigClass *class;
298 ESource *default_source;
299
300 priv = E_CAL_SOURCE_CONFIG_GET_PRIVATE (config);
301 toggle_button = GTK_TOGGLE_BUTTON (priv->default_button);
302
303 /* Chain up to parent's commit_changes() method. */
304 class = E_SOURCE_CONFIG_CLASS (e_cal_source_config_parent_class);
305 class->commit_changes (config, scratch_source);
306
307 default_source = cal_source_config_ref_default (config);
308
309 /* The default setting is a little tricky to get right. If
310 * the toggle button is active, this ESource is now the default.
311 * That much is simple. But if the toggle button is NOT active,
312 * then we have to inspect the old default. If this ESource WAS
313 * the default, reset the default to 'system'. If this ESource
314 * WAS NOT the old default, leave it alone. */
315 if (gtk_toggle_button_get_active (toggle_button))
316 cal_source_config_set_default (config, scratch_source);
317 else if (e_source_equal (scratch_source, default_source))
318 cal_source_config_set_default (config, NULL);
319
320 g_object_unref (default_source);
321 }
322
323 static void
324 e_cal_source_config_class_init (ECalSourceConfigClass *class)
325 {
326 GObjectClass *object_class;
327 ESourceConfigClass *source_config_class;
328
329 g_type_class_add_private (class, sizeof (ECalSourceConfigPrivate));
330
331 object_class = G_OBJECT_CLASS (class);
332 object_class->set_property = cal_source_config_set_property;
333 object_class->get_property = cal_source_config_get_property;
334 object_class->dispose = cal_source_config_dispose;
335 object_class->constructed = cal_source_config_constructed;
336
337 source_config_class = E_SOURCE_CONFIG_CLASS (class);
338 source_config_class->get_backend_extension_name =
339 cal_source_config_get_backend_extension_name;
340 source_config_class->list_eligible_collections =
341 cal_source_config_list_eligible_collections;
342 source_config_class->init_candidate = cal_source_config_init_candidate;
343 source_config_class->commit_changes = cal_source_config_commit_changes;
344
345 g_object_class_install_property (
346 object_class,
347 PROP_SOURCE_TYPE,
348 g_param_spec_enum (
349 "source-type",
350 "Source Type",
351 "The iCalendar object type",
352 E_TYPE_CAL_CLIENT_SOURCE_TYPE,
353 E_CAL_CLIENT_SOURCE_TYPE_EVENTS,
354 G_PARAM_READWRITE |
355 G_PARAM_CONSTRUCT_ONLY |
356 G_PARAM_STATIC_STRINGS));
357 }
358
359 static void
360 e_cal_source_config_init (ECalSourceConfig *config)
361 {
362 config->priv = E_CAL_SOURCE_CONFIG_GET_PRIVATE (config);
363 }
364
365 GtkWidget *
366 e_cal_source_config_new (ESourceRegistry *registry,
367 ESource *original_source,
368 ECalClientSourceType source_type)
369 {
370 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
371
372 if (original_source != NULL)
373 g_return_val_if_fail (E_IS_SOURCE (original_source), NULL);
374
375 return g_object_new (
376 E_TYPE_CAL_SOURCE_CONFIG, "registry", registry,
377 "original-source", original_source, "source-type",
378 source_type, NULL);
379 }
380
381 ECalClientSourceType
382 e_cal_source_config_get_source_type (ECalSourceConfig *config)
383 {
384 g_return_val_if_fail (E_IS_CAL_SOURCE_CONFIG (config), 0);
385
386 return config->priv->source_type;
387 }
388
389 void
390 e_cal_source_config_add_offline_toggle (ECalSourceConfig *config,
391 ESource *scratch_source)
392 {
393 GtkWidget *widget;
394 ESourceExtension *extension;
395 const gchar *extension_name;
396 const gchar *label;
397
398 g_return_if_fail (E_IS_CAL_SOURCE_CONFIG (config));
399 g_return_if_fail (E_IS_SOURCE (scratch_source));
400
401 extension_name = E_SOURCE_EXTENSION_OFFLINE;
402 extension = e_source_get_extension (scratch_source, extension_name);
403
404 switch (e_cal_source_config_get_source_type (config)) {
405 case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
406 label = _("Copy calendar contents locally "
407 "for offline operation");
408 break;
409 case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
410 label = _("Copy task list contents locally "
411 "for offline operation");
412 break;
413 case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
414 label = _("Copy memo list contents locally "
415 "for offline operation");
416 break;
417 default:
418 g_return_if_reached ();
419 }
420
421 widget = gtk_check_button_new_with_label (label);
422 e_source_config_insert_widget (
423 E_SOURCE_CONFIG (config), scratch_source, NULL, widget);
424 gtk_widget_show (widget);
425
426 g_object_bind_property (
427 extension, "stay-synchronized",
428 widget, "active",
429 G_BINDING_BIDIRECTIONAL |
430 G_BINDING_SYNC_CREATE);
431 }