evolution-3.6.4/addressbook/gui/widgets/eab-contact-display.c

Location Tool Test ID Function Issue
eab-contact-display.c:402:0 cppcheck uninitvar Uninitialized variable: address
eab-contact-display.c:402:0 cppcheck uninitvar Uninitialized variable: address
  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 "eab-contact-display.h"
 28 #include "eab-contact-formatter.h"
 29 
 30 #include "eab-gui-util.h"
 31 #include "e-util/e-util.h"
 32 #include "e-util/e-util-private.h"
 33 #include "e-util/e-html-utils.h"
 34 #include "e-util/e-icon-factory.h"
 35 #include "e-util/e-plugin-ui.h"
 36 #include "e-util/e-file-request.h"
 37 #include "e-util/e-stock-request.h"
 38 
 39 #include <webkit/webkit.h>
 40 
 41 #ifdef WITH_CONTACT_MAPS
 42 #include "widgets/misc/e-contact-map.h"
 43 #endif
 44 
 45 #include <string.h>
 46 #include <glib/gi18n.h>
 47 
 48 #define EAB_CONTACT_DISPLAY_GET_PRIVATE(obj) \
 49 	(G_TYPE_INSTANCE_GET_PRIVATE \
 50 	((obj), EAB_TYPE_CONTACT_DISPLAY, EABContactDisplayPrivate))
 51 
 52 #define TEXT_IS_RIGHT_TO_LEFT \
 53 	(gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
 54 
 55 struct _EABContactDisplayPrivate {
 56 	EContact *contact;
 57 
 58 	EABContactDisplayMode mode;
 59 	gboolean show_maps;
 60 
 61 	GCancellable *formatter_cancellable;
 62 };
 63 
 64 enum {
 65 	PROP_0,
 66 	PROP_CONTACT,
 67 	PROP_MODE,
 68 	PROP_SHOW_MAPS
 69 };
 70 
 71 enum {
 72 	SEND_MESSAGE,
 73 	LAST_SIGNAL
 74 };
 75 
 76 static const gchar *ui =
 77 "<ui>"
 78 "  <popup name='context'>"
 79 "    <placeholder name='custom-actions-1'>"
 80 "      <menuitem action='contact-send-message'/>"
 81 "    </placeholder>"
 82 "    <placeholder name='custom-actions-2'>"
 83 "      <menuitem action='contact-mailto-copy'/>"
 84 "    </placeholder>"
 85 "  </popup>"
 86 "</ui>";
 87 
 88 static guint signals[LAST_SIGNAL];
 89 
 90 G_DEFINE_TYPE (
 91 	EABContactDisplay,
 92 	eab_contact_display,
 93 	E_TYPE_WEB_VIEW)
 94 
 95 static void
 96 contact_display_emit_send_message (EABContactDisplay *display,
 97                                    gint email_num)
 98 {
 99 	EDestination *destination;
100 	EContact *contact;
101 
102 	g_return_if_fail (email_num >= 0);
103 
104 	destination = e_destination_new ();
105 	contact = eab_contact_display_get_contact (display);
106 	e_destination_set_contact (destination, contact, email_num);
107 	g_signal_emit (display, signals[SEND_MESSAGE], 0, destination);
108 	g_object_unref (destination);
109 }
110 
111 static void
112 action_contact_mailto_copy_cb (GtkAction *action,
113                                EABContactDisplay *display)
114 {
115 	GtkClipboard *clipboard;
116 	EWebView *web_view;
117 	EContact *contact;
118 	GList *list;
119 	const gchar *text;
120 	const gchar *uri;
121 	gint index;
122 
123 	web_view = E_WEB_VIEW (display);
124 	uri = e_web_view_get_selected_uri (web_view);
125 	g_return_if_fail (uri != NULL);
126 
127 	index = atoi (uri + strlen ("internal-mailto:"));
128 	g_return_if_fail (index >= 0);
129 
130 	contact = eab_contact_display_get_contact (display);
131 	list = e_contact_get (contact, E_CONTACT_EMAIL);
132 	text = g_list_nth_data (list, index);
133 
134 	clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
135 	gtk_clipboard_set_text (clipboard, text, -1);
136 	gtk_clipboard_store (clipboard);
137 
138 	g_list_foreach (list, (GFunc) g_free, NULL);
139 	g_list_free (list);
140 }
141 
142 static void
143 action_contact_send_message_cb (GtkAction *action,
144                                 EABContactDisplay *display)
145 {
146 	EWebView *web_view;
147 	const gchar *uri;
148 	gint index;
149 
150 	web_view = E_WEB_VIEW (display);
151 	uri = e_web_view_get_selected_uri (web_view);
152 	g_return_if_fail (uri != NULL);
153 
154 	index = atoi (uri + strlen ("internal-mailto:"));
155 	contact_display_emit_send_message (display, index);
156 }
157 
158 static GtkActionEntry internal_mailto_entries[] = {
159 
160 	{ "contact-mailto-copy",
161 	  GTK_STOCK_COPY,
162 	  N_("Copy _Email Address"),
163 	  NULL,
164 	  N_("Copy the email address to the clipboard"),
165 	  G_CALLBACK (action_contact_mailto_copy_cb) },
166 
167 	{ "contact-send-message",
168 	  "mail-message-new",
169 	  N_("_Send New Message To..."),
170 	  NULL,
171 	  N_("Send a mail message to this address"),
172 	  G_CALLBACK (action_contact_send_message_cb) }
173 };
174 
175 static void
176 contact_formatting_finished (GObject *object,
177                              GSimpleAsyncResult *result,
178                              gpointer user_data)
179 {
180 	EABContactDisplay *display = user_data;
181 	CamelStreamMem *stream;
182 	gchar *html;
183 	GByteArray *ba;
184 
185 	stream = g_simple_async_result_get_op_res_gpointer (result);
186 	/* The operation was probably cancelled */
187 	if (!stream)
188 		return;
189 
190 	ba = camel_stream_mem_get_byte_array (stream);
191 
192 	html = g_strndup ((gchar *) ba->data, ba->len);
193 	e_web_view_load_string (E_WEB_VIEW (display), html);
194 
195 	g_free (html);
196 	g_object_unref (stream);
197 	g_object_unref (object);
198 	g_clear_object (&display->priv->formatter_cancellable);
199 }
200 
201 static void
202 load_contact (EABContactDisplay *display)
203 {
204 	EABContactFormatter *formatter;
205 
206 	if (display->priv->formatter_cancellable) {
207 		g_cancellable_cancel (display->priv->formatter_cancellable);
208 		g_clear_object (&display->priv->formatter_cancellable);
209 	}
210 
211 	if (!display->priv->contact) {
212 		e_web_view_clear (E_WEB_VIEW (display));
213 		return;
214 	}
215 
216 	formatter = eab_contact_formatter_new (
217 			display->priv->mode,
218 			display->priv->show_maps);
219 	g_object_set (
220 		G_OBJECT (formatter),
221 		"style", gtk_widget_get_style (GTK_WIDGET (display)),
222 		"state", gtk_widget_get_state (GTK_WIDGET (display)),
223 		NULL);
224 
225 	display->priv->formatter_cancellable = g_cancellable_new ();
226 
227 	eab_contact_formatter_format_contact_async (
228 		formatter, display->priv->contact,
229 		display->priv->formatter_cancellable,
230 		(GAsyncReadyCallback) contact_formatting_finished,
231 		display);
232 }
233 
234 static void
235 contact_display_set_property (GObject *object,
236                               guint property_id,
237                               const GValue *value,
238                               GParamSpec *pspec)
239 {
240 	switch (property_id) {
241 		case PROP_CONTACT:
242 			eab_contact_display_set_contact (
243 				EAB_CONTACT_DISPLAY (object),
244 				g_value_get_object (value));
245 			return;
246 
247 		case PROP_MODE:
248 			eab_contact_display_set_mode (
249 				EAB_CONTACT_DISPLAY (object),
250 				g_value_get_int (value));
251 			return;
252 
253 		case PROP_SHOW_MAPS:
254 			eab_contact_display_set_show_maps (
255 				EAB_CONTACT_DISPLAY (object),
256 				g_value_get_boolean (value));
257 			return;
258 	}
259 
260 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
261 }
262 
263 static void
264 contact_display_get_property (GObject *object,
265                               guint property_id,
266                               GValue *value,
267                               GParamSpec *pspec)
268 {
269 	switch (property_id) {
270 		case PROP_CONTACT:
271 			g_value_set_object (
272 				value, eab_contact_display_get_contact (
273 				EAB_CONTACT_DISPLAY (object)));
274 			return;
275 
276 		case PROP_MODE:
277 			g_value_set_int (
278 				value, eab_contact_display_get_mode (
279 				EAB_CONTACT_DISPLAY (object)));
280 			return;
281 
282 		case PROP_SHOW_MAPS:
283 			g_value_set_boolean (
284 				value, eab_contact_display_get_show_maps (
285 				EAB_CONTACT_DISPLAY (object)));
286 			return;
287 	}
288 
289 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
290 }
291 
292 static void
293 contact_display_dispose (GObject *object)
294 {
295 	EABContactDisplayPrivate *priv;
296 
297 	priv = EAB_CONTACT_DISPLAY_GET_PRIVATE (object);
298 
299 	if (priv->contact != NULL) {
300 		g_object_unref (priv->contact);
301 		priv->contact = NULL;
302 	}
303 
304 	/* Chain up to parent's dispose() method. */
305 	G_OBJECT_CLASS (eab_contact_display_parent_class)->dispose (object);
306 }
307 
308 static void
309 contact_display_hovering_over_link (EWebView *web_view,
310                                     const gchar *title,
311                                     const gchar *uri)
312 {
313 	EWebViewClass *web_view_class;
314 	EABContactDisplay *display;
315 	EContact *contact;
316 	const gchar *name;
317 	gchar *message;
318 
319 	if (uri == NULL || *uri == '\0')
320 		goto chainup;
321 
322 	if (!g_str_has_prefix (uri, "internal-mailto:"))
323 		goto chainup;
324 
325 	display = EAB_CONTACT_DISPLAY (web_view);
326 	contact = eab_contact_display_get_contact (display);
327 
328 	name = e_contact_get_const (contact, E_CONTACT_FILE_AS);
329 	if (name == NULL)
330 		e_contact_get_const (contact, E_CONTACT_FULL_NAME);
331 	g_return_if_fail (name != NULL);
332 
333 	message = g_strdup_printf (_("Click to mail %s"), name);
334 	e_web_view_status_message (web_view, message);
335 	g_free (message);
336 
337 	return;
338 
339 chainup:
340 	/* Chain up to parent's hovering_over_link() method. */
341 	web_view_class = E_WEB_VIEW_CLASS (eab_contact_display_parent_class);
342 	web_view_class->hovering_over_link (web_view, title, uri);
343 }
344 
345 static void
346 contact_display_link_clicked (EWebView *web_view,
347                               const gchar *uri)
348 {
349 	EABContactDisplay *display;
350 	gsize length;
351 
352 	display = EAB_CONTACT_DISPLAY (web_view);
353 
354 	length = strlen ("internal-mailto:");
355 	if (g_ascii_strncasecmp (uri, "internal-mailto:", length) == 0) {
356 		gint index;
357 
358 		index = atoi (uri + length);
359 		contact_display_emit_send_message (display, index);
360 		return;
361 	}
362 
363 	/* Chain up to parent's link_clicked() method. */
364 	E_WEB_VIEW_CLASS (eab_contact_display_parent_class)->
365 		link_clicked (web_view, uri);
366 }
367 
368 #ifdef WITH_CONTACT_MAPS
369 /* XXX Clutter event handling workaround. Clutter-gtk propagates events down
370  *     to parent widgets.  In this case it leads to GtkHTML scrolling up and
371  *     down while user's trying to zoom in the champlain widget. This
372  *     workaround stops the propagation from map widget down to GtkHTML. */
373 static gboolean
374 handle_map_scroll_event (GtkWidget *widget,
375                          GdkEvent *event)
376 {
377 	return TRUE;
378 }
379 
380 static GtkWidget *
381 contact_display_object_requested (WebKitWebView *web_view,
382                                   gchar *mime_type,
383                                   gchar *uri,
384                                   GHashTable *param,
385                                   EABContactDisplay *display)
386 {
387 	EContact *contact = display->priv->contact;
388 	const gchar *name = e_contact_get_const (contact, E_CONTACT_FILE_AS);
389 	const gchar *contact_uid = e_contact_get_const (contact, E_CONTACT_UID);
390 	gchar *full_name;
391 	EContactAddress *address;
392 	GtkWidget *map = NULL;
393 
394 	if (strstr (mime_type, "work") != NULL) {
395 		address = e_contact_get (contact, E_CONTACT_ADDRESS_WORK);
396 		full_name = g_strconcat (name, " (", _("Work"), ")", NULL);
397 	} else if (strstr (mime_type, "home") != NULL) {
398 		address = e_contact_get (contact, E_CONTACT_ADDRESS_HOME);
399 		full_name = g_strconcat (name, " (", _("Home"), ")", NULL);
400 	}
401 
402 	if (address) {
Uninitialized variable: address
(emitted by cppcheck)
Uninitialized variable: address
(emitted by cppcheck)
403 map = e_contact_map_new (); 404 gtk_widget_set_size_request (map, 250, 250); 405 g_signal_connect ( 406 E_CONTACT_MAP (map), "contact-added", 407 G_CALLBACK (e_contact_map_zoom_on_marker), NULL); 408 g_signal_connect_swapped ( 409 E_CONTACT_MAP (map), "contact-added", 410 G_CALLBACK (gtk_widget_show_all), map); 411 g_signal_connect ( 412 GTK_CHAMPLAIN_EMBED (map), "scroll-event", 413 G_CALLBACK (handle_map_scroll_event), NULL); 414 415 /* No need to display photo in contact preview. */ 416 e_contact_map_add_marker ( 417 E_CONTACT_MAP (map), full_name, 418 contact_uid, address, NULL); 419 420 gtk_widget_show_all (map); 421 422 e_contact_address_free (address); 423 } 424 425 g_free (full_name); 426 427 return map; 428 } 429 #endif 430 431 static void 432 contact_display_load_status_changed (WebKitWebView *web_view, 433 GParamSpec *pspec, 434 gpointer user_data) 435 { 436 WebKitLoadStatus load_status; 437 WebKitDOMDocument *document; 438 439 load_status = webkit_web_view_get_load_status (web_view); 440 if (load_status != WEBKIT_LOAD_FINISHED) 441 return; 442 443 document = webkit_web_view_get_dom_document (web_view); 444 eab_contact_formatter_bind_dom (document); 445 } 446 447 static void 448 contact_display_update_actions (EWebView *web_view, 449 GdkEventButton *event) 450 { 451 GtkActionGroup *action_group; 452 gboolean scheme_is_internal_mailto; 453 gboolean visible; 454 const gchar *group_name; 455 const gchar *uri; 456 457 /* Chain up to parent's update_actions() method. */ 458 E_WEB_VIEW_CLASS (eab_contact_display_parent_class)-> 459 update_actions (web_view, event); 460 461 uri = e_web_view_get_selected_uri (web_view); 462 463 scheme_is_internal_mailto = (uri == NULL) ? FALSE : 464 (g_ascii_strncasecmp (uri, "internal-mailto:", 16) == 0); 465 466 /* Override how EWebView treats internal-mailto URIs. */ 467 group_name = "uri"; 468 action_group = e_web_view_get_action_group (web_view, group_name); 469 visible = gtk_action_group_get_visible (action_group); 470 visible &= !scheme_is_internal_mailto; 471 gtk_action_group_set_visible (action_group, visible); 472 473 group_name = "internal-mailto"; 474 visible = scheme_is_internal_mailto; 475 action_group = e_web_view_get_action_group (web_view, group_name); 476 gtk_action_group_set_visible (action_group, visible); 477 } 478 479 static void 480 eab_contact_display_class_init (EABContactDisplayClass *class) 481 { 482 GObjectClass *object_class; 483 EWebViewClass *web_view_class; 484 485 g_type_class_add_private (class, sizeof (EABContactDisplayPrivate)); 486 487 object_class = G_OBJECT_CLASS (class); 488 object_class->set_property = contact_display_set_property; 489 object_class->get_property = contact_display_get_property; 490 object_class->dispose = contact_display_dispose; 491 492 web_view_class = E_WEB_VIEW_CLASS (class); 493 web_view_class->hovering_over_link = contact_display_hovering_over_link; 494 web_view_class->link_clicked = contact_display_link_clicked; 495 web_view_class->update_actions = contact_display_update_actions; 496 497 g_object_class_install_property ( 498 object_class, 499 PROP_CONTACT, 500 g_param_spec_object ( 501 "contact", 502 NULL, 503 NULL, 504 E_TYPE_CONTACT, 505 G_PARAM_READWRITE)); 506 507 /* XXX Make this a real enum property. */ 508 g_object_class_install_property ( 509 object_class, 510 PROP_MODE, 511 g_param_spec_int ( 512 "mode", 513 NULL, 514 NULL, 515 EAB_CONTACT_DISPLAY_RENDER_NORMAL, 516 EAB_CONTACT_DISPLAY_RENDER_COMPACT, 517 EAB_CONTACT_DISPLAY_RENDER_NORMAL, 518 G_PARAM_READWRITE)); 519 520 g_object_class_install_property ( 521 object_class, 522 PROP_SHOW_MAPS, 523 g_param_spec_boolean ( 524 "show-maps", 525 NULL, 526 NULL, 527 FALSE, 528 G_PARAM_READWRITE)); 529 530 signals[SEND_MESSAGE] = g_signal_new ( 531 "send-message", 532 G_OBJECT_CLASS_TYPE (class), 533 G_SIGNAL_RUN_FIRST, 534 G_STRUCT_OFFSET (EABContactDisplayClass, send_message), 535 NULL, NULL, 536 g_cclosure_marshal_VOID__OBJECT, 537 G_TYPE_NONE, 1, 538 E_TYPE_DESTINATION); 539 } 540 541 static void 542 eab_contact_display_init (EABContactDisplay *display) 543 { 544 EWebView *web_view; 545 GtkUIManager *ui_manager; 546 GtkActionGroup *action_group; 547 const gchar *domain = GETTEXT_PACKAGE; 548 GError *error = NULL; 549 550 display->priv = EAB_CONTACT_DISPLAY_GET_PRIVATE (display); 551 552 web_view = E_WEB_VIEW (display); 553 ui_manager = e_web_view_get_ui_manager (web_view); 554 555 #ifdef WITH_CONTACT_MAPS 556 g_signal_connect ( 557 web_view, "create-plugin-widget", 558 G_CALLBACK (contact_display_object_requested), display); 559 #endif 560 g_signal_connect ( 561 web_view, "notify::load-status", 562 G_CALLBACK (contact_display_load_status_changed), NULL); 563 g_signal_connect ( 564 web_view, "style-set", 565 G_CALLBACK (load_contact), NULL); 566 567 e_web_view_install_request_handler (E_WEB_VIEW (display), E_TYPE_FILE_REQUEST); 568 e_web_view_install_request_handler (E_WEB_VIEW (display), E_TYPE_STOCK_REQUEST); 569 570 action_group = gtk_action_group_new ("internal-mailto"); 571 gtk_action_group_set_translation_domain (action_group, domain); 572 gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); 573 g_object_unref (action_group); 574 575 gtk_action_group_add_actions ( 576 action_group, internal_mailto_entries, 577 G_N_ELEMENTS (internal_mailto_entries), display); 578 579 /* Because we are loading from a hard-coded string, there is 580 * no chance of I/O errors. Failure here implies a malformed 581 * UI definition. Full stop. */ 582 gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); 583 if (error != NULL) 584 g_error ("%s", error->message); 585 } 586 587 GtkWidget * 588 eab_contact_display_new (void) 589 { 590 return g_object_new (EAB_TYPE_CONTACT_DISPLAY, NULL); 591 } 592 593 EContact * 594 eab_contact_display_get_contact (EABContactDisplay *display) 595 { 596 g_return_val_if_fail (EAB_IS_CONTACT_DISPLAY (display), NULL); 597 598 return display->priv->contact; 599 } 600 601 void 602 eab_contact_display_set_contact (EABContactDisplay *display, 603 EContact *contact) 604 { 605 g_return_if_fail (EAB_IS_CONTACT_DISPLAY (display)); 606 607 if (display->priv->contact == contact) 608 return; 609 610 if (contact != NULL) 611 g_object_ref (contact); 612 613 if (display->priv->contact != NULL) 614 g_object_unref (display->priv->contact); 615 616 display->priv->contact = contact; 617 618 load_contact (display); 619 620 g_object_notify (G_OBJECT (display), "contact"); 621 } 622 623 EABContactDisplayMode 624 eab_contact_display_get_mode (EABContactDisplay *display) 625 { 626 g_return_val_if_fail (EAB_IS_CONTACT_DISPLAY (display), 0); 627 628 return display->priv->mode; 629 } 630 631 void 632 eab_contact_display_set_mode (EABContactDisplay *display, 633 EABContactDisplayMode mode) 634 { 635 g_return_if_fail (EAB_IS_CONTACT_DISPLAY (display)); 636 637 if (display->priv->mode == mode) 638 return; 639 640 display->priv->mode = mode; 641 642 load_contact (display); 643 644 g_object_notify (G_OBJECT (display), "mode"); 645 } 646 647 gboolean 648 eab_contact_display_get_show_maps (EABContactDisplay *display) 649 { 650 g_return_val_if_fail (EAB_IS_CONTACT_DISPLAY (display), FALSE); 651 652 return display->priv->show_maps; 653 } 654 655 void 656 eab_contact_display_set_show_maps (EABContactDisplay *display, 657 gboolean show_maps) 658 { 659 g_return_if_fail (EAB_IS_CONTACT_DISPLAY (display)); 660 661 if (display->priv->show_maps == show_maps) 662 return; 663 664 display->priv->show_maps = show_maps; 665 666 load_contact (display); 667 668 g_object_notify (G_OBJECT (display), "show-maps"); 669 }