No issues found
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /* e-calendar-selector.c
3 *
4 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
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 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #include <config.h>
22
23 #include "e-calendar-selector.h"
24
25 #include <libecal/libecal.h>
26
27 #include "e-util/e-selection.h"
28
29 #define E_CALENDAR_SELECTOR_GET_PRIVATE(obj) \
30 (G_TYPE_INSTANCE_GET_PRIVATE \
31 ((obj), E_TYPE_CALENDAR_SELECTOR, ECalendarSelectorPrivate))
32
33 struct _ECalendarSelectorPrivate {
34 gint dummy_value;
35 };
36
37 G_DEFINE_TYPE (
38 ECalendarSelector,
39 e_calendar_selector,
40 E_TYPE_SOURCE_SELECTOR)
41
42 static gboolean
43 calendar_selector_update_single_object (ECalClient *client,
44 icalcomponent *icalcomp)
45 {
46 gchar *uid;
47 icalcomponent *tmp_icalcomp;
48
49 uid = (gchar *) icalcomponent_get_uid (icalcomp);
50
51 if (e_cal_client_get_object_sync (client, uid, NULL, &tmp_icalcomp, NULL, NULL)) {
52 icalcomponent_free (tmp_icalcomp);
53
54 return e_cal_client_modify_object_sync (
55 client, icalcomp, CALOBJ_MOD_ALL, NULL, NULL);
56 }
57
58 uid = NULL;
59 if (!e_cal_client_create_object_sync (client, icalcomp, &uid, NULL, NULL))
60 return FALSE;
61
62 if (uid)
63 icalcomponent_set_uid (icalcomp, uid);
64 g_free (uid);
65
66 return TRUE;
67 }
68
69 static gboolean
70 calendar_selector_update_objects (ECalClient *client,
71 icalcomponent *icalcomp)
72 {
73 icalcomponent *subcomp;
74 icalcomponent_kind kind;
75
76 kind = icalcomponent_isa (icalcomp);
77 if (kind == ICAL_VTODO_COMPONENT || kind == ICAL_VEVENT_COMPONENT)
78 return calendar_selector_update_single_object (
79 client, icalcomp);
80 else if (kind != ICAL_VCALENDAR_COMPONENT)
81 return FALSE;
82
83 subcomp = icalcomponent_get_first_component (
84 icalcomp, ICAL_ANY_COMPONENT);
85 while (subcomp != NULL) {
86 gboolean success;
87
88 kind = icalcomponent_isa (subcomp);
89 if (kind == ICAL_VTIMEZONE_COMPONENT) {
90 icaltimezone *zone;
91 GError *error = NULL;
92
93 zone = icaltimezone_new ();
94 icaltimezone_set_component (zone, subcomp);
95
96 e_cal_client_add_timezone_sync (client, zone, NULL, &error);
97 icaltimezone_free (zone, 1);
98
99 if (error != NULL) {
100 g_warning (
101 "%s: Failed to add timezone: %s",
102 G_STRFUNC, error->message);
103 g_error_free (error);
104 return FALSE;
105 }
106 } else if (kind == ICAL_VTODO_COMPONENT ||
107 kind == ICAL_VEVENT_COMPONENT) {
108 success = calendar_selector_update_single_object (
109 client, subcomp);
110 if (!success)
111 return FALSE;
112 }
113
114 subcomp = icalcomponent_get_next_component (
115 icalcomp, ICAL_ANY_COMPONENT);
116 }
117
118 return TRUE;
119 }
120
121 static void
122 client_opened_cb (GObject *source_object,
123 GAsyncResult *result,
124 gpointer user_data)
125 {
126 ESource *source = E_SOURCE (source_object);
127 EClient *client = NULL;
128 icalcomponent *icalcomp = user_data;
129 GError *error = NULL;
130
131 g_return_if_fail (icalcomp != NULL);
132
133 e_client_utils_open_new_finish (source, result, &client, &error);
134
135 if (error != NULL) {
136 g_warn_if_fail (client == NULL);
137 g_warning (
138 "%s: Failed to open client: %s",
139 G_STRFUNC, error->message);
140 g_error_free (error);
141 }
142
143 g_return_if_fail (E_IS_CLIENT (client));
144
145 calendar_selector_update_objects (E_CAL_CLIENT (client), icalcomp);
146 g_object_unref (client);
147
148 icalcomponent_free (icalcomp);
149 }
150
151 static void
152 calendar_selector_constructed (GObject *object)
153 {
154 ESourceSelector *selector;
155 ESourceRegistry *registry;
156 ESource *source;
157
158 selector = E_SOURCE_SELECTOR (object);
159 registry = e_source_selector_get_registry (selector);
160 source = e_source_registry_ref_default_calendar (registry);
161 e_source_selector_set_primary_selection (selector, source);
162 g_object_unref (source);
163
164 /* Chain up to parent's constructed() method. */
165 G_OBJECT_CLASS (e_calendar_selector_parent_class)->
166 constructed (object);
167 }
168
169 static gboolean
170 calendar_selector_data_dropped (ESourceSelector *selector,
171 GtkSelectionData *selection_data,
172 ESource *destination,
173 GdkDragAction action,
174 guint info)
175 {
176 GtkTreePath *path = NULL;
177 icalcomponent *icalcomp;
178 const guchar *data;
179 gboolean success = FALSE;
180 gpointer object = NULL;
181
182 data = gtk_selection_data_get_data (selection_data);
183 icalcomp = icalparser_parse_string ((const gchar *) data);
184
185 if (icalcomp == NULL)
186 goto exit;
187
188 /* FIXME Deal with GDK_ACTION_ASK. */
189 if (action == GDK_ACTION_COPY) {
190 gchar *uid;
191
192 uid = e_cal_component_gen_uid ();
193 icalcomponent_set_uid (icalcomp, uid);
194 }
195
196 e_client_utils_open_new (
197 destination, E_CLIENT_SOURCE_TYPE_EVENTS, FALSE, NULL,
198 client_opened_cb, icalcomp);
199
200 success = TRUE;
201
202 exit:
203 if (path != NULL)
204 gtk_tree_path_free (path);
205
206 if (object != NULL)
207 g_object_unref (object);
208
209 return success;
210 }
211
212 static void
213 e_calendar_selector_class_init (ECalendarSelectorClass *class)
214 {
215 GObjectClass *object_class;
216 ESourceSelectorClass *source_selector_class;
217
218 g_type_class_add_private (class, sizeof (ECalendarSelectorPrivate));
219
220 object_class = G_OBJECT_CLASS (class);
221 object_class->constructed = calendar_selector_constructed;
222
223 source_selector_class = E_SOURCE_SELECTOR_CLASS (class);
224 source_selector_class->data_dropped = calendar_selector_data_dropped;
225 }
226
227 static void
228 e_calendar_selector_init (ECalendarSelector *selector)
229 {
230 selector->priv = E_CALENDAR_SELECTOR_GET_PRIVATE (selector);
231
232 gtk_drag_dest_set (
233 GTK_WIDGET (selector), GTK_DEST_DEFAULT_ALL,
234 NULL, 0, GDK_ACTION_COPY | GDK_ACTION_MOVE);
235
236 e_drag_dest_add_calendar_targets (GTK_WIDGET (selector));
237 }
238
239 GtkWidget *
240 e_calendar_selector_new (ESourceRegistry *registry)
241 {
242 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
243
244 return g_object_new (
245 E_TYPE_CALENDAR_SELECTOR,
246 "extension-name", E_SOURCE_EXTENSION_CALENDAR,
247 "registry", registry, NULL);
248 }