No issues found
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2 of the License, or (at your option) version 3.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with the program; if not, see <http://www.gnu.org/licenses/>
14 *
15 *
16 * Authors:
17 * Chris Toshok <toshok@ximian.com>
18 *
19 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
20 *
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <gtk/gtk.h>
28 #include <glib/gi18n.h>
29
30 #include "eab-editor.h"
31 #include "e-util/e-util.h"
32 #include "addressbook/gui/widgets/eab-gui-util.h"
33
34 #define EAB_EDITOR_GET_PRIVATE(obj) \
35 (G_TYPE_INSTANCE_GET_PRIVATE \
36 ((obj), EAB_TYPE_EDITOR, EABEditorPrivate))
37
38 struct _EABEditorPrivate {
39 EShell *shell;
40 };
41
42 enum {
43 PROP_0,
44 PROP_SHELL
45 };
46
47 enum {
48 CONTACT_ADDED,
49 CONTACT_MODIFIED,
50 CONTACT_DELETED,
51 EDITOR_CLOSED,
52 LAST_SIGNAL
53 };
54
55 static GSList *all_editors;
56 static guint signals[LAST_SIGNAL];
57
58 G_DEFINE_ABSTRACT_TYPE (EABEditor, eab_editor, G_TYPE_OBJECT)
59
60 static void
61 eab_editor_quit_requested_cb (EShell *shell,
62 EShellQuitReason reason,
63 EABEditor *editor)
64 {
65 GtkWindow *window;
66
67 /* Quit immediately if another Evolution process asked us to. */
68 if (reason == E_SHELL_QUIT_REMOTE_REQUEST)
69 return;
70
71 window = eab_editor_get_window (editor);
72
73 eab_editor_raise (editor);
74 if (!eab_editor_prompt_to_save_changes (editor, window))
75 e_shell_cancel_quit (shell);
76 }
77
78 static void
79 eab_editor_set_shell (EABEditor *editor,
80 EShell *shell)
81 {
82 g_return_if_fail (editor->priv->shell == NULL);
83 g_return_if_fail (E_IS_SHELL (shell));
84
85 editor->priv->shell = g_object_ref (shell);
86
87 g_signal_connect (
88 shell, "quit-requested",
89 G_CALLBACK (eab_editor_quit_requested_cb), editor);
90 }
91
92 static void
93 eab_editor_set_property (GObject *object,
94 guint property_id,
95 const GValue *value,
96 GParamSpec *pspec)
97 {
98 switch (property_id) {
99 case PROP_SHELL:
100 eab_editor_set_shell (
101 EAB_EDITOR (object),
102 g_value_get_object (value));
103 return;
104 }
105
106 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
107 }
108
109 static void
110 eab_editor_get_property (GObject *object,
111 guint property_id,
112 GValue *value,
113 GParamSpec *pspec)
114 {
115 switch (property_id) {
116 case PROP_SHELL:
117 g_value_set_object (
118 value, eab_editor_get_shell (
119 EAB_EDITOR (object)));
120 return;
121 }
122
123 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
124 }
125
126 static void
127 eab_editor_dispose (GObject *object)
128 {
129 EABEditorPrivate *priv;
130
131 priv = EAB_EDITOR_GET_PRIVATE (object);
132
133 if (priv->shell != NULL) {
134 g_signal_handlers_disconnect_matched (
135 priv->shell, G_SIGNAL_MATCH_DATA,
136 0, 0, NULL, NULL, object);
137 g_object_unref (priv->shell);
138 priv->shell = NULL;
139 }
140
141 /* Chain up to parent's dispose() method. */
142 G_OBJECT_CLASS (eab_editor_parent_class)->dispose (object);
143 }
144
145 static void
146 eab_editor_finalize (GObject *object)
147 {
148 all_editors = g_slist_remove (all_editors, object);
149
150 /* Chain up to parent's finalize() method. */
151 G_OBJECT_CLASS (eab_editor_parent_class)->finalize (object);
152 }
153
154 static void
155 eab_editor_class_init (EABEditorClass *class)
156 {
157 GObjectClass *object_class;
158
159 g_type_class_add_private (class, sizeof (EABEditorPrivate));
160
161 object_class = G_OBJECT_CLASS (class);
162 object_class->set_property = eab_editor_set_property;
163 object_class->get_property = eab_editor_get_property;
164 object_class->dispose = eab_editor_dispose;
165 object_class->finalize = eab_editor_finalize;
166
167 g_object_class_install_property (
168 object_class,
169 PROP_SHELL,
170 g_param_spec_object (
171 "shell",
172 "Shell",
173 "The EShell singleton",
174 E_TYPE_SHELL,
175 G_PARAM_READWRITE |
176 G_PARAM_CONSTRUCT_ONLY));
177
178 signals[CONTACT_ADDED] = g_signal_new (
179 "contact_added",
180 G_OBJECT_CLASS_TYPE (object_class),
181 G_SIGNAL_RUN_FIRST,
182 G_STRUCT_OFFSET (EABEditorClass, contact_added),
183 NULL, NULL,
184 e_marshal_NONE__POINTER_OBJECT,
185 G_TYPE_NONE, 2,
186 G_TYPE_POINTER,
187 G_TYPE_OBJECT);
188
189 signals[CONTACT_MODIFIED] = g_signal_new (
190 "contact_modified",
191 G_OBJECT_CLASS_TYPE (object_class),
192 G_SIGNAL_RUN_FIRST,
193 G_STRUCT_OFFSET (EABEditorClass, contact_modified),
194 NULL, NULL,
195 e_marshal_NONE__POINTER_OBJECT,
196 G_TYPE_NONE, 2,
197 G_TYPE_POINTER,
198 G_TYPE_OBJECT);
199
200 signals[CONTACT_DELETED] = g_signal_new (
201 "contact_deleted",
202 G_OBJECT_CLASS_TYPE (object_class),
203 G_SIGNAL_RUN_FIRST,
204 G_STRUCT_OFFSET (EABEditorClass, contact_deleted),
205 NULL, NULL,
206 e_marshal_NONE__POINTER_OBJECT,
207 G_TYPE_NONE, 2,
208 G_TYPE_POINTER,
209 G_TYPE_OBJECT);
210
211 signals[EDITOR_CLOSED] = g_signal_new (
212 "editor_closed",
213 G_OBJECT_CLASS_TYPE (object_class),
214 G_SIGNAL_RUN_FIRST,
215 G_STRUCT_OFFSET (EABEditorClass, editor_closed),
216 NULL, NULL,
217 g_cclosure_marshal_VOID__VOID,
218 G_TYPE_NONE, 0);
219 }
220
221 static void
222 eab_editor_init (EABEditor *editor)
223 {
224 editor->priv = EAB_EDITOR_GET_PRIVATE (editor);
225
226 all_editors = g_slist_prepend (all_editors, editor);
227 }
228
229 EShell *
230 eab_editor_get_shell (EABEditor *editor)
231 {
232 g_return_val_if_fail (EAB_IS_EDITOR (editor), NULL);
233
234 return E_SHELL (editor->priv->shell);
235 }
236
237 GSList *
238 eab_editor_get_all_editors (void)
239 {
240 return all_editors;
241 }
242
243 void
244 eab_editor_show (EABEditor *editor)
245 {
246 EABEditorClass *class;
247
248 g_return_if_fail (EAB_IS_EDITOR (editor));
249
250 class = EAB_EDITOR_GET_CLASS (editor);
251 g_return_if_fail (class->show != NULL);
252
253 class->show (editor);
254 }
255
256 void
257 eab_editor_close (EABEditor *editor)
258 {
259 EABEditorClass *class;
260
261 g_return_if_fail (EAB_IS_EDITOR (editor));
262
263 class = EAB_EDITOR_GET_CLASS (editor);
264 g_return_if_fail (class->close != NULL);
265
266 class->close (editor);
267 }
268
269 void
270 eab_editor_raise (EABEditor *editor)
271 {
272 EABEditorClass *class;
273
274 g_return_if_fail (EAB_IS_EDITOR (editor));
275
276 class = EAB_EDITOR_GET_CLASS (editor);
277 g_return_if_fail (class->raise != NULL);
278
279 class->raise (editor);
280 }
281
282 void
283 eab_editor_save_contact (EABEditor *editor,
284 gboolean should_close)
285 {
286 EABEditorClass *class;
287
288 g_return_if_fail (EAB_IS_EDITOR (editor));
289
290 class = EAB_EDITOR_GET_CLASS (editor);
291 g_return_if_fail (class->save_contact != NULL);
292
293 class->save_contact (editor, should_close);
294 }
295
296 gboolean
297 eab_editor_is_changed (EABEditor *editor)
298 {
299 EABEditorClass *class;
300
301 g_return_val_if_fail (EAB_IS_EDITOR (editor), FALSE);
302
303 class = EAB_EDITOR_GET_CLASS (editor);
304 g_return_val_if_fail (class->is_changed != NULL, FALSE);
305
306 return class->is_changed (editor);
307 }
308
309 gboolean
310 eab_editor_is_valid (EABEditor *editor)
311 {
312 EABEditorClass *class;
313
314 g_return_val_if_fail (EAB_IS_EDITOR (editor), FALSE);
315
316 class = EAB_EDITOR_GET_CLASS (editor);
317 g_return_val_if_fail (class->is_valid != NULL, FALSE);
318
319 return class->is_valid (editor);
320 }
321
322 GtkWindow *
323 eab_editor_get_window (EABEditor *editor)
324 {
325 EABEditorClass *class;
326
327 g_return_val_if_fail (EAB_IS_EDITOR (editor), NULL);
328
329 class = EAB_EDITOR_GET_CLASS (editor);
330 g_return_val_if_fail (class->get_window != NULL, NULL);
331
332 return class->get_window (editor);
333 }
334
335 /* This function prompts for saving if editor conents are in changed state and
336 * save or discards or cancels (just returns with out doing anything) according
337 * to user input. Editor gets destroyed in case of save and discard case. */
338
339 gboolean
340 eab_editor_prompt_to_save_changes (EABEditor *editor,
341 GtkWindow *window)
342 {
343 if (!eab_editor_is_changed (editor)) {
344 eab_editor_close (EAB_EDITOR (editor));
345 return TRUE;
346 }
347
348 switch (eab_prompt_save_dialog (window)) {
349 case GTK_RESPONSE_YES:
350 if (!eab_editor_is_valid (editor)) {
351 return FALSE;
352 }
353 eab_editor_save_contact (editor, TRUE);
354 return TRUE;
355 case GTK_RESPONSE_NO:
356 eab_editor_close (EAB_EDITOR (editor));
357 return TRUE;
358 case GTK_RESPONSE_CANCEL:
359 default:
360 return FALSE;
361 }
362 }
363
364 void
365 eab_editor_contact_added (EABEditor *editor,
366 const GError *error,
367 EContact *contact)
368 {
369 g_return_if_fail (EAB_IS_EDITOR (editor));
370 g_return_if_fail (E_IS_CONTACT (contact));
371
372 g_signal_emit (editor, signals[CONTACT_ADDED], 0, error, contact);
373 }
374
375 void
376 eab_editor_contact_modified (EABEditor *editor,
377 const GError *error,
378 EContact *contact)
379 {
380 g_return_if_fail (EAB_IS_EDITOR (editor));
381 g_return_if_fail (E_IS_CONTACT (contact));
382
383 g_signal_emit (editor, signals[CONTACT_MODIFIED], 0, error, contact);
384 }
385
386 void
387 eab_editor_contact_deleted (EABEditor *editor,
388 const GError *error,
389 EContact *contact)
390 {
391 g_return_if_fail (EAB_IS_EDITOR (editor));
392 g_return_if_fail (E_IS_CONTACT (contact));
393
394 g_signal_emit (editor, signals[CONTACT_DELETED], 0, error, contact);
395 }
396
397 void
398 eab_editor_closed (EABEditor *editor)
399 {
400 g_return_if_fail (EAB_IS_EDITOR (editor));
401
402 g_signal_emit (editor, signals[EDITOR_CLOSED], 0);
403 }