No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | e-minicard.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None | |
clang-analyzer | no-output-found | e-minicard.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
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 Lahey <clahey@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 <string.h>
28 #include <gdk/gdkkeysyms.h>
29 #include <glib/gi18n.h>
30 #include <libgnomecanvas/libgnomecanvas.h>
31 #include <text/e-text.h>
32 #include <e-util/e-util.h>
33 #include <misc/e-canvas-utils.h>
34 #include <misc/e-canvas.h>
35 #include "eab-gui-util.h"
36 #include "e-minicard.h"
37 #include "e-minicard-label.h"
38 #include "e-minicard-view.h"
39 #include <e-util/e-html-utils.h>
40 #include <e-util/e-icon-factory.h>
41 #include "ea-addressbook.h"
42
43 static void e_minicard_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
44 static void e_minicard_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
45 static void e_minicard_dispose (GObject *object);
46 static void e_minicard_finalize (GObject *object);
47 static gboolean e_minicard_event (GnomeCanvasItem *item, GdkEvent *event);
48 static void e_minicard_realize (GnomeCanvasItem *item);
49 static void e_minicard_reflow (GnomeCanvasItem *item, gint flags);
50 static void e_minicard_style_set (EMinicard *minicard, GtkStyle *previous_style);
51
52 static void e_minicard_resize_children (EMinicard *e_minicard);
53 static void remodel (EMinicard *e_minicard);
54
55 static gint e_minicard_drag_begin (EMinicard *minicard, GdkEvent *event);
56
57 #define d(x)
58
59 #define LIST_ICON_NAME "stock_contact-list"
60
61 static void
62 e_minicard_field_destroy (EMinicardField *field)
63 {
64 g_object_run_dispose (G_OBJECT (field->label));
65 g_free (field);
66 }
67
68 enum {
69 PROP_0,
70 PROP_WIDTH,
71 PROP_HEIGHT,
72 PROP_HAS_FOCUS,
73 PROP_SELECTED,
74 PROP_HAS_CURSOR,
75 PROP_EDITABLE,
76 PROP_CONTACT
77 };
78
79 enum {
80 SELECTED,
81 DRAG_BEGIN,
82 OPEN_CONTACT,
83 STYLE_SET,
84 LAST_SIGNAL
85 };
86
87 static struct {
88 const gchar *name;
89 const gchar *pretty_name;
90 }
91 common_location[] =
92 {
93 { "WORK", N_ ("Work Email") },
94 { "HOME", N_ ("Home Email") },
95 { "OTHER", N_ ("Other Email") }
96 };
97
98 static guint signals[LAST_SIGNAL] = {0, };
99
100 G_DEFINE_TYPE (EMinicard, e_minicard, GNOME_TYPE_CANVAS_GROUP)
101
102 static void
103 e_minicard_class_init (EMinicardClass *class)
104 {
105 GObjectClass *object_class;
106 GnomeCanvasItemClass *item_class;
107
108 object_class = G_OBJECT_CLASS (class);
109 object_class->set_property = e_minicard_set_property;
110 object_class->get_property = e_minicard_get_property;
111 object_class->dispose = e_minicard_dispose;
112 object_class->finalize = e_minicard_finalize;
113
114 item_class = GNOME_CANVAS_ITEM_CLASS (class);
115 item_class->realize = e_minicard_realize;
116 item_class->event = e_minicard_event;
117
118 class->style_set = e_minicard_style_set;
119 class->selected = NULL;
120
121 g_object_class_install_property (
122 object_class,
123 PROP_WIDTH,
124 g_param_spec_double (
125 "width",
126 "Width",
127 NULL,
128 0.0, G_MAXDOUBLE, 10.0,
129 G_PARAM_READWRITE));
130
131 g_object_class_install_property (
132 object_class,
133 PROP_HEIGHT,
134 g_param_spec_double (
135 "height",
136 "Height",
137 NULL,
138 0.0, G_MAXDOUBLE, 10.0,
139 G_PARAM_READABLE));
140
141 g_object_class_install_property (
142 object_class,
143 PROP_HAS_FOCUS,
144 /* XXX should be _enum */
145 g_param_spec_int (
146 "has_focus",
147 "Has Focus",
148 NULL,
149 E_MINICARD_FOCUS_TYPE_START,
150 E_MINICARD_FOCUS_TYPE_END,
151 E_MINICARD_FOCUS_TYPE_START,
152 G_PARAM_READWRITE));
153
154 g_object_class_install_property (
155 object_class,
156 PROP_SELECTED,
157 g_param_spec_boolean (
158 "selected",
159 "Selected",
160 NULL,
161 FALSE,
162 G_PARAM_READWRITE));
163
164 g_object_class_install_property (
165 object_class,
166 PROP_HAS_CURSOR,
167 g_param_spec_boolean (
168 "has_cursor",
169 "Has Cursor",
170 NULL,
171 FALSE,
172 G_PARAM_READWRITE));
173
174 g_object_class_install_property (
175 object_class,
176 PROP_EDITABLE,
177 g_param_spec_boolean (
178 "editable",
179 "Editable",
180 NULL,
181 FALSE,
182 G_PARAM_READWRITE));
183
184 g_object_class_install_property (
185 object_class,
186 PROP_CONTACT,
187 g_param_spec_object (
188 "contact",
189 "Contact",
190 NULL,
191 E_TYPE_CONTACT,
192 G_PARAM_READWRITE));
193
194 signals[SELECTED] = g_signal_new (
195 "selected",
196 G_OBJECT_CLASS_TYPE (object_class),
197 G_SIGNAL_RUN_LAST,
198 G_STRUCT_OFFSET (EMinicardClass, selected),
199 NULL, NULL,
200 e_marshal_INT__POINTER,
201 G_TYPE_INT, 1,
202 G_TYPE_POINTER);
203
204 signals[DRAG_BEGIN] = g_signal_new (
205 "drag_begin",
206 G_OBJECT_CLASS_TYPE (object_class),
207 G_SIGNAL_RUN_LAST,
208 G_STRUCT_OFFSET (EMinicardClass, drag_begin),
209 NULL, NULL,
210 e_marshal_INT__POINTER,
211 G_TYPE_INT, 1,
212 G_TYPE_POINTER);
213
214 signals[OPEN_CONTACT] = g_signal_new (
215 "open-contact",
216 G_OBJECT_CLASS_TYPE (object_class),
217 G_SIGNAL_RUN_LAST,
218 G_STRUCT_OFFSET (EMinicardClass, open_contact),
219 NULL, NULL,
220 g_cclosure_marshal_VOID__OBJECT,
221 G_TYPE_NONE, 1,
222 E_TYPE_CONTACT);
223
224 signals[STYLE_SET] = g_signal_new (
225 "style_set",
226 G_TYPE_FROM_CLASS (object_class),
227 G_SIGNAL_RUN_FIRST,
228 G_STRUCT_OFFSET (EMinicardClass, style_set),
229 NULL, NULL,
230 g_cclosure_marshal_VOID__OBJECT,
231 G_TYPE_NONE, 1,
232 GTK_TYPE_STYLE);
233
234 /* init the accessibility support for e_minicard */
235 e_minicard_a11y_init ();
236 }
237
238 static void
239 e_minicard_init (EMinicard *minicard)
240 {
241 minicard->rect = NULL;
242 minicard->fields = NULL;
243 minicard->width = 10;
244 minicard->height = 10;
245 minicard->has_focus = FALSE;
246 minicard->selected = FALSE;
247 minicard->editable = FALSE;
248 minicard->has_cursor = FALSE;
249
250 minicard->contact = NULL;
251
252 minicard->list_icon_pixbuf = e_icon_factory_get_icon (LIST_ICON_NAME, GTK_ICON_SIZE_MENU);
253 minicard->list_icon_size = gdk_pixbuf_get_height (minicard->list_icon_pixbuf);
254
255 minicard->changed = FALSE;
256
257 e_canvas_item_set_reflow_callback (GNOME_CANVAS_ITEM (minicard), e_minicard_reflow);
258 }
259
260 static void
261 set_selected (EMinicard *minicard,
262 gboolean selected)
263 {
264 GnomeCanvas *canvas;
265 GtkStyle *style;
266
267 canvas = GNOME_CANVAS_ITEM (minicard)->canvas;
268 style = gtk_widget_get_style (GTK_WIDGET (canvas));
269
270 if (selected) {
271 gnome_canvas_item_set (
272 minicard->rect,
273 "outline_color_gdk", &style->bg[GTK_STATE_ACTIVE],
274 NULL);
275 gnome_canvas_item_set (
276 minicard->header_rect,
277 "fill_color_gdk", &style->bg[GTK_STATE_SELECTED],
278 NULL);
279 gnome_canvas_item_set (
280 minicard->header_text,
281 "fill_color_gdk", &style->text[GTK_STATE_SELECTED],
282 NULL);
283 } else {
284 gnome_canvas_item_set (
285 minicard->rect,
286 "outline_color", NULL,
287 NULL);
288 gnome_canvas_item_set (
289 minicard->header_rect,
290 "fill_color_gdk", &style->bg[GTK_STATE_NORMAL],
291 NULL);
292 gnome_canvas_item_set (
293 minicard->header_text,
294 "fill_color_gdk", &style->text[GTK_STATE_NORMAL],
295 NULL);
296 }
297 minicard->selected = selected;
298 }
299
300 static void
301 set_has_cursor (EMinicard *minicard,
302 gboolean has_cursor)
303 {
304 if (!minicard->has_focus && has_cursor)
305 e_canvas_item_grab_focus (GNOME_CANVAS_ITEM (minicard), FALSE);
306 minicard->has_cursor = has_cursor;
307 }
308
309 static void
310 e_minicard_set_property (GObject *object,
311 guint property_id,
312 const GValue *value,
313 GParamSpec *pspec)
314 {
315 GnomeCanvasItem *item;
316 EMinicard *e_minicard;
317 EContact *contact;
318 GList *l;
319
320 item = GNOME_CANVAS_ITEM (object);
321 e_minicard = E_MINICARD (object);
322
323 switch (property_id) {
324 case PROP_WIDTH:
325 if (e_minicard->width != g_value_get_double (value)) {
326 e_minicard->width = g_value_get_double (value);
327 e_minicard_resize_children (e_minicard);
328 if (item->flags & GNOME_CANVAS_ITEM_REALIZED)
329 e_canvas_item_request_reflow (item);
330 }
331 break;
332 case PROP_HAS_FOCUS:
333 if (e_minicard->fields) {
334 if (g_value_get_int (value) == E_FOCUS_START ||
335 g_value_get_int (value) == E_FOCUS_CURRENT) {
336 gnome_canvas_item_set (
337 E_MINICARD_FIELD (e_minicard->fields->data)->label,
338 "has_focus", g_value_get_int (value),
339 NULL);
340 } else if (g_value_get_int (value) == E_FOCUS_END) {
341 gnome_canvas_item_set (
342 E_MINICARD_FIELD (g_list_last (e_minicard->fields)->data)->label,
343 "has_focus", g_value_get_int (value),
344 NULL);
345 }
346 }
347 else {
348 if (!e_minicard->has_focus)
349 e_canvas_item_grab_focus (item, FALSE);
350 }
351 break;
352 case PROP_SELECTED:
353 if (e_minicard->selected != g_value_get_boolean (value))
354 set_selected (e_minicard, g_value_get_boolean (value));
355 break;
356 case PROP_EDITABLE:
357 e_minicard->editable = g_value_get_boolean (value);
358 for (l = e_minicard->fields; l; l = l->next) {
359 g_object_set (
360 E_MINICARD_FIELD (l->data)->label,
361 "editable", FALSE /* e_minicard->editable */,
362 NULL);
363 }
364 break;
365 case PROP_HAS_CURSOR:
366 d (g_print ("%s: PROP_HAS_CURSOR\n", G_STRFUNC));
367 if (e_minicard->has_cursor != g_value_get_boolean (value))
368 set_has_cursor (e_minicard, g_value_get_boolean (value));
369 break;
370 case PROP_CONTACT:
371 contact = E_CONTACT (g_value_get_object (value));
372 if (contact)
373 g_object_ref (contact);
374
375 if (e_minicard->contact)
376 g_object_unref (e_minicard->contact);
377
378 e_minicard->contact = contact;
379
380 remodel (e_minicard);
381 e_canvas_item_request_reflow (item);
382 e_minicard->changed = FALSE;
383 break;
384 default:
385 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
386 break;
387 }
388 }
389
390 static void
391 e_minicard_get_property (GObject *object,
392 guint property_id,
393 GValue *value,
394 GParamSpec *pspec)
395 {
396 EMinicard *e_minicard;
397
398 e_minicard = E_MINICARD (object);
399
400 switch (property_id) {
401 case PROP_WIDTH:
402 g_value_set_double (value, e_minicard->width);
403 break;
404 case PROP_HEIGHT:
405 g_value_set_double (value, e_minicard->height);
406 break;
407 case PROP_HAS_FOCUS:
408 g_value_set_int (value, e_minicard->has_focus ? E_FOCUS_CURRENT : E_FOCUS_NONE);
409 break;
410 case PROP_SELECTED:
411 g_value_set_boolean (value, e_minicard->selected);
412 break;
413 case PROP_HAS_CURSOR:
414 g_value_set_boolean (value, e_minicard->has_cursor);
415 break;
416 case PROP_EDITABLE:
417 g_value_set_boolean (value, e_minicard->editable);
418 break;
419 case PROP_CONTACT:
420 g_value_set_object (value, e_minicard->contact);
421 break;
422 default:
423 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
424 break;
425 }
426 }
427
428 static void
429 e_minicard_dispose (GObject *object)
430 {
431 EMinicard *e_minicard;
432
433 g_return_if_fail (object != NULL);
434 g_return_if_fail (E_IS_MINICARD (object));
435
436 e_minicard = E_MINICARD (object);
437
438 if (e_minicard->fields) {
439 g_list_foreach (e_minicard->fields, (GFunc) e_minicard_field_destroy, NULL);
440 g_list_free (e_minicard->fields);
441 e_minicard->fields = NULL;
442 }
443
444 if (e_minicard->list_icon_pixbuf) {
445 g_object_unref (e_minicard->list_icon_pixbuf);
446 e_minicard->list_icon_pixbuf = NULL;
447 }
448
449 /* Chain up to parent's dispose() method. */
450 G_OBJECT_CLASS (e_minicard_parent_class)->dispose (object);
451 }
452
453 static void
454 e_minicard_finalize (GObject *object)
455 {
456 EMinicard *e_minicard;
457
458 g_return_if_fail (object != NULL);
459 g_return_if_fail (E_IS_MINICARD (object));
460
461 e_minicard = E_MINICARD (object);
462
463 if (e_minicard->contact) {
464 g_object_unref (e_minicard->contact);
465 e_minicard->contact = NULL;
466 }
467
468 if (e_minicard->list_icon_pixbuf) {
469 g_object_unref (e_minicard->list_icon_pixbuf);
470 e_minicard->list_icon_pixbuf = NULL;
471 }
472
473 /* Chain up to parent's finalize() method. */
474 G_OBJECT_CLASS (e_minicard_parent_class)->finalize (object);
475 }
476
477 static void
478 e_minicard_style_set (EMinicard *minicard,
479 GtkStyle *previous_style)
480 {
481 GnomeCanvasItem *item = GNOME_CANVAS_ITEM (minicard);
482
483 if ((item->flags & GNOME_CANVAS_ITEM_REALIZED))
484 set_selected (minicard, minicard->selected);
485 }
486
487 static void
488 e_minicard_realize (GnomeCanvasItem *item)
489 {
490 EMinicard *e_minicard;
491 GnomeCanvasGroup *group;
492 GnomeCanvas *canvas;
493 GtkStyle *style;
494
495 e_minicard = E_MINICARD (item);
496 group = GNOME_CANVAS_GROUP (item);
497
498 canvas = GNOME_CANVAS_ITEM (item)->canvas;
499 style = gtk_widget_get_style (GTK_WIDGET (canvas));
500
501 GNOME_CANVAS_ITEM_CLASS (e_minicard_parent_class)->realize (item);
502
503 e_minicard->rect = gnome_canvas_item_new (
504 group,
505 gnome_canvas_rect_get_type (),
506 "x1", (gdouble) 0,
507 "y1", (gdouble) 0,
508 "x2", (gdouble) MAX (e_minicard->width - 1, 0),
509 "y2", (gdouble) MAX (e_minicard->height - 1, 0),
510 "outline_color", NULL,
511 NULL);
512
513 e_minicard->header_rect = gnome_canvas_item_new (
514 group,
515 gnome_canvas_rect_get_type (),
516 "x1", (gdouble) 2,
517 "y1", (gdouble) 2,
518 "x2", (gdouble) MAX (e_minicard->width - 3, 0),
519 "y2", (gdouble) MAX (e_minicard->height - 3, 0),
520 "fill_color_gdk", &style->bg[GTK_STATE_NORMAL],
521 NULL);
522
523 e_minicard->header_text = gnome_canvas_item_new (
524 group,
525 e_text_get_type (),
526 "width", (gdouble) MAX (e_minicard->width - 12, 0),
527 "clip", TRUE,
528 "use_ellipsis", TRUE,
529 "fill_color_gdk", &style->fg[GTK_STATE_NORMAL],
530 "text", "",
531 NULL);
532
533 e_canvas_item_move_absolute (e_minicard->header_text, 6, 6);
534
535 e_minicard->list_icon = gnome_canvas_item_new (
536 group,
537 gnome_canvas_pixbuf_get_type (),
538 "pixbuf", e_minicard->list_icon_pixbuf,
539 NULL);
540
541 set_selected (e_minicard, e_minicard->selected);
542
543 remodel (e_minicard);
544 e_canvas_item_request_reflow (item);
545 }
546
547 void
548 e_minicard_activate_editor (EMinicard *minicard)
549 {
550 g_return_if_fail (E_IS_MINICARD (minicard));
551
552 g_signal_emit (minicard, signals[OPEN_CONTACT], 0, minicard->contact);
553 }
554
555 static gboolean
556 e_minicard_event (GnomeCanvasItem *item,
557 GdkEvent *event)
558 {
559 EMinicard *e_minicard;
560
561 e_minicard = E_MINICARD (item);
562
563 switch (event->type) {
564 case GDK_FOCUS_CHANGE:
565 {
566 GdkEventFocus *focus_event = (GdkEventFocus *) event;
567 d (g_print ("%s: GDK_FOCUS_CHANGE: %s\n", G_STRFUNC, focus_event->in?"in":"out"));
568 if (focus_event->in) {
569 /* Chris: When EMinicard gets the cursor, if it doesn't have the focus, it should take it. */
570 e_minicard->has_focus = TRUE;
571 if (!e_minicard->selected) {
572 e_minicard_selected (e_minicard, event);
573 }
574 }
575 else {
576 e_minicard->has_focus = FALSE;
577 }
578 }
579 break;
580 case GDK_BUTTON_PRESS: {
581 if (1 <= event->button.button && event->button.button <= 2) {
582 gint ret_val = e_minicard_selected (e_minicard, event);
583 GdkEventMask mask = ((1 << (4 + event->button.button)) |
584 GDK_POINTER_MOTION_MASK |
585 GDK_BUTTON_PRESS_MASK |
586 GDK_BUTTON_RELEASE_MASK);
587
588 e_canvas_item_grab_focus (item, TRUE);
589
590 if (gnome_canvas_item_grab (GNOME_CANVAS_ITEM (e_minicard),
591 mask, NULL, event->button.time)) {
592 return FALSE;
593 }
594 gtk_grab_add (GTK_WIDGET (GNOME_CANVAS_ITEM (e_minicard)->canvas));
595 e_minicard->button_x = event->button.x;
596 e_minicard->button_y = event->button.y;
597 e_minicard->drag_button = event->button.button;
598 e_minicard->drag_button_down = TRUE;
599 return ret_val;
600 } else if (event->button.button == 3) {
601 gint ret_val = e_minicard_selected (e_minicard, event);
602 if (ret_val != 0)
603 return ret_val;
604 }
605 break;
606 }
607 case GDK_BUTTON_RELEASE:
608 e_minicard_selected (e_minicard, event);
609 if (e_minicard->drag_button == event->button.button) {
610 e_minicard->drag_button = 0;
611 e_minicard->drag_button_down = FALSE;
612 e_minicard->button_x = -1;
613 e_minicard->button_y = -1;
614
615 if (gtk_widget_has_grab (GTK_WIDGET (GNOME_CANVAS_ITEM (e_minicard)->canvas))) {
616 gtk_grab_remove (GTK_WIDGET (GNOME_CANVAS_ITEM (e_minicard)->canvas));
617 gnome_canvas_item_ungrab (GNOME_CANVAS_ITEM (e_minicard), event->button.time);
618 }
619 }
620 break;
621 case GDK_MOTION_NOTIFY:
622 if (e_minicard->drag_button_down && event->motion.state & GDK_BUTTON1_MASK) {
623 if (MAX (abs (e_minicard->button_x - event->motion.x),
624 abs (e_minicard->button_y - event->motion.y)) > 3) {
625 gint ret_val;
626
627 ret_val = e_minicard_drag_begin (e_minicard, event);
628
629 e_minicard->drag_button_down = FALSE;
630
631 return ret_val;
632 }
633 }
634 break;
635 case GDK_2BUTTON_PRESS:
636 if (event->button.button == 1 && E_IS_MINICARD_VIEW (item->parent)) {
637 e_minicard_activate_editor (e_minicard);
638 return TRUE;
639 }
640 break;
641 case GDK_KEY_PRESS:
642 if (event->key.keyval == GDK_KEY_Tab ||
643 event->key.keyval == GDK_KEY_KP_Tab ||
644 event->key.keyval == GDK_KEY_ISO_Left_Tab) {
645
646 EMinicardView *view = E_MINICARD_VIEW (item->parent);
647 EReflow *reflow = E_REFLOW (view);
648
649 if (reflow == NULL) {
650 return FALSE;
651 }
652
653 if (event->key.state & GDK_SHIFT_MASK) {
654 if (event->key.state & GDK_CONTROL_MASK) {
655 return FALSE;
656 }
657 else {
658 gint row_count = e_selection_model_row_count (reflow->selection);
659 gint model_index = e_selection_model_cursor_row (reflow->selection);
660 gint view_index = e_sorter_model_to_sorted (reflow->selection->sorter, model_index);
661
662 if (view_index == 0)
663 view_index = row_count - 1;
664 else
665 view_index--;
666
667 model_index = e_sorter_sorted_to_model (E_SORTER (reflow->sorter), view_index);
668 if (reflow->items[model_index] == NULL) {
669 reflow->items[model_index] = e_reflow_model_incarnate (reflow->model, model_index, GNOME_CANVAS_GROUP (reflow));
670 g_object_set (
671 reflow->items[model_index],
672 "width", (gdouble) reflow->column_width,
673 NULL);
674
675 }
676 e_canvas_item_grab_focus (reflow->items[model_index], FALSE);
677 return TRUE;
678 }
679 }
680 else {
681 if (event->key.state & GDK_CONTROL_MASK) {
682 return FALSE;
683 }
684 else {
685 gint row_count = e_selection_model_row_count (reflow->selection);
686 gint model_index = e_selection_model_cursor_row (reflow->selection);
687 gint view_index = e_sorter_model_to_sorted (reflow->selection->sorter, model_index);
688
689 if (view_index == row_count - 1)
690 view_index = 0;
691 else
692 view_index++;
693
694 model_index = e_sorter_sorted_to_model (E_SORTER (reflow->sorter), view_index);
695 if (reflow->items[model_index] == NULL) {
696 reflow->items[model_index] = e_reflow_model_incarnate (reflow->model, model_index, GNOME_CANVAS_GROUP (reflow));
697 g_object_set (
698 reflow->items[model_index],
699 "width", (gdouble) reflow->column_width,
700 NULL);
701
702 }
703 e_canvas_item_grab_focus (reflow->items[model_index], FALSE);
704 return TRUE;
705 }
706 }
707 }
708 else if (event->key.keyval == GDK_KEY_Return ||
709 event->key.keyval == GDK_KEY_KP_Enter) {
710 e_minicard_activate_editor (e_minicard);
711 return TRUE;
712 }
713 break;
714 default:
715 break;
716 }
717
718 return FALSE;
719 }
720
721 static void
722 e_minicard_resize_children (EMinicard *e_minicard)
723 {
724 GList *list;
725 gboolean is_list = GPOINTER_TO_INT (e_contact_get (e_minicard->contact, E_CONTACT_IS_LIST));
726
727 if (e_minicard->header_text) {
728 gnome_canvas_item_set (
729 e_minicard->header_text,
730 "width", ((gdouble) e_minicard->width - 12
731 - (is_list ? e_minicard->list_icon_size : 0.0)),
732 NULL);
733 }
734 if (e_minicard->list_icon) {
735 e_canvas_item_move_absolute (
736 e_minicard->list_icon,
737 e_minicard->width - e_minicard->list_icon_size - 3,
738 3);
739 }
740 for (list = e_minicard->fields; list; list = g_list_next (list)) {
741 gnome_canvas_item_set (
742 E_MINICARD_FIELD (list->data)->label,
743 "width", (gdouble) e_minicard->width - 4.0,
744 NULL);
745 }
746 }
747
748 static void
749 add_field (EMinicard *e_minicard,
750 EContactField field,
751 gdouble left_width)
752 {
753 GnomeCanvasItem *new_item;
754 GnomeCanvasGroup *group;
755 EMinicardField *minicard_field;
756 gchar *name;
757 gchar *string;
758 gboolean is_rtl = (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL);
759
760 group = GNOME_CANVAS_GROUP (e_minicard);
761
762 name = g_strdup_printf ("%s:", e_contact_pretty_name (field));
763 string = e_contact_get (e_minicard->contact, field);
764
765 new_item = e_minicard_label_new (group);
766
767 if (e_minicard->contact && e_contact_get (e_minicard->contact, E_CONTACT_IS_LIST))
768 gnome_canvas_item_set (
769 new_item,
770 "fieldname", is_rtl ? "" : string,
771 "field", is_rtl ? string : "",
772 "max_field_name_length", left_width,
773 "editable", FALSE /* e_minicard->editable */,
774 "width", e_minicard->width - 4.0,
775 NULL);
776 else
777 gnome_canvas_item_set (
778 new_item,
779 "fieldname", is_rtl ? string : name,
780 "field", is_rtl ? name : string,
781 "max_field_name_length", left_width,
782 "editable", FALSE /* e_minicard->editable */,
783 "width", e_minicard->width - 4.0,
784 NULL);
785
786 #ifdef notyet
787 g_object_set (
788 E_MINICARD_LABEL (new_item)->field,
789 "allow_newlines", e_card_simple_get_allow_newlines (e_minicard->contact, field),
790 NULL);
791 #endif
792 g_object_set_data (
793 G_OBJECT (E_MINICARD_LABEL (new_item)->field),
794 "EMinicard:field",
795 GINT_TO_POINTER (field));
796
797 minicard_field = g_new (EMinicardField, 1);
798 minicard_field->field = field;
799 minicard_field->label = new_item;
800
801 e_minicard->fields = g_list_append (e_minicard->fields, minicard_field);
802 e_canvas_item_move_absolute (new_item, 2, e_minicard->height);
803 g_free (name);
804 g_free (string);
805 }
806
807 static const gchar *
808 get_email_location (EVCardAttribute *attr)
809 {
810 gint i;
811
812 for (i = 0; i < G_N_ELEMENTS (common_location); i++) {
813 if (e_vcard_attribute_has_type (attr, common_location[i].name))
814 return _(common_location[i].pretty_name);
815 }
816
817 return _("Other Email");
818 }
819
820 static void
821 add_email_field (EMinicard *e_minicard,
822 GList *email_list,
823 gdouble left_width,
824 gint limit,
825 gboolean is_list)
826 {
827 GnomeCanvasItem *new_item;
828 GnomeCanvasGroup *group;
829 EMinicardField *minicard_field;
830 gchar *name;
831 GList *l, *le;
832 gint count =0;
833 gboolean is_rtl = (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL);
834 GList *emails = e_contact_get (e_minicard->contact, E_CONTACT_EMAIL);
835 group = GNOME_CANVAS_GROUP (e_minicard);
836
837 for (l = email_list, le = emails; l != NULL && count < limit && le != NULL; l = l->next, le = le->next) {
838 const gchar *tmp;
839 gchar *email = NULL;
840 gchar *string = NULL;
841 gchar *parsed_name = NULL;
842 gboolean parser_check;
843
844 /* do not use name for fields in the contact list */
845 if (is_list) {
846 name = (gchar *)"";
847 } else {
848 tmp = get_email_location ((EVCardAttribute *) l->data);
849 name = g_strdup_printf ("%s:", tmp);
850 }
851
852 parser_check = eab_parse_qp_email ((const gchar *) le->data, &parsed_name, &email);
853 if (parser_check) {
854 /* if true, we had a quoted printable mail address */
855 string = g_strdup_printf ("%s <%s>", parsed_name, email);
856 } else {
857 /* we got a NON-quoted printable string */
858 string = g_strdup (le->data);
859 }
860
861 new_item = e_minicard_label_new (group);
862
863 gnome_canvas_item_set (
864 new_item,
865 "fieldname", is_rtl ? string : name,
866 "field", is_rtl ? name : string,
867 "max_field_name_length", left_width,
868 "editable", FALSE /* e_minicard->editable */,
869 "width", e_minicard->width - 4.0,
870 NULL);
871
872 #ifdef notyet
873 g_object_set (
874 E_MINICARD_LABEL (new_item)->field,
875 "allow_newlines", e_card_simple_get_allow_newlines (e_minicard->contact, field),
876 NULL);
877 #endif
878 g_object_set_data (
879 G_OBJECT (E_MINICARD_LABEL (new_item)->field),
880 "EMinicard:field",
881 GINT_TO_POINTER (E_CONTACT_EMAIL));
882
883 minicard_field = g_new (EMinicardField, 1);
884 minicard_field->field = E_CONTACT_EMAIL;
885 minicard_field->label = new_item;
886
887 e_minicard->fields = g_list_append (e_minicard->fields, minicard_field);
888 e_canvas_item_move_absolute (new_item, 2, e_minicard->height);
889 count++;
890 if (!is_list)
891 g_free (name);
892 g_free (string);
893 g_free (parsed_name);
894 g_free (email);
895 }
896 g_list_foreach (emails, (GFunc) g_free, NULL);
897 g_list_free (emails);
898 }
899
900 static gint
901 get_left_width (EMinicard *e_minicard,
902 gboolean is_list)
903 {
904 gchar *name;
905 EContactField field;
906 gint width = -1;
907 PangoLayout *layout;
908
909 if (is_list)
910 return 0;
911
912 layout = gtk_widget_create_pango_layout (GTK_WIDGET (GNOME_CANVAS_ITEM (e_minicard)->canvas), "");
913 for (field = E_CONTACT_FULL_NAME; field != E_CONTACT_LAST_SIMPLE_STRING; field++) {
914 gint this_width;
915
916 if (field == E_CONTACT_FAMILY_NAME || field == E_CONTACT_GIVEN_NAME)
917 continue;
918
919 name = g_strdup_printf ("%s:", e_contact_pretty_name (field));
920 pango_layout_set_text (layout, name, -1);
921 pango_layout_get_pixel_size (layout, &this_width, NULL);
922 if (width < this_width)
923 width = this_width;
924 g_free (name);
925 }
926 g_object_unref (layout);
927 return width;
928 }
929
930 static void
931 remodel (EMinicard *e_minicard)
932 {
933 GnomeCanvasItem *item = GNOME_CANVAS_ITEM (e_minicard);
934 gint count = 0;
935
936 if (!(item->flags & GNOME_CANVAS_ITEM_REALIZED))
937 return;
938
939 if (e_minicard->contact) {
940 EContactField field;
941 GList *list;
942 gchar *file_as;
943 gint left_width = -1;
944 gboolean is_list = FALSE;
945 gboolean email_rendered = FALSE;
946 gboolean has_voice = FALSE, has_fax = FALSE;
947
948 if (e_minicard->header_text) {
949 file_as = e_contact_get (e_minicard->contact, E_CONTACT_FILE_AS);
950 gnome_canvas_item_set (
951 e_minicard->header_text,
952 "text", file_as ? file_as : "",
953 NULL);
954 g_free (file_as);
955 }
956
957 if (e_minicard->contact && e_contact_get (e_minicard->contact, E_CONTACT_IS_LIST))
958 is_list = TRUE;
959
960 if (is_list)
961 gnome_canvas_item_show (e_minicard->list_icon);
962 else
963 gnome_canvas_item_hide (e_minicard->list_icon);
964
965 list = e_minicard->fields;
966 e_minicard->fields = NULL;
967
968 for (field = E_CONTACT_FULL_NAME; field != (E_CONTACT_LAST_SIMPLE_STRING -1) && count < 5; field++) {
969 EMinicardField *minicard_field = NULL;
970 gboolean is_email = FALSE;
971
972 if (field == E_CONTACT_FAMILY_NAME || field == E_CONTACT_GIVEN_NAME ||
973 (has_voice && field == E_CONTACT_PHONE_OTHER) ||
974 (has_fax && field == E_CONTACT_PHONE_OTHER_FAX))
975 continue;
976
977 if (field == E_CONTACT_FULL_NAME && is_list)
978 continue;
979
980 if (field == E_CONTACT_EMAIL_1 || field == E_CONTACT_EMAIL_2 || field == E_CONTACT_EMAIL_3 || field == E_CONTACT_EMAIL_4) {
981 if (email_rendered)
982 continue;
983 email_rendered = TRUE;
984 is_email = TRUE;
985 }
986
987 if (list)
988 minicard_field = list->data;
989 if (minicard_field && minicard_field->field == field) {
990 GList *this_list = list;
991 gchar *string;
992
993 string = e_contact_get (e_minicard->contact, field);
994 if (string && *string) {
995 e_minicard->fields = g_list_append (e_minicard->fields, minicard_field);
996 g_object_set (
997 minicard_field->label,
998 "field", string,
999 NULL);
1000 count++;
1001 } else {
1002 e_minicard_field_destroy (minicard_field);
1003 }
1004 list = g_list_delete_link (list, this_list);
1005 g_free (string);
1006 } else {
1007 gchar *string;
1008 if (left_width == -1) {
1009 left_width = get_left_width (e_minicard, is_list);
1010 }
1011
1012 if (is_email) {
1013 GList *email;
1014 gint limit;
1015
1016 limit = 5 - count;
1017 email = e_contact_get_attributes (e_minicard->contact, E_CONTACT_EMAIL);
1018 add_email_field (e_minicard, email, left_width, limit, is_list);
1019 if (count + limit >5)
1020 count = 5;
1021 else
1022 count = count + g_list_length (email);
1023 g_list_free_full (email, (GDestroyNotify) e_vcard_attribute_free);
1024 } else {
1025 string = e_contact_get (e_minicard->contact, field);
1026 if (string && *string) {
1027 add_field (e_minicard, field, left_width);
1028 count++;
1029
1030 has_voice = has_voice ||
1031 field == E_CONTACT_PHONE_BUSINESS ||
1032 field == E_CONTACT_PHONE_BUSINESS_2 ||
1033 field == E_CONTACT_PHONE_HOME ||
1034 field == E_CONTACT_PHONE_HOME_2;
1035 has_fax = has_fax ||
1036 field == E_CONTACT_PHONE_BUSINESS_FAX ||
1037 field == E_CONTACT_PHONE_HOME_FAX;
1038 }
1039 g_free (string);
1040 }
1041 }
1042 }
1043
1044 g_list_foreach (list, (GFunc) e_minicard_field_destroy, NULL);
1045 g_list_free (list);
1046 }
1047 }
1048
1049 static void
1050 e_minicard_reflow (GnomeCanvasItem *item,
1051 gint flags)
1052 {
1053 EMinicard *e_minicard = E_MINICARD (item);
1054
1055 if (item->flags & GNOME_CANVAS_ITEM_REALIZED) {
1056 GList *list;
1057 gdouble text_height;
1058 gint old_height;
1059
1060 old_height = e_minicard->height;
1061
1062 g_object_get (
1063 e_minicard->header_text,
1064 "text_height", &text_height,
1065 NULL);
1066
1067 e_minicard->height = text_height + 10.0;
1068
1069 gnome_canvas_item_set (
1070 e_minicard->header_rect,
1071 "y2", text_height + 9.0,
1072 NULL);
1073
1074 for (list = e_minicard->fields; list; list = g_list_next (list)) {
1075 EMinicardField *field = E_MINICARD_FIELD (list->data);
1076 /* Why not use the item that is passed in? */
1077 GnomeCanvasItem *item = field->label;
1078 g_object_get (
1079 item,
1080 "height", &text_height,
1081 NULL);
1082 e_canvas_item_move_absolute (item, 2, e_minicard->height);
1083 e_minicard->height += text_height;
1084 }
1085 e_minicard->height += 2;
1086
1087 gnome_canvas_item_set (
1088 e_minicard->rect,
1089 "x2", (gdouble) e_minicard->width - 1.0,
1090 "y2", (gdouble) e_minicard->height - 1.0,
1091 NULL);
1092 gnome_canvas_item_set (
1093 e_minicard->header_rect,
1094 "x2", (gdouble) e_minicard->width - 3.0,
1095 NULL);
1096
1097 if (old_height != e_minicard->height)
1098 e_canvas_item_request_parent_reflow (item);
1099 }
1100 }
1101
1102 const gchar *
1103 e_minicard_get_card_id (EMinicard *minicard)
1104 {
1105 g_return_val_if_fail (minicard != NULL, NULL);
1106 g_return_val_if_fail (E_IS_MINICARD (minicard), NULL);
1107
1108 if (minicard->contact) {
1109 return e_contact_get_const (minicard->contact, E_CONTACT_UID);
1110 } else {
1111 return "";
1112 }
1113 }
1114
1115 gint
1116 e_minicard_compare (EMinicard *minicard1,
1117 EMinicard *minicard2)
1118 {
1119 gint cmp = 0;
1120
1121 g_return_val_if_fail (minicard1 != NULL, 0);
1122 g_return_val_if_fail (E_IS_MINICARD (minicard1), 0);
1123 g_return_val_if_fail (minicard2 != NULL, 0);
1124 g_return_val_if_fail (E_IS_MINICARD (minicard2), 0);
1125
1126 if (minicard1->contact && minicard2->contact) {
1127 gchar *file_as1, *file_as2;
1128 g_object_get (
1129 minicard1->contact,
1130 "file_as", &file_as1,
1131 NULL);
1132 g_object_get (
1133 minicard2->contact,
1134 "file_as", &file_as2,
1135 NULL);
1136
1137 if (file_as1 && file_as2)
1138 cmp = g_utf8_collate (file_as1, file_as2);
1139 else if (file_as1)
1140 cmp = -1;
1141 else if (file_as2)
1142 cmp = 1;
1143 else
1144 cmp = strcmp (e_minicard_get_card_id (minicard1), e_minicard_get_card_id (minicard2));
1145
1146 g_free (file_as1);
1147 g_free (file_as2);
1148 }
1149
1150 return cmp;
1151 }
1152
1153 gint
1154 e_minicard_selected (EMinicard *minicard,
1155 GdkEvent *event)
1156 {
1157 gint ret_val = 0;
1158 GnomeCanvasItem *item = GNOME_CANVAS_ITEM (minicard);
1159 if (item->parent) {
1160 guint signal_id = g_signal_lookup ("selection_event", G_OBJECT_TYPE (item->parent));
1161 /* We should probably check the signature here, but I
1162 * don't think it's worth the time required to code
1163 * it.
1164 */
1165 if (signal_id != 0) {
1166 g_signal_emit (
1167 item->parent,
1168 signal_id, 0,
1169 item, event, &ret_val);
1170 }
1171 }
1172 return ret_val;
1173 }
1174
1175 static gint
1176 e_minicard_drag_begin (EMinicard *minicard,
1177 GdkEvent *event)
1178 {
1179 gint ret_val = 0;
1180 GnomeCanvasItem *parent;
1181 g_signal_emit (
1182 minicard,
1183 signals[DRAG_BEGIN], 0,
1184 event, &ret_val);
1185
1186 parent = GNOME_CANVAS_ITEM (minicard)->parent;
1187 if (parent && E_IS_REFLOW (parent)) {
1188 E_REFLOW (parent)->maybe_in_drag = FALSE;
1189 }
1190 return ret_val;
1191 }