No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | e-memo-shell-backend.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None | |
clang-analyzer | no-output-found | e-memo-shell-backend.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /*
2 * e-memo-shell-backend.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 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
19 *
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include "e-memo-shell-backend.h"
27
28 #include <string.h>
29 #include <glib/gi18n.h>
30 #include <libecal/libecal.h>
31 #include <libedataserverui/libedataserverui.h>
32
33 #include "shell/e-shell.h"
34 #include "shell/e-shell-backend.h"
35 #include "shell/e-shell-window.h"
36 #include "widgets/misc/e-cal-source-config.h"
37 #include "widgets/misc/e-source-config-dialog.h"
38
39 #include "calendar/gui/comp-util.h"
40 #include "calendar/gui/dialogs/memo-editor.h"
41
42 #include "e-memo-shell-migrate.h"
43 #include "e-memo-shell-view.h"
44
45 #define E_MEMO_SHELL_BACKEND_GET_PRIVATE(obj) \
46 (G_TYPE_INSTANCE_GET_PRIVATE \
47 ((obj), E_TYPE_MEMO_SHELL_BACKEND, EMemoShellBackendPrivate))
48
49 #define E_MEMO_SHELL_BACKEND_GET_PRIVATE(obj) \
50 (G_TYPE_INSTANCE_GET_PRIVATE \
51 ((obj), E_TYPE_MEMO_SHELL_BACKEND, EMemoShellBackendPrivate))
52
53 struct _EMemoShellBackendPrivate {
54 gint placeholder;
55 };
56
57 G_DEFINE_DYNAMIC_TYPE (
58 EMemoShellBackend,
59 e_memo_shell_backend,
60 E_TYPE_SHELL_BACKEND)
61
62 static void
63 memo_shell_backend_new_memo (ESource *source,
64 GAsyncResult *result,
65 EShell *shell,
66 CompEditorFlags flags)
67 {
68 EClient *client = NULL;
69 ECalClient *cal_client;
70 ECalComponent *comp;
71 CompEditor *editor;
72 GError *error = NULL;
73
74 e_client_utils_open_new_finish (source, result, &client, &error);
75
76 /* XXX Handle errors better. */
77 if (error != NULL) {
78 g_warn_if_fail (client == NULL);
79 g_warning (
80 "%s: Failed to open '%s': %s",
81 G_STRFUNC, e_source_get_display_name (source),
82 error->message);
83 g_error_free (error);
84 return;
85 }
86
87 g_return_if_fail (E_IS_CAL_CLIENT (client));
88
89 cal_client = E_CAL_CLIENT (client);
90 comp = cal_comp_memo_new_with_defaults (cal_client);
91 cal_comp_update_time_by_active_window (comp, shell);
92 editor = memo_editor_new (cal_client, shell, flags);
93 comp_editor_edit_comp (editor, comp);
94
95 gtk_window_present (GTK_WINDOW (editor));
96
97 g_object_unref (comp);
98 g_object_unref (client);
99 }
100
101 static void
102 memo_shell_backend_memo_new_cb (GObject *source_object,
103 GAsyncResult *result,
104 gpointer shell)
105 {
106 CompEditorFlags flags = 0;
107
108 flags |= COMP_EDITOR_NEW_ITEM;
109
110 memo_shell_backend_new_memo (
111 E_SOURCE (source_object), result, shell, flags);
112
113 g_object_unref (shell);
114 }
115
116 static void
117 memo_shell_backend_memo_shared_new_cb (GObject *source_object,
118 GAsyncResult *result,
119 gpointer shell)
120 {
121 CompEditorFlags flags = 0;
122
123 flags |= COMP_EDITOR_NEW_ITEM;
124 flags |= COMP_EDITOR_IS_SHARED;
125 flags |= COMP_EDITOR_USER_ORG;
126
127 memo_shell_backend_new_memo (
128 E_SOURCE (source_object), result, shell, flags);
129
130 g_object_unref (shell);
131 }
132
133 static void
134 action_memo_new_cb (GtkAction *action,
135 EShellWindow *shell_window)
136 {
137 EShell *shell;
138 ESource *source;
139 ESourceRegistry *registry;
140 EClientSourceType source_type;
141 const gchar *action_name;
142
143 /* This callback is used for both memos and shared memos. */
144
145 shell = e_shell_window_get_shell (shell_window);
146
147 registry = e_shell_get_registry (shell);
148 source_type = E_CLIENT_SOURCE_TYPE_MEMOS;
149 source = e_source_registry_ref_default_memo_list (registry);
150
151 /* Use a callback function appropriate for the action.
152 * FIXME Need to obtain a better default time zone. */
153 action_name = gtk_action_get_name (action);
154 if (g_strcmp0 (action_name, "memo-shared-new") == 0)
155 e_client_utils_open_new (
156 source, source_type, FALSE, NULL,
157 memo_shell_backend_memo_shared_new_cb,
158 g_object_ref (shell));
159 else
160 e_client_utils_open_new (
161 source, source_type, FALSE, NULL,
162 memo_shell_backend_memo_new_cb,
163 g_object_ref (shell));
164
165 g_object_unref (source);
166 }
167
168 static void
169 action_memo_list_new_cb (GtkAction *action,
170 EShellWindow *shell_window)
171 {
172 EShell *shell;
173 ESourceRegistry *registry;
174 ECalClientSourceType source_type;
175 GtkWidget *config;
176 GtkWidget *dialog;
177 const gchar *icon_name;
178
179 shell = e_shell_window_get_shell (shell_window);
180
181 registry = e_shell_get_registry (shell);
182 source_type = E_CAL_CLIENT_SOURCE_TYPE_MEMOS;
183 config = e_cal_source_config_new (registry, NULL, source_type);
184
185 dialog = e_source_config_dialog_new (E_SOURCE_CONFIG (config));
186
187 gtk_window_set_transient_for (
188 GTK_WINDOW (dialog), GTK_WINDOW (shell_window));
189
190 icon_name = gtk_action_get_icon_name (action);
191 gtk_window_set_icon_name (GTK_WINDOW (dialog), icon_name);
192
193 gtk_window_set_title (GTK_WINDOW (dialog), _("New Memo List"));
194
195 gtk_widget_show (dialog);
196 }
197
198 static GtkActionEntry item_entries[] = {
199
200 { "memo-new",
201 "stock_insert-note",
202 NC_("New", "Mem_o"),
203 "<Shift><Control>o",
204 N_("Create a new memo"),
205 G_CALLBACK (action_memo_new_cb) },
206
207 { "memo-shared-new",
208 "stock_insert-note",
209 NC_("New", "_Shared Memo"),
210 "<Shift><Control>h",
211 N_("Create a new shared memo"),
212 G_CALLBACK (action_memo_new_cb) }
213 };
214
215 static GtkActionEntry source_entries[] = {
216
217 { "memo-list-new",
218 "stock_notes",
219 NC_("New", "Memo Li_st"),
220 NULL,
221 N_("Create a new memo list"),
222 G_CALLBACK (action_memo_list_new_cb) }
223 };
224
225 static gboolean
226 memo_shell_backend_handle_uri_cb (EShellBackend *shell_backend,
227 const gchar *uri)
228 {
229 EShell *shell;
230 CompEditor *editor;
231 CompEditorFlags flags = 0;
232 ECalClient *client;
233 ECalComponent *comp;
234 ESource *source;
235 ESourceRegistry *registry;
236 ECalClientSourceType source_type;
237 SoupURI *soup_uri;
238 icalcomponent *icalcomp;
239 const gchar *cp;
240 gchar *source_uid = NULL;
241 gchar *comp_uid = NULL;
242 gchar *comp_rid = NULL;
243 gboolean handled = FALSE;
244 GError *error = NULL;
245
246 source_type = E_CAL_CLIENT_SOURCE_TYPE_MEMOS;
247 shell = e_shell_backend_get_shell (shell_backend);
248
249 if (strncmp (uri, "memo:", 5) != 0)
250 return FALSE;
251
252 soup_uri = soup_uri_new (uri);
253
254 if (soup_uri == NULL)
255 return FALSE;
256
257 cp = soup_uri_get_query (soup_uri);
258 if (cp == NULL)
259 goto exit;
260
261 while (*cp != '\0') {
262 gchar *header;
263 gchar *content;
264 gsize header_len;
265 gsize content_len;
266
267 header_len = strcspn (cp, "=&");
268
269 /* If it's malformed, give up. */
270 if (cp[header_len] != '=')
271 break;
272
273 header = (gchar *) cp;
274 header[header_len] = '\0';
275 cp += header_len + 1;
276
277 content_len = strcspn (cp, "&");
278
279 content = g_strndup (cp, content_len);
280 if (g_ascii_strcasecmp (header, "source-uid") == 0)
281 source_uid = g_strdup (content);
282 else if (g_ascii_strcasecmp (header, "comp-uid") == 0)
283 comp_uid = g_strdup (content);
284 else if (g_ascii_strcasecmp (header, "comp-rid") == 0)
285 comp_rid = g_strdup (content);
286 g_free (content);
287
288 cp += content_len;
289 if (*cp == '&') {
290 cp++;
291 if (strcmp (cp, "amp;") == 0)
292 cp += 4;
293 }
294 }
295
296 if (source_uid == NULL || comp_uid == NULL)
297 goto exit;
298
299 /* URI is valid, so consider it handled. Whether
300 * we successfully open it is another matter... */
301 handled = TRUE;
302
303 registry = e_shell_get_registry (shell);
304 source = e_source_registry_ref_source (registry, source_uid);
305 if (source == NULL) {
306 g_printerr ("No source for UID '%s'\n", source_uid);
307 goto exit;
308 }
309
310 client = e_cal_client_new (source, source_type, &error);
311
312 if (client != NULL)
313 e_client_open_sync (E_CLIENT (client), TRUE, NULL, &error);
314
315 if (error != NULL) {
316 g_warning (
317 "%s: Failed to create/open client: %s",
318 G_STRFUNC, error->message);
319 if (client != NULL)
320 g_object_unref (client);
321 g_object_unref (source);
322 g_error_free (error);
323 goto exit;
324 }
325
326 g_object_unref (source);
327 source = NULL;
328
329 /* XXX Copied from e_memo_shell_view_open_memo().
330 * Clearly a new utility function is needed. */
331
332 editor = comp_editor_find_instance (comp_uid);
333
334 if (editor != NULL)
335 goto present;
336
337 e_cal_client_get_object_sync (
338 client, comp_uid, comp_rid, &icalcomp, NULL, &error);
339
340 if (error != NULL) {
341 g_warning (
342 "%s: Failed to get object: %s",
343 G_STRFUNC, error->message);
344 g_object_unref (client);
345 g_error_free (error);
346 goto exit;
347 }
348
349 comp = e_cal_component_new ();
350 if (!e_cal_component_set_icalcomponent (comp, icalcomp)) {
351 g_warning ("%s: Failed to set icalcomp to comp\n", G_STRFUNC);
352 icalcomponent_free (icalcomp);
353 icalcomp = NULL;
354 }
355
356 if (e_cal_component_has_organizer (comp))
357 flags |= COMP_EDITOR_IS_SHARED;
358
359 if (itip_organizer_is_user (registry, comp, client))
360 flags |= COMP_EDITOR_USER_ORG;
361
362 editor = memo_editor_new (client, shell, flags);
363 comp_editor_edit_comp (editor, comp);
364
365 g_object_unref (comp);
366
367 present:
368 gtk_window_present (GTK_WINDOW (editor));
369
370 g_object_unref (client);
371
372 exit:
373 g_free (source_uid);
374 g_free (comp_uid);
375 g_free (comp_rid);
376
377 soup_uri_free (soup_uri);
378
379 return handled;
380 }
381
382 static void
383 memo_shell_backend_window_added_cb (EShellBackend *shell_backend,
384 GtkWindow *window)
385 {
386 const gchar *module_name;
387
388 if (!E_IS_SHELL_WINDOW (window))
389 return;
390
391 module_name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name;
392
393 e_shell_window_register_new_item_actions (
394 E_SHELL_WINDOW (window), module_name,
395 item_entries, G_N_ELEMENTS (item_entries));
396
397 e_shell_window_register_new_source_actions (
398 E_SHELL_WINDOW (window), module_name,
399 source_entries, G_N_ELEMENTS (source_entries));
400 }
401
402 static void
403 memo_shell_backend_constructed (GObject *object)
404 {
405 EShell *shell;
406 EShellBackend *shell_backend;
407
408 shell_backend = E_SHELL_BACKEND (object);
409 shell = e_shell_backend_get_shell (shell_backend);
410
411 g_signal_connect_swapped (
412 shell, "handle-uri",
413 G_CALLBACK (memo_shell_backend_handle_uri_cb),
414 shell_backend);
415
416 g_signal_connect_swapped (
417 shell, "window-added",
418 G_CALLBACK (memo_shell_backend_window_added_cb),
419 shell_backend);
420
421 /* Chain up to parent's constructed() method. */
422 G_OBJECT_CLASS (e_memo_shell_backend_parent_class)->constructed (object);
423 }
424
425 static void
426 e_memo_shell_backend_class_init (EMemoShellBackendClass *class)
427 {
428 GObjectClass *object_class;
429 EShellBackendClass *shell_backend_class;
430
431 g_type_class_add_private (class, sizeof (EMemoShellBackendPrivate));
432
433 object_class = G_OBJECT_CLASS (class);
434 object_class->constructed = memo_shell_backend_constructed;
435
436 shell_backend_class = E_SHELL_BACKEND_CLASS (class);
437 shell_backend_class->shell_view_type = E_TYPE_MEMO_SHELL_VIEW;
438 shell_backend_class->name = "memos";
439 shell_backend_class->aliases = "";
440 shell_backend_class->schemes = "memo";
441 shell_backend_class->sort_order = 600;
442 shell_backend_class->preferences_page = "calendar-and-tasks";
443 shell_backend_class->start = NULL;
444 shell_backend_class->migrate = e_memo_shell_backend_migrate;
445
446 /* Register relevant ESource extensions. */
447 E_TYPE_SOURCE_MEMO_LIST;
448 }
449
450 static void
451 e_memo_shell_backend_class_finalize (EMemoShellBackendClass *class)
452 {
453 }
454
455 static void
456 e_memo_shell_backend_init (EMemoShellBackend *memo_shell_backend)
457 {
458 memo_shell_backend->priv =
459 E_MEMO_SHELL_BACKEND_GET_PRIVATE (memo_shell_backend);
460 }
461
462 void
463 e_memo_shell_backend_type_register (GTypeModule *type_module)
464 {
465 /* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
466 * function, so we have to wrap it with a public function in
467 * order to register types from a separate compilation unit. */
468 e_memo_shell_backend_register_type (type_module);
469 }