evolution-3.6.4/addressbook/gui/contact-editor/eab-editor.c

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 }